@@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+80
@@ -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>
|
||||
+26
@@ -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;
|
||||
}
|
||||
+25
@@ -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();
|
||||
});
|
||||
});
|
||||
+101
@@ -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':
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user