RED-6578, fix the incomprehensible cosmic horror thingy.

This commit is contained in:
George 2023-04-11 20:15:31 +03:00
parent 733aa7687d
commit bd760de3e9
3 changed files with 88 additions and 97 deletions

View File

@ -10,18 +10,20 @@
</mat-form-field>
</div>
<ng-container *ngIf="selectedApproversList.length">
<div class="all-caps-label mt-16" id="approversLabel" translate="assign-dossier-owner.dialog.approvers"></div>
<redaction-team-members
(remove)="toggleSelected($event)"
[canAdd]="false"
[canRemove]="hasOwner && !disabled"
[dossierId]="dossier.id"
[largeSpacing]="true"
[memberIds]="selectedApproversList"
[perLine]="13"
[unremovableMembers]="[selectedOwnerId]"
></redaction-team-members>
<ng-container *ngIf="selectedApprovers$ | async as selectedApprovers">
<ng-container *ngIf="selectedApprovers.length">
<div class="all-caps-label mt-16" id="approversLabel" translate="assign-dossier-owner.dialog.approvers"></div>
<redaction-team-members
(remove)="toggleSelected($event)"
[canAdd]="false"
[canRemove]="hasOwner && !disabled"
[dossierId]="dossier.id"
[largeSpacing]="true"
[memberIds]="selectedApprovers"
[perLine]="13"
[unremovableMembers]="[this.form.value.owner]"
></redaction-team-members>
</ng-container>
</ng-container>
<div class="all-caps-label mt-16" id="reviewersLabel" translate="assign-dossier-owner.dialog.reviewers"></div>
@ -34,7 +36,7 @@
[largeSpacing]="true"
[memberIds]="selectedReviewers$ | async"
[perLine]="13"
[unremovableMembers]="[selectedOwnerId]"
[unremovableMembers]="[this.form.value.owner]"
></redaction-team-members>
<ng-container *ngIf="!(selectedReviewers$ | async)?.length">

View File

