Skip to content

Commit

Permalink
Refactor groups to support multiple event ids
Browse files Browse the repository at this point in the history
  • Loading branch information
caebr committed Sep 10, 2021
1 parent 7ee127d commit aba3e77
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ describe('PresenceControlGroupDialogComponent', () => {
component = fixture.componentInstance;
component.dialogMode = DialogMode.Select;
component.subscriptionDetail = buildSubscriptionDetail(3843);
component.savedGroupView = { eventId: 1, group: null };
component.group = null;
fixture.detectChanges();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Component, Input, OnInit } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { TranslateService } from '@ngx-translate/core';
import { SubscriptionDetail } from '../../../shared/models/subscription-detail.model';
import { GroupViewType } from '../../../shared/models/user-setting.model';

export interface GroupOptions {
id: Option<string>;
Expand All @@ -22,7 +21,7 @@ export enum DialogMode {
export class PresenceControlGroupDialogComponent implements OnInit {
@Input() dialogMode: DialogMode;
@Input() subscriptionDetail: SubscriptionDetail;
@Input() savedGroupView: GroupViewType;
@Input() group: Option<string>;
groupOptions: Array<GroupOptions> = [];
selected: GroupOptions;
title: string;
Expand All @@ -41,9 +40,8 @@ export class PresenceControlGroupDialogComponent implements OnInit {
this.groupOptions.unshift(emptyOption);

this.selected =
this.groupOptions.find(
(option) => option.id === this.savedGroupView.group
) || emptyOption;
this.groupOptions.find((option) => option.id === this.group) ||
emptyOption;
}

private createEmtpyOption(): GroupOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
sortCriteria: sortCriteria$ | async,
sortedEntries: sortedEntries$ | async,
selection: selectionService.selection$ | async,
groupView: groupService.groupView$ | async
group: groupService.group$ | async
} as data"
>
<a
Expand All @@ -24,10 +24,8 @@
<span class="pl-3">{{ 'presence-control.groups.show' | translate }}</span>
<button type="button" class="show btn btn-link" (click)="selectGroup()">
{{
data.groupView && data.groupView.group
? ('presence-control.groups.group' | translate) +
' ' +
data.groupView.group
data.group
? ('presence-control.groups.group' | translate) + ' ' + data.group
: ('presence-control.groups.all' | translate)
}}
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import { ActivatedRoute } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { TranslateService } from '@ngx-translate/core';
import { ToastrService } from 'ngx-toastr';
import { BehaviorSubject, combineLatest, EMPTY, forkJoin, of } from 'rxjs';
import { BehaviorSubject, combineLatest, forkJoin } from 'rxjs';
import { map, mapTo, pluck, switchMap, take } from 'rxjs/operators';
import { GroupViewType } from '../../../shared/models/user-setting.model';
import { SubscriptionDetailsRestService } from '../../../shared/services/subscription-details-rest.service';
import { UserSettingsRestService } from '../../../shared/services/user-settings-rest.service';
import { spread } from '../../../shared/utils/function';
import { parseQueryString } from '../../../shared/utils/url';
import {
updateGroupViews,
updateGroupViewSettings,
getUserSetting,
} from '../../../shared/utils/user-settings';
import { PresenceControlGroupSelectionService } from '../../services/presence-control-group-selection.service';
Expand Down Expand Up @@ -46,11 +45,7 @@ export class PresenceControlGroupComponent implements OnInit {
map(parseQueryString)
);

private eventId$ = this.route.paramMap.pipe(
map((params) => Number(params.get('id')))
); // TODO remove?, pass multiple event ids in url?

eventIds$ = this.state.selectedLesson$.pipe(
private eventIds$ = this.state.selectedLesson$.pipe(
map((lesson) => lesson?.getEventIds() || [])
);

Expand Down Expand Up @@ -99,16 +94,16 @@ export class PresenceControlGroupComponent implements OnInit {
): void {
combineLatest([
this.groupService.getSubscriptionDetailForGroupEvent(),
this.groupService.groupView$,
this.groupService.group$,
])
.pipe(take(1))
.subscribe(([subscriptionDetail, groupView]) => {
.subscribe(([subscriptionDetail, group]) => {
const modalRef = this.modalService.open(
PresenceControlGroupDialogComponent
);
modalRef.componentInstance.dialogMode = dialogMode;
modalRef.componentInstance.subscriptionDetail = subscriptionDetail;
modalRef.componentInstance.savedGroupView = groupView;
modalRef.componentInstance.group = group;

modalRef.result.then(
(selectedGroup) => {
Expand All @@ -123,30 +118,20 @@ export class PresenceControlGroupComponent implements OnInit {
combineLatest([this.eventIds$, this.groupService.savedGroupViews$])
.pipe(
take(1),
switchMap(([eventIds, groupViews]) => {
if (eventIds.length > 0) {
const groupView: GroupViewType = {
eventId: eventIds[0], // TODO send all event ids
group: selectedGroup.id,
};

const propertyBody = updateGroupViews(groupView, groupViews);
const cst = getUserSetting(
'presenceControlGroupView',
propertyBody
);

return this.settingsService
.updateUserSettingsCst(cst)
.pipe(mapTo(groupView));
}
return EMPTY;
switchMap(([eventIds, savedGroupViews]) => {
const propertyBody = updateGroupViewSettings(
selectedGroup.id,
eventIds,
savedGroupViews
);
const cst = getUserSetting('presenceControlGroupView', propertyBody);

return this.settingsService
.updateUserSettingsCst(cst)
.pipe(mapTo(selectedGroup.id));
})
)
.subscribe(
(propertyBody) =>
propertyBody && this.groupService.selectGroupView(propertyBody)
);
.subscribe((groupId) => this.groupService.selectGroup(groupId));
}

private assignCallback(selectedGroup: GroupOptions): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@
></erz-resettable-input>
<div class="group-and-views d-flex">
<a
*ngIf="state.groupsAvailability$ | async"
*ngIf="selectedLesson && state.groupsAvailability$ | async"
type="button"
class="group btn btn-link pr-xs-0 pr-sm-4"
[routerLink]="['groups', selectedLesson.eventId]"
[routerLink]="['groups', selectedLesson.id]"
[queryParams]="{
returnparams: (state.queryParamsString$ | async)
}"
Expand Down
37 changes: 22 additions & 15 deletions src/app/presence-control/services/presence-control-group.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,25 @@ import { flatten } from 'lodash-es';

@Injectable()
export class PresenceControlGroupService {
private selectGroupView$ = new Subject<GroupViewType>();
private selectGroup$ = new Subject<Option<string>>();
private selectedLesson$ = new ReplaySubject<Option<LessonEntry>>();
private lessonPresences$ = new ReplaySubject<ReadonlyArray<LessonPresence>>();
private reloadSubscriptionDetails$ = new Subject();

private defaultGroupView: GroupViewType = { eventId: null, group: null };
private defaultGroup: Option<string> = null;

savedGroupViews$ = this.loadSavedGroupViews();

private savedGroupView$ = this.selectedLesson$.pipe(
private savedGroup$ = this.selectedLesson$.pipe(
switchMap((lesson) =>
this.savedGroupViews$.pipe(
map(
(views) =>
views.find((view) => view.eventId === lesson?.getEventIds()[0]) ||
this.defaultGroupView // TODO helper
)
map((views) => this.findGroupByLesson(views, lesson))
)
)
);

groupView$ = merge(this.selectGroupView$, this.savedGroupView$).pipe(
startWith(this.defaultGroupView),
group$ = merge(this.selectGroup$, this.savedGroup$).pipe(
startWith(this.defaultGroup),
shareReplay(1)
);

Expand Down Expand Up @@ -125,11 +121,11 @@ export class PresenceControlGroupService {
);

subscriptionDetailPersonIds$ = combineLatest([
this.groupView$,
this.group$,
this.subscriptionDetails$,
]).pipe(
map(([groupView, details]) =>
details.filter((d) => d.Value === groupView?.group).map((d) => d.IdPerson)
map(([group, details]) =>
details.filter((d) => d.Value === group).map((d) => d.IdPerson)
),
startWith([])
);
Expand All @@ -142,8 +138,8 @@ export class PresenceControlGroupService {
@Inject(SETTINGS) private settings: Settings
) {}

selectGroupView(view: GroupViewType): void {
this.selectGroupView$.next(view);
selectGroup(groupId: Option<string>): void {
this.selectGroup$.next(groupId);
}

setSelectedLesson(selected: Option<LessonEntry>): void {
Expand Down Expand Up @@ -197,4 +193,15 @@ export class PresenceControlGroupService {
defaultIfEmpty([] as ReadonlyArray<GroupViewType>)
);
}

private findGroupByLesson(
groupViews: ReadonlyArray<GroupViewType>,
lesson: Option<LessonEntry>
): Option<string> {
const groupView = groupViews.find(
(gv) => gv.eventId === lesson?.getEventIds()[0] // All event ids of a lesson share the same group
);

return groupView?.group || this.defaultGroup;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export class PresenceControlStateService
]).pipe(map(spread(getPresenceControlEntriesForLesson)));

selectedPresenceControlEntriesByGroup$ = combineLatest([
this.groupService.groupView$,
this.groupService.group$,
this.selectedPresenceControlEntries$,
this.groupService.subscriptionDetailPersonIds$,
]).pipe(map(spread(filterByGroup)), shareReplay(1));
Expand Down
12 changes: 4 additions & 8 deletions src/app/shared/utils/presence-control-entries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,35 @@ describe('PresenceControlEntries', () => {
});

it('does not filter entries if group is null', () => {
const groupView = { eventId: 333, group: null };
const personIds = [1, 2, 3];

expect(filterByGroup(groupView, entries, personIds)).toEqual([
expect(filterByGroup(null, entries, personIds)).toEqual([
entry1,
entry2,
entry3,
]);
});

it('does filter entries - given all student ids', () => {
const groupView = { eventId: 333, group: 'A' };
const personIds = [1, 2, 3];

expect(filterByGroup(groupView, entries, personIds)).toEqual([
expect(filterByGroup('A', entries, personIds)).toEqual([
entry1,
entry2,
entry3,
]);
});

it('does filter entries - given one student id', () => {
const groupView = { eventId: 333, group: 'A' };
const personIds = [2];

expect(filterByGroup(groupView, entries, personIds)).toEqual([entry2]);
expect(filterByGroup('A', entries, personIds)).toEqual([entry2]);
});

it('does filter entries - given empty student ids', () => {
const groupView = { eventId: 333, group: 'A' };
const personIds: ReadonlyArray<number> = [];

expect(filterByGroup(groupView, entries, personIds)).toEqual([]);
expect(filterByGroup('A', entries, personIds)).toEqual([]);
});
});
});
4 changes: 2 additions & 2 deletions src/app/shared/utils/presence-control-entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ export function buildPresenceControlEntries(
}

export function filterByGroup(
groupView: Option<GroupViewType>,
group: Option<string>,
entries: ReadonlyArray<PresenceControlEntry>,
personIds: ReadonlyArray<number>
): ReadonlyArray<PresenceControlEntry> {
if (groupView?.group) {
if (group) {
return entries.filter((e) =>
personIds.find((id) => id === e.lessonPresence.StudentRef.Id)
);
Expand Down
Loading

0 comments on commit aba3e77

Please sign in to comment.