From 2e2eaf476d76394f504bc7b1f437fce613a383d6 Mon Sep 17 00:00:00 2001 From: Nicoleta Panaghiu Date: Fri, 25 Oct 2024 13:39:10 +0300 Subject: [PATCH] RED-9447, RED-10244: disable dossier template field if state is changed. --- .../edit-dossier-general-info.component.html | 18 +- .../edit-dossier-general-info.component.ts | 242 +++++++++++++----- .../dossier-templates.service.ts | 7 + 3 files changed, 191 insertions(+), 76 deletions(-) diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.html b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.html index bbd9d8aa2..86a398e69 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.html +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.html @@ -44,11 +44,15 @@
- - -
- -
{{ getStateName(stateId) }}
+ + +
+ +
{{ stateNameAndColor()[stateId]?.name }}
@@ -80,7 +84,7 @@
(); hasDueDate: boolean; dossierTemplates: IDossierTemplate[]; - states: string[]; + form: FormGroup> = this._formBuilder.group({ + dossierName: [null, Validators.required], + dossierTemplateId: [null, Validators.required], + dossierStatusId: [null], + description: [null], + dueDate: [null], + }); + initialFormValue: GeneralInfoForm; + readonly dossierStatusIdControl = formControlToSignal(this.form.controls.dossierStatusId); + readonly dossierTemplateIdControl = formControlToSignal(this.form.controls.dossierTemplateId); + readonly states = signal([null]); + readonly stateNameAndColor = computed(() => { + const nameAndColor = {}; + this.states().forEach(stateId => { + nameAndColor[stateId] = { + name: this.#getStateName(stateId, untracked(this.dossierTemplateIdControl)), + color: this.#getStateColor(stateId, untracked(this.dossierTemplateIdControl)), + }; + }); + return nameAndColor; + }); + readonly statePlaceholder = computed(() => this.#statePlaceholder); constructor( readonly permissionsService: PermissionsService, @@ -87,18 +115,36 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti private readonly _loadingService: LoadingService, private readonly _translateService: TranslateService, private readonly _archivedDossiersService: ArchivedDossiersService, - ) {} + private readonly _changeDetectorRef: ChangeDetectorRef, + private readonly _dossierStatesService: DossierStatesService, + ) { + effect(() => { + if (this.dossierStatusIdControl() !== this.initialFormValue.dossierStatusId && this.dossierStatusIdControl()) { + this.form.controls.dossierTemplateId.disable(); + } else { + this.form.controls.dossierTemplateId.enable(); + } + }); + + effect( + () => { + this.states.set(this.#statesForDossierTemplate); + this.#onDossierTemplateChange(); + }, + { allowSignalWrites: true }, + ); + } get changed(): boolean { for (const key of Object.keys(this.form.getRawValue())) { if (key === 'dueDate') { - if (this.hasDueDate !== !!this.dossier.dueDate) { + if (this.hasDueDate !== !!this.dossier().dueDate) { return true; } - if (this.hasDueDate && !dayjs(this.dossier.dueDate).isSame(dayjs(this.form.get(key).value), 'day')) { + if (this.hasDueDate && !dayjs(this.dossier().dueDate).isSame(dayjs(this.form.get(key).value), 'day')) { return true; } - } else if (this.dossier[key] !== this.form.get(key).value) { + } else if (this.dossier()[key] !== this.form.get(key).value) { return true; } } @@ -114,40 +160,89 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti return this.hasDueDate && this.form.get('dueDate').value === null; } - get #statusPlaceholder(): string { + get #statePlaceholder(): string { return this._translateService.instant( - this.states.length === 1 + isJustOne(this.states()) ? 'edit-dossier-dialog.general-info.form.dossier-state.no-state-placeholder' : 'dossier-state.placeholder', ) as string; } + get #statesForDossierTemplate() { + return [ + null, + ...this._dossierStatesMapService + .get(this.dossierTemplateIdControl() ?? untracked(this.dossier).dossierTemplateId) + .map(s => s.id), + ]; + } + + get #formValue(): { key: string; value: string; disabled: boolean }[] { + const dossier = untracked(this.dossier); + const formFieldWithArchivedCheck = value => ({ value, disabled: !dossier.isActive }); + const dossierStateId = untracked(this.dossierStatusIdControl); + const states = untracked(this.states); + return [ + { + key: 'dossierName', + ...formFieldWithArchivedCheck(dossier.dossierName), + }, + { + key: 'dossierTemplateId', + value: dossier.dossierTemplateId, + disabled: this._dossierStatsService.get(dossier.id).hasFiles || !dossier.isActive || !!dossierStateId, + }, + { + key: 'dossierStatusId', + value: dossier.dossierStatusId, + disabled: isJustOne(states) || !dossier.isActive, + }, + { + key: 'description', + ...formFieldWithArchivedCheck(dossier.description), + }, + { + key: 'dueDate', + ...formFieldWithArchivedCheck(dossier.dueDate), + }, + ]; + } + ngOnInit() { - this.states = [null, ...this._dossierStatesMapService.get(this.dossier.dossierTemplateId).map(s => s.id)]; - this.statusPlaceholder = this.#statusPlaceholder; - this.#filterInvalidDossierTemplates(); - this.form = this.#getForm(); - if (!this.permissionsService.canEditDossier(this.dossier)) { + this.#patchFormValue(); + if (isJustOne(this._dossierTemplatesService.all)) { + this._loadingService.loadWhile( + firstValueFrom(this._dossierTemplatesService.loadOnlyDossierTemplates()).then(async () => { + await firstValueFrom(this._dossierStatesService.loadAllForAllTemplates()); + this.#filterInvalidDossierTemplates(); + }), + ); + } else { + this.#filterInvalidDossierTemplates(); + } + + if (!this.permissionsService.canEditDossier(this.dossier())) { this.form.disable(); } - this.hasDueDate = !!this.dossier.dueDate; + this.hasDueDate = !!this.dossier().dueDate; } revert() { this.form.reset({ - dossierName: this.dossier.dossierName, - dossierTemplateId: this.dossier.dossierTemplateId, - dossierStatusId: this.dossier.dossierStatusId, - description: this.dossier.description, - dueDate: this.dossier.dueDate, + dossierName: this.dossier().dossierName, + dossierTemplateId: this.dossier().dossierTemplateId, + dossierStatusId: this.dossier().dossierStatusId, + description: this.dossier().description, + dueDate: this.dossier().dueDate, }); - this.hasDueDate = !!this.dossier.dueDate; + this.hasDueDate = !!this.dossier().dueDate; + this.initialFormValue = this.form.getRawValue(); } async save(): EditDossierSaveResult { const dueDate = dateWithoutTime(dayjs(this.form.get('dueDate').value)); const dossier = { - ...this.dossier, + ...this.dossier(), dossierName: this.form.get('dossierName').value, description: this.form.get('description').value, dueDate: dueDate.isValid() ? dueDate.toISOString() : undefined, @@ -156,9 +251,10 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti } as IDossierRequest; const updatedDossier = await firstValueFrom(this._dossiersService.createOrUpdate(dossier)); - if (updatedDossier && updatedDossier.dossierTemplateId !== this.dossier.dossierTemplateId) { + if (updatedDossier && updatedDossier.dossierTemplateId !== this.dossier().dossierTemplateId) { await this._router.navigate([updatedDossier.routerLink]); } + this.initialFormValue = this.form.getRawValue(); return { success: !!updatedDossier }; } @@ -171,14 +267,14 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti requireInput: true, denyText: _('confirmation-dialog.delete-dossier.deny-text'), translateParams: { - dossierName: this.dossier.dossierName, + dossierName: this.dossier().dossierName, dossiersCount: 1, }, }; this._dialogService.openDialog('confirm', data, async () => { this._loadingService.start(); - const successful = await this._trashService.deleteDossier(this.dossier); + const successful = await this._trashService.deleteDossier(this.dossier()); if (successful) { await this.#closeDialogAndRedirectToDossier(); } @@ -194,7 +290,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti confirmationText: _('confirm-archive-dossier.archive'), denyText: _('confirm-archive-dossier.cancel'), titleColor: TitleColors.WARN, - translateParams: { ...this.dossier }, + translateParams: { ...this.dossier() }, checkboxes: [{ value: false, label: _('confirm-archive-dossier.checkbox.documents') }], toastMessage: _('confirm-archive-dossier.toast-error'), }; @@ -202,10 +298,10 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti this._dialogService.openDialog('confirm', data, async result => { if (result === ConfirmOptions.CONFIRM) { this._loadingService.start(); - await firstValueFrom(this._archivedDossiersService.archive([this.dossier])); + await firstValueFrom(this._archivedDossiersService.archive([this.dossier()])); this._toaster.success(_('dossier-listing.archive.archive-succeeded'), { params: { - dossierName: this.dossier.dossierName, + dossierName: this.dossier().dossierName, }, }); this._editDossierDialogRef.close(); @@ -214,15 +310,6 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti }); } - getStateName(stateId: string): string { - return (this._dossierStatesMapService.get(this.dossier.dossierTemplateId, stateId)?.name || - this._translateService.instant('dossier-state.placeholder')) as string; - } - - getStateColor(stateId: string): string { - return this._dossierStatesMapService.get(this.dossier.dossierTemplateId, stateId).color; - } - toggleDueDateField() { this.hasDueDate = !this.hasDueDate; if (!this.hasDueDate) { @@ -230,46 +317,63 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti } } + #getStateName(stateId: string, templateId: string): string { + return (this._dossierStatesMapService.get(templateId, stateId)?.name || + this._translateService.instant('dossier-state.placeholder')) as string; + } + + #getStateColor(stateId: string, templateId: string): string { + return this._dossierStatesMapService.get(templateId, stateId)?.color; + } + + #patchFormValue() { + this.#formValue.forEach(formValue => { + this.form.patchValue({ [formValue.key]: formValue.value }); + if (formValue.disabled) this.form.get(formValue.key).disable(); + }); + this.initialFormValue = this.form.getRawValue(); + } + async #closeDialogAndRedirectToDossier() { this._editDossierDialogRef.close(); - await this._router.navigate([this.dossier.dossiersListRouterLink]); + await this._router.navigate([this.dossier().dossiersListRouterLink]); this._toaster.success(_('edit-dossier-dialog.delete-successful'), { params: { - dossierName: this.dossier.dossierName, + dossierName: this.dossier().dossierName, }, }); } - #getForm(): UntypedFormGroup { - const formFieldWithArchivedCheck = value => ({ value, disabled: !this.dossier.isActive }); - return this._formBuilder.group({ - dossierName: [formFieldWithArchivedCheck(this.dossier.dossierName), Validators.required], - dossierTemplateId: [ - { - value: this.dossier.dossierTemplateId, - disabled: this._dossierStatsService.get(this.dossier.id).hasFiles || !this.dossier.isActive, - }, - Validators.required, - ], - dossierStatusId: [ - { - value: this.dossier.dossierStatusId, - disabled: this.states.length === 1 || !this.dossier.isActive, - }, - ], - description: [formFieldWithArchivedCheck(this.dossier.description)], - dueDate: [formFieldWithArchivedCheck(this.dossier.dueDate)], - }); - } - #filterInvalidDossierTemplates() { + const dossier = untracked(this.dossier); this.dossierTemplates = this._dossierTemplatesService.all.filter(r => { - if (this.dossier?.dossierTemplateId === r.dossierTemplateId) { + if (dossier.dossierTemplateId === r.dossierTemplateId) { return true; } const notYetValid = !!r.validFrom && dayjs(r.validFrom).isAfter(dayjs()); const notValidAnymore = !!r.validTo && dayjs(r.validTo).add(1, 'd').isBefore(dayjs()); + this._changeDetectorRef.markForCheck(); return !(notYetValid || notValidAnymore) && r.isActive; }); } + + #onDossierTemplateChange() { + const dossierStateId = untracked(this.dossierStatusIdControl); + const dossierTemplateId = untracked(this.dossierTemplateIdControl); + if (!!dossierStateId && dossierTemplateId !== this.initialFormValue.dossierTemplateId) { + this.form.controls.dossierStatusId.setValue(null); + } + const dossier = untracked(this.dossier); + if (dossierTemplateId === this.initialFormValue.dossierTemplateId) { + this.form.controls.dossierStatusId.setValue(dossier.dossierStatusId); + } + const states = untracked(this.states); + if (isJustOne(states) || !dossier.isActive) { + this.form.controls.dossierStatusId.disable(); + } else { + this.form.controls.dossierStatusId.enable(); + } + + this._changeDetectorRef.markForCheck(); + } } diff --git a/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts b/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts index fa79a0d16..2283d410b 100644 --- a/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts +++ b/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts @@ -45,6 +45,13 @@ export class DossierTemplatesService extends EntitiesService { + return this.getAll().pipe( + mapEach(entity => new DossierTemplate(entity)), + tap(templates => this.setEntities(templates)), + ); + } + loadDossierTemplate(dossierTemplateId: string) { return this._getOne([dossierTemplateId], this._defaultModelPath).pipe( map(entity => new DossierTemplate(entity)),