@ -1,14 +1,15 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, Component, inject, Input, OnChanges, SimpleChanges } from '@angular/core';
import { UserService } from '@users/user.service';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Dossier, IDossierRequest } from '@red/domain';
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { BehaviorSubject, firstValueFrom } from 'rxjs';
import { firstValueFrom } from 'rxjs';
import { PermissionsService } from '@services/permissions.service';
import { DossiersService } from '@services/dossiers/dossiers.service';
import { compareLists } from '@utils/functions';
import { FilesService } from '@services/files/files.service';
import { Debounce } from '@iqser/common-ui';
import { map } from 'rxjs/operators';
@Component({
selector: 'redaction-edit-dossier-team',
@ -16,42 +17,26 @@ import { Debounce } from '@iqser/common-ui';
styleUrls: ['./edit-dossier-team.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class EditDossierTeamComponent implements EditDossierSectionInterface, OnInit {
form: UntypedFormGroup;
export class EditDossierTeamComponent implements EditDossierSectionInterface, OnChanges {
form = this.#getForm();
searchQuery = '';
@Input() dossier: Dossier;
membersSelectOptions: string[] = [];
readonly ownersSelectOptions = this.userService.all.filter(u => u.isManager).map(m => m.id);
readonly selectedReviewers$ = new BehaviorSubject<string[]>([]);
constructor(
readonly userService: UserService,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _dossiersService: DossiersService,
private readonly _permissionsService: PermissionsService,
private readonly _filesService: FilesService,
) {}
get selectedOwnerId(): string {
return this.form.get('owner').value;
}
get selectedApproversList(): string[] {
return this.form.get('approvers').value;
}
get selectedMembersList(): string[] {
return this.form.get('members').value;
}
readonly #userService = inject(UserService);
readonly #dossiersService = inject(DossiersService);
readonly #permissionsService = inject(PermissionsService);
readonly #filesService = inject(FilesService);
readonly ownersSelectOptions = this.#userService.all.filter(u => u.isManager).map(m => m.id);
readonly #formValue$ = this.form.valueChanges;
readonly selectedReviewers$ = this.#formValue$.pipe(map(v => v.members.filter(m => !v.approvers.includes(m))));
readonly selectedApprovers$ = this.#formValue$.pipe(map(v => v.approvers));
get valid(): boolean {
return this.form.valid;
}
get disabled() {
return !this._permissionsService.canEditTeamMembers() || !this.form.get('owner').value;
return !this.#permissionsService.canEditTeamMembers() || !this.form.get('owner').value;
}
get hasOwner() {
@ -59,15 +44,17 @@ export class EditDossierTeamComponent implements EditDossierSectionInterface, On
}
get changed() {
if (this.dossier.ownerId !== this.selectedOwnerId) {
const { owner, members, approvers } = this.form.value;
if (this.dossier.ownerId !== owner) {
return true;
}
const initialMembers = [...this.dossier.memberIds].sort();
const currentMembers = this.selectedMembersList.sort();
const currentMembers = members.sort();
const initialApprovers = [...this.dossier.approverIds].sort();
const currentApprovers = this.selectedApproversList.sort();
const currentApprovers = approvers.sort();
return compareLists(initialMembers, currentMembers) || compareLists(initialApprovers, currentApprovers);
}
@ -77,70 +64,72 @@ export class EditDossierTeamComponent implements EditDossierSectionInterface, On
if (!this.isApprover(ownerId)) {
this.toggleApprover(ownerId);
}
this._updateLists();
this.#updateLists();
}
const { owner, members, approvers } = this.form.value;
const dossier = {
...this.dossier,
memberIds: this.selectedMembersList,
approverIds: this.selectedApproversList,
ownerId: this.selectedOwnerId,
memberIds: members,
approverIds: approvers,
ownerId: owner,
} as IDossierRequest;
const updatedDossier = await firstValueFrom(this._dossiersService.createOrUpdate(dossier));
await firstValueFrom(this._filesService.loadAll(updatedDossier.dossierId));
const updatedDossier = await firstValueFrom(this.#dossiersService.createOrUpdate(dossier));
await firstValueFrom(this.#filesService.loadAll(updatedDossier.dossierId));
return { success: !!updatedDossier };
}
isMemberSelected(userId: string): boolean {
return this.selectedMembersList.indexOf(userId) !== -1;
return this.form.value.members.includes(userId);
}
isApprover(userId: string): boolean {
return this.selectedApproversList.indexOf(userId) !== -1;
return this.form.value.approvers.includes(userId);
}
toggleApprover(userId: string) {
const currentApprovers = this.form.value.approvers;
const approversControl = this.form.controls.approvers;
if (this.isApprover(userId)) {
this.selectedApproversList.splice(this.selectedApproversList.indexOf(userId), 1);
approversControl.patchValue(currentApprovers.filter(a => a !== userId));
} else {
this.selectedApproversList.push(userId);
approversControl.patchValue([...currentApprovers, userId]);
if (!this.isMemberSelected(userId)) {
this.toggleSelected(userId);
}
}
this._updateLists();
this.#updateLists();
}
toggleSelected(userId: string) {
const { members, approvers } = this.form.value;
const { members: membersControl, approvers: approversControl } = this.form.controls;
if (this.isMemberSelected(userId)) {
this.selectedMembersList.splice(this.selectedMembersList.indexOf(userId), 1);
membersControl.patchValue(members.filter(m => m !== userId));
if (this.isApprover(userId)) {
this.selectedApproversList.splice(this.selectedApproversList.indexOf(userId), 1);
approversControl.patchValue(approvers.filter(a => a !== userId));
}
} else {
this.selectedMembersList.push(userId);
membersControl.patchValue([...members, userId]);
}
this._updateLists();
this.#updateLists();
}
ngOnInit() {
this._loadData();
ngOnChanges(changes: SimpleChanges): void {
setTimeout(this.#resetForm.bind(this));
}
revert() {
this._loadData();
this.#resetForm();
}
setMembersSelectOptions(value = this.searchQuery): void {
const possibleMembers = this.userService.all.filter(user => user.isUser || user.isManager);
const possibleMembers = this.#userService.all.filter(user => user.isUser || user.isManager);
this.membersSelectOptions = possibleMembers
.filter(user => this.userService.getName(user.id).toLowerCase().includes(value.toLowerCase()))
.filter(user => this.selectedOwnerId !== user.id)
.filter(user => this.#userService.getName(user.id).toLowerCase().includes(value.toLowerCase()))
.filter(user => this.form.value.owner !== user.id)
.map(user => user.id)
.sort((a, b) => this.userService.getName(a).localeCompare(this.userService.getName(b)));
.sort((a, b) => this.#userService.getName(a).localeCompare(this.#userService.getName(b)));
}
@Debounce(0)
@ -150,36 +139,35 @@ export class EditDossierTeamComponent implements EditDossierSectionInterface, On
this.toggleApprover(ownerId);
}
// If it is an approver, it is already a member, no need to check
this._updateLists();
this.#updateLists();
}
}
private _setSelectedReviewersList() {
const selectedReviewers = this.selectedMembersList.filter(m => this.selectedApproversList.indexOf(m) === -1);
this.selectedReviewers$.next(this._sortByName(selectedReviewers));
}
private _loadData() {
this.form = this._formBuilder.group({
owner: [
{
value: this.dossier.ownerId,
disabled: !this._permissionsService.canEditTeamMembers(),
},
Validators.required,
],
approvers: [this._sortByName([...this.dossier.approverIds])],
members: [this._sortByName([...this.dossier.memberIds])],
});
this._updateLists();
}
private _updateLists() {
this._setSelectedReviewersList();
#updateLists() {
this.setMembersSelectOptions();
}
private _sortByName(ids: string[]) {
return ids.sort((a, b) => this.userService.getName(a).localeCompare(this.userService.getName(b)));
#sortByName(ids: string[]) {
return ids.sort((a, b) => this.#userService.getName(a).localeCompare(this.#userService.getName(b)));
}
#getForm() {
return new FormGroup({
owner: new FormControl({ value: '', disabled: false }, Validators.required),
approvers: new FormControl([]),
members: new FormControl([]),
});
}
#resetForm() {
this.form.reset(
{
owner: { value: this.dossier.ownerId, disabled: !this.#permissionsService.canEditTeamMembers() },
approvers: this.#sortByName([...this.dossier.approverIds]),
members: this.#sortByName([...this.dossier.memberIds]),
} as unknown,
{ emitEvent: true },
);
this.#updateLists();
}
}

View File

@ -32,6 +32,7 @@ export class TeamMembersComponent implements OnChanges {
constructor(private readonly _dialogService: DossiersDialogService) {}
ngOnChanges() {
this.memberIds ??= [];
this.memberIds = [...this.memberIds].sort((a, b) => this.userService.getName(a).localeCompare(this.userService.getName(b)));
}
@ -52,7 +53,7 @@ export class TeamMembersComponent implements OnChanges {
}
canRemoveMember(userId: string) {
return this.canRemove && this.unremovableMembers.indexOf(userId) === -1;
return this.canRemove && !this.unremovableMembers.includes(userId);
}
openEditDossierDialog(): void {