feat: group actions (manage-members) (#1049)

Fixes: #1048
This commit is contained in:
Karan Takalkar
2020-07-09 18:52:55 +05:30
committed by GitHub
parent 66e53e97a0
commit 9f9bbc775a
12 changed files with 226 additions and 6 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ export class ClientsService {
*/
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()
.set('displayName', displayName)
.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');
switch (actionName) {
case 'Attendance':
case 'Manage Members':
return this.groupsService.getGroupData(groupId);
case 'Assign Staff':
return this.groupsService.getGroupData(groupId, 'true');
@@ -3,3 +3,4 @@
<mifosx-activate-group *ngIf="actions['Activate']"></mifosx-activate-group>
<mifosx-attach-group-meeting *ngIf="actions['Attach Meeting']"></mifosx-attach-group-meeting>
<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
'Attach Meeting': boolean
'Attendance': boolean
'Manage Members': boolean
} = {
'Assign Staff': false,
'Close': false,
'Activate': false,
'Attach Meeting': false,
'Attendance': false
'Attendance': false,
'Manage Members': false
};
/**
@@ -37,7 +37,7 @@ export class GroupAttendanceComponent implements OnInit {
meetingDate = new FormControl();
/** Meeting Dates Data */
meetingDates: any[];
/** Data source for currencies table. */
/** Data source for client members table. */
dataSource: {}[];
/**
@@ -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>
@@ -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;
}
}
@@ -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();
});
});
@@ -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>
<button mat-raised-button *mifosxHasPermission="'ASSOCIATECLIENTS_GROUP'">
<i class="fa fa-exchange"></i>Transfer Clients</button>
<button mat-raised-button *mifosxHasPermission="'TRANSFERCLIENTS_GROUP'">
<i class="fa fa-user"></i>Manage Clients</button>
<button mat-raised-button *mifosxHasPermission="'TRANSFERCLIENTS_GROUP'" (click)="doAction('Manage Members')">
<i class="fa fa-user"></i>Manage Members</button>
<button mat-raised-button *ngIf="groupViewData.active" [matMenuTriggerFor]="LoanApplications">
<i class="fa fa-file"></i>Loan Applications</button>
@@ -50,6 +50,7 @@ export class GroupsViewComponent {
case 'Activate':
case 'Attach Meeting':
case 'Attendance':
case 'Manage Members':
this.router.navigate([`actions/${name}`], { relativeTo: this.route });
break;
case 'Edit':
+3 -1
View File
@@ -28,6 +28,7 @@ import { ActivateGroupComponent } from './groups-view/group-actions/activate-gro
import { EditGroupComponent } from './edit-group/edit-group.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 { ManageGroupMembersComponent } from './groups-view/group-actions/manage-group-members/manage-group-members.component';
/**
* Groups Module
@@ -60,7 +61,8 @@ import { GroupAttendanceComponent } from './groups-view/group-actions/group-atte
ActivateGroupComponent,
EditGroupComponent,
AttachGroupMeetingComponent,
GroupAttendanceComponent
GroupAttendanceComponent,
ManageGroupMembersComponent
],
entryComponents: [
UnassignRoleDialogComponent,