diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html index a056d7d3c..ea0944da4 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html @@ -7,16 +7,16 @@
-
{{ dictionary?.type || technicalName || '-' }}
+
{{ dictionary?.type || (technicalName$ | async) || '-' }}
-
+
{{ dictionary.label }}
-
+
- +
diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts index 6fe2d7c2e..75fe1ac4e 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts @@ -1,39 +1,47 @@ -import { Component, Inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Observable } from 'rxjs'; -import { BaseDialogComponent, Toaster } from '@iqser/common-ui'; +import { BaseDialogComponent, shareDistinctLast, Toaster } from '@iqser/common-ui'; import { TranslateService } from '@ngx-translate/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { AppStateService } from '@state/app-state.service'; import { toKebabCase } from '@utils/functions'; import { DictionaryService } from '@shared/services/dictionary.service'; import { Dictionary, IDictionary } from '@red/domain'; +import { UserService } from '@services/user.service'; +import { map } from 'rxjs/operators'; @Component({ selector: 'redaction-add-edit-dictionary-dialog', templateUrl: './add-edit-dictionary-dialog.component.html', styleUrls: ['./add-edit-dictionary-dialog.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class AddEditDictionaryDialogComponent extends BaseDialogComponent { - form: FormGroup; - readonly dictionary: Dictionary; - technicalName = ''; - private readonly _dossierTemplateId: string; + readonly form: FormGroup; + readonly dictionary = this._data.dictionary; + readonly canEditLabel$ = this._canEditLabel$; + readonly technicalName$: Observable; + readonly dialogHeader = this._translateService.instant('add-edit-dictionary.title', { + type: this._data.dictionary ? 'edit' : 'create', + name: this._data.dictionary?.label, + }); + readonly hasColor$: Observable; + private readonly _dossierTemplateId = this._data.dossierTemplateId; constructor( - private readonly _dictionaryService: DictionaryService, - private readonly _appStateService: AppStateService, - private readonly _formBuilder: FormBuilder, + readonly userService: UserService, private readonly _toaster: Toaster, + private readonly _formBuilder: FormBuilder, + private readonly _appStateService: AppStateService, private readonly _translateService: TranslateService, + private readonly _dictionaryService: DictionaryService, private readonly _dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) - private readonly _data: { dictionary: Dictionary; dossierTemplateId: string }, + private readonly _data: { readonly dictionary: Dictionary; readonly dossierTemplateId: string }, ) { super(); - this.dictionary = _data.dictionary; - this._dossierTemplateId = _data.dossierTemplateId; this.form = _formBuilder.group({ label: [this.dictionary?.label, [Validators.required, Validators.minLength(3)]], description: [this.dictionary?.description], @@ -43,21 +51,8 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent { addToDictionaryAction: [!!this.dictionary?.addToDictionaryAction], caseSensitive: [this.dictCaseSensitive], }); - this.form.get('label').valueChanges.subscribe(() => { - this._updateTechnicalName(); - }); - } - - get dialogHeader(): string { - return this._translateService.instant('add-edit-dictionary.title', { - type: this.dictionary ? 'edit' : 'create', - name: this.dictionary?.label, - }); - } - - get hasColor(): boolean { - const hexColorValue = this.form.get('hexColor').value; - return !hexColorValue || hexColorValue?.length === 0; + this.hasColor$ = this._colorEmpty$; + this.technicalName$ = this.form.get('label').valueChanges.pipe(map(value => this._toTechnicalName(value))); } get dictCaseSensitive(): boolean { @@ -82,21 +77,34 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent { return false; } - save(): void { + private get _canEditLabel$() { + return this.userService.currentUser$.pipe( + map(user => user.isAdmin || !this._data.dictionary), + shareDistinctLast(), + ); + } + + private get _colorEmpty$() { + return this.form.get('hexColor').valueChanges.pipe(map((value: string) => !value || value?.length === 0)); + } + + async save(): Promise { const dictionary = this._formToObject(); let observable: Observable; + const dossierTemplateId = this._data.dossierTemplateId; if (this.dictionary) { // edit mode - observable = this._dictionaryService.updateDictionary(dictionary, this._dossierTemplateId, dictionary.type); + observable = this._dictionaryService.updateDictionary(dictionary, dossierTemplateId, dictionary.type); } else { // create mode - observable = this._dictionaryService.addDictionary({ ...dictionary, dossierTemplateId: this._dossierTemplateId }); + observable = this._dictionaryService.addDictionary({ ...dictionary, dossierTemplateId }); } - observable.subscribe( - () => this._dialogRef.close(true), - error => { + return observable + .toPromise() + .then(() => this._dialogRef.close(true)) + .catch(error => { if (error.status === 409) { this._toaster.error(_('add-edit-dictionary.error.dictionary-already-exists')); } else if (error.status === 400) { @@ -104,25 +112,23 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent { } else { this._toaster.error(_('add-edit-dictionary.error.generic')); } - }, - ); + }); } - private _updateTechnicalName() { - const displayName = this.form.get('label').value.trim(); + private _toTechnicalName(value: string) { const existingTechnicalNames = Object.keys(this._appStateService.dictionaryData[this._dossierTemplateId]); - const baseTechnicalName: string = toKebabCase(displayName); + const baseTechnicalName = toKebabCase(value.trim()); let technicalName = baseTechnicalName; let suffix = 1; while (existingTechnicalNames.includes(technicalName)) { technicalName = [baseTechnicalName, suffix++].join('-'); } - this.technicalName = technicalName; + return technicalName; } private _formToObject(): IDictionary { return { - type: this.dictionary?.type || this.technicalName, + type: this.dictionary?.type || this._toTechnicalName(this.form.get('label').value), label: this.form.get('label').value, caseInsensitive: !this.form.get('caseSensitive').value, description: this.form.get('description').value, @@ -130,7 +136,7 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent { hint: this.form.get('hint').value, rank: this.form.get('rank').value, addToDictionaryAction: this.form.get('addToDictionaryAction').value, - dossierTemplateId: this._dossierTemplateId, + dossierTemplateId: this._data.dossierTemplateId, }; } } diff --git a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts index b26199467..a93bcec16 100644 --- a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts +++ b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts @@ -4,7 +4,7 @@ import { IDictionary } from './dictionary'; export class Dictionary implements IDictionary, IListable { readonly addToDictionaryAction: boolean; readonly caseInsensitive: boolean; - readonly description?: string; + readonly description: string; readonly dossierTemplateId?: string; entries: List; readonly hexColor?: string; @@ -17,7 +17,7 @@ export class Dictionary implements IDictionary, IListable { constructor(dictionary: IDictionary, readonly virtual = false) { this.addToDictionaryAction = !!dictionary.addToDictionaryAction; this.caseInsensitive = !!dictionary.caseInsensitive; - this.description = dictionary.description; + this.description = dictionary.description ?? ''; this.dossierTemplateId = dictionary.dossierTemplateId; this.entries = dictionary.entries ?? []; this.hexColor = dictionary.hexColor; diff --git a/package.json b/package.json index c657bcf2a..965a88c70 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redaction", - "version": "2.339.0", + "version": "2.340.0", "private": true, "license": "MIT", "scripts": { diff --git a/paligo-theme.tar.gz b/paligo-theme.tar.gz index e18d163cb..1dd888198 100644 Binary files a/paligo-theme.tar.gz and b/paligo-theme.tar.gz differ