@@ -16,7 +16,7 @@ export class ClientsService {
|
|||||||
*/
|
*/
|
||||||
constructor(private http: HttpClient) { }
|
constructor(private http: HttpClient) { }
|
||||||
|
|
||||||
getFilteredClients(orderBy: string, sortOrder: string, orphansOnly: boolean, displayName: string, officeId: any): Observable<any> {
|
getFilteredClients(orderBy: string, sortOrder: string, orphansOnly: boolean, displayName: string, officeId?: any): Observable<any> {
|
||||||
let httpParams = new HttpParams()
|
let httpParams = new HttpParams()
|
||||||
.set('displayName', displayName)
|
.set('displayName', displayName)
|
||||||
.set('orphansOnly', orphansOnly.toString())
|
.set('orphansOnly', orphansOnly.toString())
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export class GroupActionsResolver implements Resolve<Object> {
|
|||||||
const groupId = route.paramMap.get('groupId') || route.parent.parent.paramMap.get('groupId');
|
const groupId = route.paramMap.get('groupId') || route.parent.parent.paramMap.get('groupId');
|
||||||
switch (actionName) {
|
switch (actionName) {
|
||||||
case 'Attendance':
|
case 'Attendance':
|
||||||
|
case 'Manage Members':
|
||||||
return this.groupsService.getGroupData(groupId);
|
return this.groupsService.getGroupData(groupId);
|
||||||
case 'Assign Staff':
|
case 'Assign Staff':
|
||||||
return this.groupsService.getGroupData(groupId, 'true');
|
return this.groupsService.getGroupData(groupId, 'true');
|
||||||
|
|||||||
@@ -3,3 +3,4 @@
|
|||||||
<mifosx-activate-group *ngIf="actions['Activate']"></mifosx-activate-group>
|
<mifosx-activate-group *ngIf="actions['Activate']"></mifosx-activate-group>
|
||||||
<mifosx-attach-group-meeting *ngIf="actions['Attach Meeting']"></mifosx-attach-group-meeting>
|
<mifosx-attach-group-meeting *ngIf="actions['Attach Meeting']"></mifosx-attach-group-meeting>
|
||||||
<mifosx-group-attendance *ngIf="actions['Attendance']"></mifosx-group-attendance>
|
<mifosx-group-attendance *ngIf="actions['Attendance']"></mifosx-group-attendance>
|
||||||
|
<mifosx-manage-group-members *ngIf="actions['Manage Members']"></mifosx-manage-group-members>
|
||||||
|
|||||||
@@ -19,12 +19,14 @@ export class GroupActionsComponent {
|
|||||||
'Activate': boolean
|
'Activate': boolean
|
||||||
'Attach Meeting': boolean
|
'Attach Meeting': boolean
|
||||||
'Attendance': boolean
|
'Attendance': boolean
|
||||||
|
'Manage Members': boolean
|
||||||
} = {
|
} = {
|
||||||
'Assign Staff': false,
|
'Assign Staff': false,
|
||||||
'Close': false,
|
'Close': false,
|
||||||
'Activate': false,
|
'Activate': false,
|
||||||
'Attach Meeting': false,
|
'Attach Meeting': false,
|
||||||
'Attendance': false
|
'Attendance': false,
|
||||||
|
'Manage Members': false
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ export class GroupAttendanceComponent implements OnInit {
|
|||||||
meetingDate = new FormControl();
|
meetingDate = new FormControl();
|
||||||
/** Meeting Dates Data */
|
/** Meeting Dates Data */
|
||||||
meetingDates: any[];
|
meetingDates: any[];
|
||||||
/** Data source for currencies table. */
|
/** Data source for client members table. */
|
||||||
dataSource: {}[];
|
dataSource: {}[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
<div class="container" fxLayout="row" fxLayoutGap="3%">
|
||||||
|
|
||||||
|
<mat-card fxFlex class="client-card" fxLayout="column" fxLayoutGap="2%">
|
||||||
|
|
||||||
|
<mat-form-field fxFlex="30%">
|
||||||
|
<mat-label>Add Clients</mat-label>
|
||||||
|
<input matInput [formControl]="clientChoice" [matAutocomplete]="clientsAutocomplete">
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-autocomplete autoActiveFirstOption #clientsAutocomplete="matAutocomplete" [displayWith]="displayClient">
|
||||||
|
<mat-option *ngFor="let client of clientsData" [value]="client">
|
||||||
|
{{ client.displayName }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-autocomplete>
|
||||||
|
|
||||||
|
<div class="mat-table">
|
||||||
|
<div class="mat-header-row">
|
||||||
|
<div class="mat-header-cell">Client Details</div>
|
||||||
|
<button mat-icon-button (click)="addClient()">
|
||||||
|
<fa-icon icon="plus"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="mat-row">
|
||||||
|
<div class="mat-cell">Name</div>
|
||||||
|
<div class="mat-cell">{{clientChoice.value.displayName}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="mat-row">
|
||||||
|
<div class="mat-cell">Id</div>
|
||||||
|
<div class="mat-cell">{{clientChoice.value.id}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="mat-row">
|
||||||
|
<div class="mat-cell">Office</div>
|
||||||
|
<div class="mat-cell">{{clientChoice.value.officeName}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
<mat-card fxFlex="40%">
|
||||||
|
|
||||||
|
<h3 matSubheader>Client Members</h3>
|
||||||
|
|
||||||
|
<mat-nav-list *ngIf="clientMembers?.length">
|
||||||
|
<div mat-list-item *ngFor="let client of clientMembers index as i">
|
||||||
|
<span matLine class="p-t-10">{{client.displayName}}</span>
|
||||||
|
<div fxFlex></div>
|
||||||
|
<button mat-icon-button color="warn" (click)="removeClient(i, client)">
|
||||||
|
<fa-icon icon="trash"></fa-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</mat-nav-list>
|
||||||
|
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
</div>
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
.container {
|
||||||
|
max-width: 50rem;
|
||||||
|
|
||||||
|
.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: 48px;
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-cell,
|
||||||
|
.mat-header-cell {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
padding-left: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.client-card {
|
||||||
|
max-height: 20rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ManageGroupMembersComponent } from './manage-group-members.component';
|
||||||
|
|
||||||
|
describe('ManageGroupMembersComponent', () => {
|
||||||
|
let component: ManageGroupMembersComponent;
|
||||||
|
let fixture: ComponentFixture<ManageGroupMembersComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ ManageGroupMembersComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ManageGroupMembersComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+98
@@ -0,0 +1,98 @@
|
|||||||
|
/** Angular Imports */
|
||||||
|
import { Component, OnInit, AfterViewInit } from '@angular/core';
|
||||||
|
import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms';
|
||||||
|
import { Router, ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
/** Custom Dialogs */
|
||||||
|
import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
|
||||||
|
|
||||||
|
/** Custom Services */
|
||||||
|
import { GroupsService } from 'app/groups/groups.service';
|
||||||
|
import { ClientsService } from 'app/clients/clients.service';
|
||||||
|
import { MatDialog } from '@angular/material';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'mifosx-manage-group-members',
|
||||||
|
templateUrl: './manage-group-members.component.html',
|
||||||
|
styleUrls: ['./manage-group-members.component.scss']
|
||||||
|
})
|
||||||
|
export class ManageGroupMembersComponent implements AfterViewInit {
|
||||||
|
|
||||||
|
/** Group Data */
|
||||||
|
groupData: any;
|
||||||
|
/** Client data. */
|
||||||
|
clientsData: any = [];
|
||||||
|
/** Client Members. */
|
||||||
|
clientMembers: any[] = [];
|
||||||
|
/** ClientChoice. */
|
||||||
|
clientChoice = new FormControl('');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches group action data from `resolve`
|
||||||
|
* @param {ActivatedRoute} route Activated Route
|
||||||
|
* @param {GroupsService} groupsService Groups Service
|
||||||
|
* @param {ClientsService} clientsService Clients Service
|
||||||
|
* @param {MatDialog} dialog Mat Dialog
|
||||||
|
*/
|
||||||
|
constructor(private route: ActivatedRoute,
|
||||||
|
private groupsService: GroupsService,
|
||||||
|
private clientsService: ClientsService,
|
||||||
|
public dialog: MatDialog) {
|
||||||
|
this.route.data.subscribe((data: { groupActionData: any }) => {
|
||||||
|
this.groupData = data.groupActionData;
|
||||||
|
this.clientMembers = data.groupActionData.clientMembers;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribes to Clients search filter:
|
||||||
|
*/
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.clientChoice.valueChanges.subscribe( (value: string) => {
|
||||||
|
if (value.length >= 2) {
|
||||||
|
this.clientsService.getFilteredClients('displayName', 'ASC', true, value, this.groupData.officeId)
|
||||||
|
.subscribe((data: any) => {
|
||||||
|
this.clientsData = data.pageItems;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add client.
|
||||||
|
*/
|
||||||
|
addClient() {
|
||||||
|
if (!this.clientMembers.includes(this.clientChoice.value)) {
|
||||||
|
this.groupsService.executeGroupCommand(this.groupData.id, 'associateClients', {clientMembers: [this.clientChoice.value.id]})
|
||||||
|
.subscribe(() => { this.clientMembers.push(this.clientChoice.value); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove client.
|
||||||
|
* @param index Client's array index.
|
||||||
|
*/
|
||||||
|
removeClient(index: number, client: any) {
|
||||||
|
const removeMemberDialogRef = this.dialog.open(DeleteDialogComponent, {
|
||||||
|
data: { deleteContext: `client member: ${client.displayName}` }
|
||||||
|
});
|
||||||
|
removeMemberDialogRef.afterClosed().subscribe((response: any) => {
|
||||||
|
if (response.delete) {
|
||||||
|
this.groupsService.executeGroupCommand(this.groupData.id, 'disassociateClients', {clientMembers: [client.id]})
|
||||||
|
.subscribe(() => { this.clientMembers.splice(index, 1); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays Client name in form control input.
|
||||||
|
* @param {any} client Client data.
|
||||||
|
* @returns {string} Client name if valid otherwise undefined.
|
||||||
|
*/
|
||||||
|
displayClient(client: any): string | undefined {
|
||||||
|
return client ? client.displayName : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -63,8 +63,8 @@
|
|||||||
<i class="fa fa-plus"></i>Add Clients</button>
|
<i class="fa fa-plus"></i>Add Clients</button>
|
||||||
<button mat-raised-button *mifosxHasPermission="'ASSOCIATECLIENTS_GROUP'">
|
<button mat-raised-button *mifosxHasPermission="'ASSOCIATECLIENTS_GROUP'">
|
||||||
<i class="fa fa-exchange"></i>Transfer Clients</button>
|
<i class="fa fa-exchange"></i>Transfer Clients</button>
|
||||||
<button mat-raised-button *mifosxHasPermission="'TRANSFERCLIENTS_GROUP'">
|
<button mat-raised-button *mifosxHasPermission="'TRANSFERCLIENTS_GROUP'" (click)="doAction('Manage Members')">
|
||||||
<i class="fa fa-user"></i>Manage Clients</button>
|
<i class="fa fa-user"></i>Manage Members</button>
|
||||||
|
|
||||||
<button mat-raised-button *ngIf="groupViewData.active" [matMenuTriggerFor]="LoanApplications">
|
<button mat-raised-button *ngIf="groupViewData.active" [matMenuTriggerFor]="LoanApplications">
|
||||||
<i class="fa fa-file"></i>Loan Applications</button>
|
<i class="fa fa-file"></i>Loan Applications</button>
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export class GroupsViewComponent {
|
|||||||
case 'Activate':
|
case 'Activate':
|
||||||
case 'Attach Meeting':
|
case 'Attach Meeting':
|
||||||
case 'Attendance':
|
case 'Attendance':
|
||||||
|
case 'Manage Members':
|
||||||
this.router.navigate([`actions/${name}`], { relativeTo: this.route });
|
this.router.navigate([`actions/${name}`], { relativeTo: this.route });
|
||||||
break;
|
break;
|
||||||
case 'Edit':
|
case 'Edit':
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import { ActivateGroupComponent } from './groups-view/group-actions/activate-gro
|
|||||||
import { EditGroupComponent } from './edit-group/edit-group.component';
|
import { EditGroupComponent } from './edit-group/edit-group.component';
|
||||||
import { AttachGroupMeetingComponent } from './groups-view/group-actions/attach-group-meeting/attach-group-meeting.component';
|
import { AttachGroupMeetingComponent } from './groups-view/group-actions/attach-group-meeting/attach-group-meeting.component';
|
||||||
import { GroupAttendanceComponent } from './groups-view/group-actions/group-attendance/group-attendance.component';
|
import { GroupAttendanceComponent } from './groups-view/group-actions/group-attendance/group-attendance.component';
|
||||||
|
import { ManageGroupMembersComponent } from './groups-view/group-actions/manage-group-members/manage-group-members.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Groups Module
|
* Groups Module
|
||||||
@@ -60,7 +61,8 @@ import { GroupAttendanceComponent } from './groups-view/group-actions/group-atte
|
|||||||
ActivateGroupComponent,
|
ActivateGroupComponent,
|
||||||
EditGroupComponent,
|
EditGroupComponent,
|
||||||
AttachGroupMeetingComponent,
|
AttachGroupMeetingComponent,
|
||||||
GroupAttendanceComponent
|
GroupAttendanceComponent,
|
||||||
|
ManageGroupMembersComponent
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
UnassignRoleDialogComponent,
|
UnassignRoleDialogComponent,
|
||||||
|
|||||||
Reference in New Issue
Block a user