feat: group actions (transfer-clients) (#1056)

Fixes: #1055
This commit is contained in:
Karan Takalkar
2020-07-10 15:45:22 +05:30
committed by GitHub
parent 24c9e04c09
commit 11d74bd665
11 changed files with 260 additions and 4 deletions
@@ -30,6 +30,7 @@ export class GroupActionsResolver implements Resolve<Object> {
switch (actionName) {
case 'Attendance':
case 'Manage Members':
case 'Transfer Clients':
return this.groupsService.getGroupData(groupId);
case 'Assign Staff':
return this.groupsService.getGroupData(groupId, 'true');
@@ -6,3 +6,4 @@
<mifosx-manage-group-members *ngIf="actions['Manage Members']"></mifosx-manage-group-members>
<mifosx-edit-group-meeting *ngIf="actions['Edit Meeting']"></mifosx-edit-group-meeting>
<mifosx-edit-group-meeting-schedule *ngIf="actions['Edit Meeting Schedule']"></mifosx-edit-group-meeting-schedule>
<mifosx-group-transfer-clients *ngIf="actions['Transfer Clients']"></mifosx-group-transfer-clients>
@@ -22,6 +22,7 @@ export class GroupActionsComponent {
'Manage Members': boolean
'Edit Meeting': boolean
'Edit Meeting Schedule': boolean
'Transfer Clients': boolean
} = {
'Assign Staff': false,
'Close': false,
@@ -30,7 +31,8 @@ export class GroupActionsComponent {
'Attendance': false,
'Manage Members': false,
'Edit Meeting': false,
'Edit Meeting Schedule': false
'Edit Meeting Schedule': false,
'Transfer Clients': false
};
/**
@@ -0,0 +1,80 @@
<div class="container">
<mat-card>
<form [formGroup]="transferClientsForm">
<mat-card-content>
<div fxLayout="column">
<mat-form-field>
<mat-label>Select Client Members for Transfer</mat-label>
<mat-select required formControlName="clients" multiple>
<mat-option *ngFor="let member of clientMembers" [value]="{ id: member.id }">
{{ member.displayName }}
</mat-option>
</mat-select>
<mat-error *ngIf="transferClientsForm.controls.clients.hasError('required')">
Office is <strong>required</strong>
</mat-error>
</mat-form-field>
<mat-checkbox class="m-t-10 m-b-10" labelPosition="before" formControlName="inheritDestinationGroupLoanOfficer">
Inherit Group Loan Officer?
</mat-checkbox>
<mat-form-field>
<mat-label>Destination Group</mat-label>
<input matInput formControlName="destinationGroupId" [matAutocomplete]="groupsAutocomplete">
<mat-error *ngIf="transferClientsForm.controls.destinationGroupId.hasError('required')">
Destination Group is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<mat-autocomplete autoActiveFirstOption #groupsAutocomplete="matAutocomplete" [displayWith]="displayGroup">
<mat-option *ngFor="let group of groupsData" [value]="group">
{{ group.name }}
</mat-option>
</mat-autocomplete>
<div class="mat-table" *ngIf="transferClientsForm.get('destinationGroupId').value">
<div class="mat-header-row">
<div class="mat-header-cell">Destination Group Details</div>
</div>
<div class="mat-row">
<div class="mat-cell">Name</div>
<div class="mat-cell">{{transferClientsForm.get('destinationGroupId').value.name}}</div>
</div>
<div class="mat-row">
<div class="mat-cell">Id</div>
<div class="mat-cell">{{transferClientsForm.get('destinationGroupId').value.id}}</div>
</div>
<div class="mat-row">
<div class="mat-cell">Activation Date</div>
<div class="mat-cell">{{(transferClientsForm.get('destinationGroupId').value.activationDate | date) || 'Not Activated'}}</div>
</div>
<div class="mat-row">
<div class="mat-cell">Staff</div>
<div class="mat-cell">{{transferClientsForm.get('destinationGroupId').value.staffName || 'Unassigned'}}</div>
</div>
<div class="mat-row">
<div class="mat-cell">External Id</div>
<div class="mat-cell">{{transferClientsForm.get('destinationGroupId').value.externalId || 'Unassigned'}}</div>
</div>
</div>
</mat-card-content>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
<button mat-raised-button color="primary" [disabled]="!transferClientsForm.valid" (click)="submit()">Submit</button>
</mat-card-actions>
</form>
</mat-card>
</div>
@@ -0,0 +1,26 @@
.container {
max-width: 37rem;
}
.mat-table {
display: block;
font-family: Tahoma, Verdana;
width: 100%
}
.mat-row,
.mat-header-row {
display: flex;
border-bottom-width: 1px;
border-bottom-style: solid;
align-items: center;
min-height: 30px;
padding: 0 24px;
}
.mat-cell,
.mat-header-cell {
flex: 1;
overflow: hidden;
word-wrap: break-word;
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { GroupTransferClientsComponent } from './group-transfer-clients.component';
describe('GroupTransferClientsComponent', () => {
let component: GroupTransferClientsComponent;
let fixture: ComponentFixture<GroupTransferClientsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ GroupTransferClientsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(GroupTransferClientsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,101 @@
/** Angular Imports */
import { Component, OnInit, AfterViewInit } from '@angular/core';
import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
/** Custom Services */
import { GroupsService } from 'app/groups/groups.service';
/**
* Group Transfer Clients component.
*/
@Component({
selector: 'mifosx-group-transfer-clients',
templateUrl: './group-transfer-clients.component.html',
styleUrls: ['./group-transfer-clients.component.scss']
})
export class GroupTransferClientsComponent implements OnInit, AfterViewInit {
/** Transfer Clients form. */
transferClientsForm: FormGroup;
/** Group Data */
groupData: any;
/** Group data. */
groupsData: any = [];
/** Staff data. */
staffData: any;
/** Group Members. */
clientMembers: any[] = [];
/**
* Retrieves the offices data from `resolve`.
* @param {FormBuilder} formBuilder Form Builder.
* @param {ActivatedRoute} route Activated Route.
* @param {Router} router Router for navigation
* @param {GroupsService} groupsService GroupsService.
*/
constructor(private formBuilder: FormBuilder,
private route: ActivatedRoute,
private router: Router,
private groupsService: GroupsService) {
this.route.data.subscribe((data: { groupActionData: any }) => {
this.groupData = data.groupActionData;
this.clientMembers = this.groupData.clientMembers;
});
}
ngOnInit() {
this.createTransferClientsForm();
}
/**
* Subscribes to Groups search filter:
*/
ngAfterViewInit() {
this.transferClientsForm.get('destinationGroupId').valueChanges.subscribe( (value: string) => {
if (value.length >= 2) {
this.groupsService.getFilteredGroups('name', 'ASC', value, this.groupData.officeId)
.subscribe( (data: any) => {
this.groupsData = data;
});
}
});
}
/**
* Creates the transfer clients form.
*/
createTransferClientsForm() {
this.transferClientsForm = this.formBuilder.group({
'clients': ['', Validators.required],
'inheritDestinationGroupLoanOfficer': [false],
'destinationGroupId': ['', Validators.required]
});
}
/**
* Displays Group name in form control input.
* @param {any} group Group data.
* @returns {string} Group name if valid otherwise undefined.
*/
displayGroup(group: any): string | undefined {
return group ? group.name : undefined;
}
/**
* Submits the group form and transfers the clients,
* if successful redirects to group.
*/
submit() {
const locale = 'en';
const data = {
...this.transferClientsForm.value,
destinationGroupId: this.transferClientsForm.get('destinationGroupId').value.id,
locale
};
this.groupsService.executeGroupCommand(this.groupData.id, 'transferClients', data).subscribe(() => {
this.router.navigate(['../../'], { relativeTo: this.route });
});
}
}
@@ -61,7 +61,7 @@
<i class="fa fa-edit"></i>Edit</button>
<button mat-raised-button *mifosxHasPermission="'CREATE_CLIENT'">
<i class="fa fa-plus"></i>Add Clients</button>
<button mat-raised-button *mifosxHasPermission="'ASSOCIATECLIENTS_GROUP'">
<button mat-raised-button *mifosxHasPermission="'ASSOCIATECLIENTS_GROUP'" (click)="doAction('Transfer Clients')">
<i class="fa fa-exchange"></i>Transfer Clients</button>
<button mat-raised-button *mifosxHasPermission="'TRANSFERCLIENTS_GROUP'" (click)="doAction('Manage Members')">
<i class="fa fa-user"></i>Manage Members</button>
@@ -51,6 +51,7 @@ export class GroupsViewComponent {
case 'Attach Meeting':
case 'Attendance':
case 'Manage Members':
case 'Transfer Clients':
this.router.navigate([`actions/${name}`], { relativeTo: this.route });
break;
case 'Edit Meeting':
+3 -1
View File
@@ -31,6 +31,7 @@ import { GroupAttendanceComponent } from './groups-view/group-actions/group-atte
import { ManageGroupMembersComponent } from './groups-view/group-actions/manage-group-members/manage-group-members.component';
import { EditGroupMeetingComponent } from './groups-view/group-actions/edit-group-meeting/edit-group-meeting.component';
import { EditGroupMeetingScheduleComponent } from './groups-view/group-actions/edit-group-meeting-schedule/edit-group-meeting-schedule.component';
import { GroupTransferClientsComponent } from './groups-view/group-actions/group-transfer-clients/group-transfer-clients.component';
/**
* Groups Module
@@ -66,7 +67,8 @@ import { EditGroupMeetingScheduleComponent } from './groups-view/group-actions/e
GroupAttendanceComponent,
ManageGroupMembersComponent,
EditGroupMeetingComponent,
EditGroupMeetingScheduleComponent
EditGroupMeetingScheduleComponent,
GroupTransferClientsComponent
],
entryComponents: [
UnassignRoleDialogComponent,
+18 -1
View File
@@ -19,6 +19,23 @@ export class GroupsService {
*/
constructor(private http: HttpClient) { }
/**
* @param {string} orderBy Property by which entries should be sorted.
* @param {string} sortOrder Sort order: ascending or descending.
* @param {string} name Filter value for groups names.
* @returns {Observable<any>} Groups.
*/
getFilteredGroups(orderBy: string, sortOrder: string, name: string, officeId?: any): Observable<any> {
let httpParams = new HttpParams()
.set('name', name)
.set('sortOrder', sortOrder)
.set('orderBy', orderBy);
if (officeId) {
httpParams = httpParams.set('officeId', officeId);
}
return this.http.get('/groups', { params: httpParams });
}
/**
* @param {any} filterBy Properties by which entries should be filtered.
* @param {string} orderBy Property by which entries should be sorted.
@@ -27,7 +44,7 @@ export class GroupsService {
* @param {number} limit Number of entries within the page.
* @returns {Observable<any>} Groups.
*/
getGroups(filterBy: any, orderBy: string, sortOrder: string, offset: number, limit: number): Observable<any> {
getGroups(filterBy: any, orderBy: string, sortOrder: string, offset?: number, limit?: number): Observable<any> {
let httpParams = new HttpParams()
.set('offset', offset.toString())
.set('limit', limit.toString())