diff --git a/src/app/groups/common-resolvers/group-actions.resolver.ts b/src/app/groups/common-resolvers/group-actions.resolver.ts index 2d5461227..aae98a13d 100644 --- a/src/app/groups/common-resolvers/group-actions.resolver.ts +++ b/src/app/groups/common-resolvers/group-actions.resolver.ts @@ -28,6 +28,8 @@ export class GroupActionsResolver implements Resolve { const actionName = route.paramMap.get('name'); const groupId = route.paramMap.get('groupId') || route.parent.parent.paramMap.get('groupId'); switch (actionName) { + case 'Attendance': + return this.groupsService.getGroupData(groupId); case 'Assign Staff': return this.groupsService.getGroupData(groupId, 'true'); case 'Close': diff --git a/src/app/groups/groups-view/group-actions/group-actions.component.html b/src/app/groups/groups-view/group-actions/group-actions.component.html index 8cca9392b..de39bdc29 100644 --- a/src/app/groups/groups-view/group-actions/group-actions.component.html +++ b/src/app/groups/groups-view/group-actions/group-actions.component.html @@ -2,3 +2,4 @@ + diff --git a/src/app/groups/groups-view/group-actions/group-actions.component.ts b/src/app/groups/groups-view/group-actions/group-actions.component.ts index f10016121..917eb6661 100644 --- a/src/app/groups/groups-view/group-actions/group-actions.component.ts +++ b/src/app/groups/groups-view/group-actions/group-actions.component.ts @@ -18,11 +18,13 @@ export class GroupActionsComponent { 'Close': boolean 'Activate': boolean 'Attach Meeting': boolean + 'Attendance': boolean } = { 'Assign Staff': false, 'Close': false, 'Activate': false, 'Attach Meeting': false, + 'Attendance': false }; /** diff --git a/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.html b/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.html new file mode 100644 index 000000000..bf1a45678 --- /dev/null +++ b/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.html @@ -0,0 +1,49 @@ +
+ + + + + Meeting Date + + + {{ date | date }} + + + Next Meeting on: {{ this.groupData.collectionMeetingCalendar.nextTenRecurringDates[0] | date }} + + + + + + + + + + + + + + + + + +
Name {{ member.clientId | find:membersData:'id':'displayName' }} Attendance + Present + Absent + Approved + Leave + Late + +
+ + + + + + +
+ +
diff --git a/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.scss b/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.scss new file mode 100644 index 000000000..d774f68da --- /dev/null +++ b/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.scss @@ -0,0 +1,3 @@ +.container { + max-width: 37rem; +} diff --git a/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.spec.ts b/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.spec.ts new file mode 100644 index 000000000..6898d6898 --- /dev/null +++ b/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GroupAttendanceComponent } from './group-attendance.component'; + +describe('GroupAttendanceComponent', () => { + let component: GroupAttendanceComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ GroupAttendanceComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(GroupAttendanceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.ts b/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.ts new file mode 100644 index 000000000..8707d0670 --- /dev/null +++ b/src/app/groups/groups-view/group-actions/group-attendance/group-attendance.component.ts @@ -0,0 +1,132 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { MatDialog } from '@angular/material'; +import { DatePipe } from '@angular/common'; +import { ActivatedRoute, Router } from '@angular/router'; +import { FormControl } from '@angular/forms'; + +/** Custom Services */ +import { GroupsService } from 'app/groups/groups.service'; + +/** Custom Dialogs */ +import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component'; + +/** Custom Models */ +import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base'; +import { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base'; + +/** + * Group Attendance component. + */ +@Component({ + selector: 'mifosx-group-attendance', + templateUrl: './group-attendance.component.html', + styleUrls: ['./group-attendance.component.scss'] +}) +export class GroupAttendanceComponent implements OnInit { + + /** Members data. */ + membersData: any; + /** Group Data */ + groupData: any; + /** Attendance Type Options */ + attendanceTypeOptions: any; + /** Columns to be displayed in member's attendance table. */ + displayedColumns: string[] = ['name', 'attendance']; + /** Start Date Form Control */ + meetingDate = new FormControl(); + /** Meeting Dates Data */ + meetingDates: any[]; + /** Data source for currencies table. */ + dataSource: {}[]; + + /** + * Retrieves the group members data from `resolve`. + * @param {ActivatedRoute} route Route + * @param {DatePipe} datePipe Date Pipe + * @param {Router} router Router + * @param {GroupsService} groupsService Groups Service + * @param {MatDialog} dialog Mat Dialog + */ + constructor(private route: ActivatedRoute, + private datePipe: DatePipe, + private router: Router, + private groupsService: GroupsService, + public dialog: MatDialog) { + this.route.data.subscribe(( data: { groupActionData: any }) => { + this.groupData = data.groupActionData; + this.membersData = data.groupActionData.clientMembers; + }); + } + + /** + * Sets the members table. + */ + ngOnInit() { + this.dataSource = this.membersData.map((member: any) => ({ clientId: member.id, attendanceType: 1 })); + this.meetingDates = this.groupData.collectionMeetingCalendar.recurringDates + .filter((date: any) => new Date(date).getTime() < new Date().getTime()); + this.getAttendanceOptions(); + } + + /** + * Gets attendance type options based on calendar id. + */ + getAttendanceOptions() { + this.groupsService.getMeetingsTemplate(this.groupData.id, this.groupData.collectionMeetingCalendar.id) + .subscribe((response: any) => { + this.attendanceTypeOptions = response.attendanceTypeOptions; + }); + } + + /** + * Edits a member's attendance + * @param {any} member Client Member + */ + editAttendance(member: any) { + const formfields: FormfieldBase[] = [ + new SelectBase({ + controlName: 'attendanceType', + label: 'Attendance', + value: member.attendanceType, + options: { label: 'value', value: 'id', data: this.attendanceTypeOptions }, + required: false + }), + ]; + const data = { + title: 'Assign Member Attendance', + layout: { addButtonText: 'Confirm' }, + formfields: formfields + }; + const memberAttendanceDialogRef = this.dialog.open(FormDialogComponent, { data }); + memberAttendanceDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + const updatedMemeber = { ...member, ...response.data.value }; + this.dataSource.splice(this.dataSource.indexOf(member), 1, updatedMemeber); + this.dataSource = this.dataSource.concat([]); + } + }); + } + + /** + * Assigns Client Members Attendance + */ + submit() { + // TODO: Update once language and date settings are setup + const locale = 'en'; + const dateFormat = 'dd MMMM yyyy'; + const prevMeetingDate: Date = new Date(this.meetingDate.value); + this.meetingDate.patchValue(this.datePipe.transform(prevMeetingDate, dateFormat)); + const data = { + meetingDate: this.meetingDate.value, + calendarId: this.groupData.collectionMeetingCalendar.id, + clientsAttendance: this.dataSource, + dateFormat, + locale + }; + this.groupsService.assignGroupAttendance(this.groupData.id, this.groupData.collectionMeetingCalendar.id, data).subscribe(() => { + this.router.navigate(['../../'], { relativeTo: this.route }); + }); + } + +} diff --git a/src/app/groups/groups-view/groups-view.component.html b/src/app/groups/groups-view/groups-view.component.html index 6aec9d8ac..e262c2a76 100644 --- a/src/app/groups/groups-view/groups-view.component.html +++ b/src/app/groups/groups-view/groups-view.component.html @@ -78,7 +78,7 @@ - + diff --git a/src/app/groups/groups-view/groups-view.component.ts b/src/app/groups/groups-view/groups-view.component.ts index 4cb2d8baa..d04bd2bb1 100644 --- a/src/app/groups/groups-view/groups-view.component.ts +++ b/src/app/groups/groups-view/groups-view.component.ts @@ -49,6 +49,7 @@ export class GroupsViewComponent { case 'Close': case 'Activate': case 'Attach Meeting': + case 'Attendance': this.router.navigate([`actions/${name}`], { relativeTo: this.route }); break; case 'Edit': diff --git a/src/app/groups/groups.module.ts b/src/app/groups/groups.module.ts index 03e40e75f..c7ee69a39 100644 --- a/src/app/groups/groups.module.ts +++ b/src/app/groups/groups.module.ts @@ -27,6 +27,7 @@ import { CloseGroupComponent } from './groups-view/group-actions/close-group/clo import { ActivateGroupComponent } from './groups-view/group-actions/activate-group/activate-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 { GroupAttendanceComponent } from './groups-view/group-actions/group-attendance/group-attendance.component'; /** * Groups Module @@ -58,7 +59,8 @@ import { AttachGroupMeetingComponent } from './groups-view/group-actions/attach- CloseGroupComponent, ActivateGroupComponent, EditGroupComponent, - AttachGroupMeetingComponent + AttachGroupMeetingComponent, + GroupAttendanceComponent ], entryComponents: [ UnassignRoleDialogComponent, diff --git a/src/app/groups/groups.service.ts b/src/app/groups/groups.service.ts index 4113842ca..563a46c5c 100644 --- a/src/app/groups/groups.service.ts +++ b/src/app/groups/groups.service.ts @@ -106,8 +106,9 @@ export class GroupsService { * @returns {Observable} */ unAssignRoleCommand(groupId: string, roleId: any): Observable { - const httpParams = new HttpParams().set('command', 'unassignRole') - .set('roleId', roleId); + const httpParams = new HttpParams() + .set('command', 'unassignRole') + .set('roleId', roleId); return this.http.post(`/groups/${groupId}`, {}, { params: httpParams }); } @@ -249,4 +250,24 @@ export class GroupsService { return this.http.post(`/groups/${groupId}/calendars`, data); } + /** + * @param {any} groupId Group Id + * @param {any} calendarId Calendar Id + * @returns {Observable} + */ + getMeetingsTemplate(groupId: any, calendarId: any): Observable { + const httpParams = new HttpParams().set('calenderId', calendarId); + return this.http.get(`/groups/${groupId}/meetings/template`, { params: httpParams }); + } + + /** + * @param {any} groupId Group Id + * @param {any} calendarId Calendar Id + * @returns {Observable} + */ + assignGroupAttendance(groupId: any, calendarId: any, data: any): Observable { + const httpParams = new HttpParams().set('calenderId', calendarId); + return this.http.post(`/groups/${groupId}/meetings`, data, { params: httpParams }); + } + }