From 0ccb68726eacb588191e2050409a4d538b96a179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Wed, 13 Apr 2022 11:52:40 +0300 Subject: [PATCH] RED-3827: Refactor entity form --- .../add-entity-dialog.component.html | 14 +-- .../add-entity-dialog.component.ts | 43 +++----- .../entities/screens/info/info.component.html | 4 +- .../entities/screens/info/info.component.ts | 58 +++------- .../add-edit-entity.component.html | 2 +- .../add-edit-entity.component.ts | 101 ++++++++++++------ 6 files changed, 112 insertions(+), 110 deletions(-) diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.html index 9b107f290..e2267fb81 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.html @@ -3,11 +3,13 @@ {{ dialogHeader }} -
-
- -
-
+
+ +
- + diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.ts index efecbc48d..d3c61b548 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.ts @@ -1,13 +1,16 @@ import { ChangeDetectionStrategy, Component, Inject, Injector, ViewChild } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { BaseDialogComponent } from '@iqser/common-ui'; import { TranslateService } from '@ngx-translate/core'; import { DictionaryService } from '@services/entity-services/dictionary.service'; -import { Dictionary } from '@red/domain'; import { UserService } from '@services/user.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { AddEditEntityComponent } from '../../shared/components/add-edit-entity/add-edit-entity.component'; +import { BaseDialogComponent } from '@iqser/common-ui'; + +interface DialogData { + readonly dossierTemplateId: string; +} @Component({ templateUrl: './add-entity-dialog.component.html', @@ -15,11 +18,10 @@ import { AddEditEntityComponent } from '../../shared/components/add-edit-entity/ changeDetection: ChangeDetectionStrategy.OnPush, }) export class AddEntityDialogComponent extends BaseDialogComponent { - readonly entity = this._data.dictionary; readonly dialogHeader = this._translateService.instant('add-entity.title'); readonly dossierTemplateId = this._data.dossierTemplateId; - @ViewChild(AddEditEntityComponent) private readonly _addEditEntityComponent: AddEditEntityComponent; + @ViewChild(AddEditEntityComponent, { static: true }) private readonly _addEditEntityComponent: AddEditEntityComponent; constructor( readonly userService: UserService, @@ -29,12 +31,17 @@ export class AddEntityDialogComponent extends BaseDialogComponent { private readonly _dictionaryService: DictionaryService, protected readonly _injector: Injector, protected readonly _dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) - private readonly _data: { readonly dictionary: Dictionary; readonly dossierTemplateId: string }, + @Inject(MAT_DIALOG_DATA) private readonly _data: DialogData, ) { - super(_injector, _dialogRef, !!_data.dictionary); - this.form = this._getForm(this.entity); - this.initialFormValue = this.form.getRawValue(); + super(_injector, _dialogRef, false); + } + + get valid(): boolean { + return this._addEditEntityComponent.valid; + } + + get changed(): boolean { + return this._addEditEntityComponent.changed; } async save(): Promise { @@ -45,20 +52,4 @@ export class AddEntityDialogComponent extends BaseDialogComponent { console.error(e); } } - - private _getForm(entity: Dictionary): FormGroup { - return this._formBuilder.group({ - type: [entity?.label], - label: [entity?.label, [Validators.required, Validators.minLength(3)]], - description: [entity?.description], - rank: [entity?.rank, Validators.required], - hexColor: [entity?.hexColor, [Validators.required, Validators.minLength(7)]], - hint: [!!entity?.hint], - addToDictionaryAction: [!!entity?.addToDictionaryAction], - caseSensitive: [entity ? !entity.caseInsensitive : false], - recommendationHexColor: [this.entity?.recommendationHexColor, [Validators.required, Validators.minLength(7)]], - hasDictionary: [this.entity?.hasDictionary], - defaultReason: [{ value: null, disabled: true }], - }); - } } diff --git a/apps/red-ui/src/app/modules/admin/screens/entities/screens/info/info.component.html b/apps/red-ui/src/app/modules/admin/screens/entities/screens/info/info.component.html index 1a8618ba9..2c3040c08 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities/screens/info/info.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/entities/screens/info/info.component.html @@ -10,11 +10,11 @@
- +
- diff --git a/apps/red-ui/src/app/modules/admin/screens/entities/screens/info/info.component.ts b/apps/red-ui/src/app/modules/admin/screens/entities/screens/info/info.component.ts index b2fc313c9..7138f6a32 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities/screens/info/info.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/entities/screens/info/info.component.ts @@ -1,6 +1,5 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ViewChild } from '@angular/core'; -import { BaseFormComponent } from '@iqser/common-ui'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, ViewChild } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; import { Dictionary } from '@red/domain'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { DOSSIER_TEMPLATE_ID, ENTITY_TYPE } from '@utils/constants'; @@ -9,6 +8,7 @@ import { UserService } from '@services/user.service'; import { DictionaryService } from '@services/entity-services/dictionary.service'; import { PermissionsService } from '@services/permissions.service'; import { AddEditEntityComponent } from '../../../../shared/components/add-edit-entity/add-edit-entity.component'; +import { IqserEventTarget } from '../../../../../../../../../../libs/common-ui/src'; @Component({ selector: 'redaction-info', @@ -16,7 +16,7 @@ import { AddEditEntityComponent } from '../../../../shared/components/add-edit-e styleUrls: ['./info.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class InfoComponent extends BaseFormComponent { +export class InfoComponent { readonly currentUser = this._userService.currentUser; entity: Dictionary; readonly dossierTemplateId: string; @@ -31,57 +31,33 @@ export class InfoComponent extends BaseFormComponent { private readonly _changeRef: ChangeDetectorRef, readonly permissionsService: PermissionsService, ) { - super(); this.dossierTemplateId = this._route.parent.snapshot.paramMap.get(DOSSIER_TEMPLATE_ID); - this.form = this._initializeForm(); + const entityType = this._route.parent.snapshot.paramMap.get(ENTITY_TYPE); + this.entity = this._dictionariesMapService.getDictionary(entityType, this.dossierTemplateId); } async save(): Promise { try { await this._addEditEntityComponent.save(); - this.initialFormValue = this.form.getRawValue(); - this._changeRef.markForCheck(); } catch (e) { console.error(e); } } - revert(): void { - this.form = this._initializeForm(); + get disabled(): boolean { + return !this._addEditEntityComponent || this._addEditEntityComponent.form?.invalid || !this._addEditEntityComponent.changed; } - private _initializeForm(): FormGroup { - const entityType = this._route.parent.snapshot.paramMap.get(ENTITY_TYPE); - this.entity = this._dictionariesMapService.getDictionary(entityType, this.dossierTemplateId); + revert(): void { + this._addEditEntityComponent.revert(); + } - const controlsConfig = { - type: [this.entity.type], - label: [ - { - value: this.entity.label, - disabled: !this.currentUser.isAdmin, - }, - [Validators.required, Validators.minLength(3)], - ], - description: [this.entity.description], - rank: [this.entity.rank, Validators.required], - hexColor: [this.entity.hexColor, [Validators.required, Validators.minLength(7)]], - recommendationHexColor: [this.entity.recommendationHexColor, [Validators.required, Validators.minLength(7)]], - hint: [this.entity.hint], - hasDictionary: [this.entity.hasDictionary], - }; - - if (!this.entity.hint) { - Object.assign(controlsConfig, { - defaultReason: [{ value: null, disabled: true }], - caseSensitive: [!this.entity.caseInsensitive], - addToDictionaryAction: [this.entity.addToDictionaryAction], - }); + @HostListener('window:keydown.Enter', ['$event']) + async onEnter(event: KeyboardEvent): Promise { + event?.stopImmediatePropagation(); + const node = (event.target as IqserEventTarget).localName; + if (this._addEditEntityComponent.valid && !this.disabled && this._addEditEntityComponent.changed && node !== 'textarea') { + await this.save(); } - const form = this._formBuilder.group(controlsConfig); - - this.initialFormValue = form.getRawValue(); - - return form; } } diff --git a/apps/red-ui/src/app/modules/admin/shared/components/add-edit-entity/add-edit-entity.component.html b/apps/red-ui/src/app/modules/admin/shared/components/add-edit-entity/add-edit-entity.component.html index 7b5c6a8b3..4803ea9b6 100644 --- a/apps/red-ui/src/app/modules/admin/shared/components/add-edit-entity/add-edit-entity.component.html +++ b/apps/red-ui/src/app/modules/admin/shared/components/add-edit-entity/add-edit-entity.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/apps/red-ui/src/app/modules/admin/shared/components/add-edit-entity/add-edit-entity.component.ts b/apps/red-ui/src/app/modules/admin/shared/components/add-edit-entity/add-edit-entity.component.ts index 25edfe741..e707b56e5 100644 --- a/apps/red-ui/src/app/modules/admin/shared/components/add-edit-entity/add-edit-entity.component.ts +++ b/apps/red-ui/src/app/modules/admin/shared/components/add-edit-entity/add-edit-entity.component.ts @@ -1,6 +1,6 @@ -import { ChangeDetectionStrategy, Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; import { Dictionary, IDictionary } from '@red/domain'; -import { FormControl, FormGroup } from '@angular/forms'; +import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { map, startWith } from 'rxjs/operators'; import { firstValueFrom, Observable } from 'rxjs'; import { toSnakeCase } from '@utils/functions'; @@ -8,7 +8,7 @@ import { DictionariesMapService } from '@services/entity-services/dictionaries-m import { PermissionsService } from '@services/permissions.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DictionaryService } from '@services/entity-services/dictionary.service'; -import { LoadingService, Toaster } from '@iqser/common-ui'; +import { BaseFormComponent, LoadingService, Toaster } from '@iqser/common-ui'; const REDACTION_FIELDS = ['defaultReason', 'caseSensitive', 'addToDictionaryAction']; @@ -18,10 +18,9 @@ const REDACTION_FIELDS = ['defaultReason', 'caseSensitive', 'addToDictionaryActi styleUrls: ['./add-edit-entity.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class AddEditEntityComponent implements OnInit, OnChanges { +export class AddEditEntityComponent extends BaseFormComponent implements OnInit { @Input() dossierTemplateId: string; @Input() entity: Dictionary; - @Input() form: FormGroup; hasHexColor$: Observable; hasRecommendationHexColor$: Observable; @@ -33,36 +32,68 @@ export class AddEditEntityComponent implements OnInit, OnChanges { private readonly _dictionaryService: DictionaryService, private readonly _toaster: Toaster, private readonly _loadingService: LoadingService, - ) {} - - ngOnInit() { - this.hasHexColor$ = this._colorEmpty$('hexColor'); - this.hasRecommendationHexColor$ = this._colorEmpty$('recommendationHexColor'); - this.technicalName$ = this.form.get('label').valueChanges.pipe(map((value: string) => this._toTechnicalName(value))); + private readonly _formBuilder: FormBuilder, + private readonly _changeRef: ChangeDetectorRef, + ) { + super(); } - ngOnChanges(changes: SimpleChanges) { - if (changes.form) { - this.form.get('hint').valueChanges.subscribe(isHint => { - if (isHint) { - REDACTION_FIELDS.forEach(field => this.form.removeControl(field)); - } else { - this.form.addControl('addToDictionaryAction', new FormControl(this.entity?.addToDictionaryAction)); - this.form.addControl('caseSensitive', new FormControl(!this.entity?.caseInsensitive)); - this.form.addControl('defaultReason', new FormControl({ value: null, disabled: true })); - } + revert(): void { + this.form.patchValue(this.initialFormValue); + } + + private _initializeForm(): void { + const controlsConfig = { + type: [this.entity?.type], + label: [this.entity?.label, [Validators.required, Validators.minLength(3)]], + description: [this.entity?.description], + rank: [this.entity?.rank, Validators.required], + hexColor: [this.entity?.hexColor, [Validators.required, Validators.minLength(7)]], + recommendationHexColor: [this.entity?.recommendationHexColor, [Validators.required, Validators.minLength(7)]], + hint: [!!this.entity?.hint], + hasDictionary: [!!this.entity?.hasDictionary], + }; + + if (!this.entity?.hint) { + Object.assign(controlsConfig, { + defaultReason: [{ value: null, disabled: true }], + caseSensitive: [this.entity ? !this.entity.caseInsensitive : false], + addToDictionaryAction: [this.entity?.addToDictionaryAction], }); - - if (!this.entity) { - this.form.get('label').valueChanges.subscribe((label: string) => { - this.form.get('type').setValue(this._toTechnicalName(label)); - }); - } - - if (!this._permissionsService.canEditEntities()) { - this.form.disable(); - } } + const form = this._formBuilder.group(controlsConfig); + + this.hasHexColor$ = this._colorEmpty$(form, 'hexColor'); + this.hasRecommendationHexColor$ = this._colorEmpty$(form, 'recommendationHexColor'); + this.technicalName$ = form.get('label').valueChanges.pipe(map((value: string) => this._toTechnicalName(value))); + + form.get('hint').valueChanges.subscribe(isHint => { + if (isHint) { + REDACTION_FIELDS.forEach(field => form.removeControl(field)); + } else { + form.addControl('addToDictionaryAction', new FormControl(this.entity?.addToDictionaryAction)); + form.addControl('caseSensitive', new FormControl(!this.entity?.caseInsensitive)); + form.addControl('defaultReason', new FormControl({ value: null, disabled: true })); + } + }); + + if (!this.entity) { + form.get('label').valueChanges.subscribe((label: string) => { + form.get('type').setValue(this._toTechnicalName(label)); + }); + } + + if (!this._permissionsService.canEditEntities()) { + form.disable(); + } + + this.initialFormValue = form.getRawValue(); + + this.form = form; + } + + ngOnInit() { + this._initializeForm(); } async save(): Promise { @@ -79,6 +110,8 @@ export class AddEditEntityComponent implements OnInit, OnChanges { await firstValueFrom(this._dictionaryService.addDictionary({ ...dictionary, dossierTemplateId: this.dossierTemplateId })); this._toaster.success(_('add-edit-entity.success.create')); } + this.initialFormValue = this.form.getRawValue(); + this._changeRef.markForCheck(); this._loadingService.stop(); } catch (e) { this._loadingService.stop(); @@ -97,9 +130,9 @@ export class AddEditEntityComponent implements OnInit, OnChanges { return technicalName; } - private _colorEmpty$(field: string) { - return this.form.get(field).valueChanges.pipe( - startWith(this.form.get(field).value), + private _colorEmpty$(form: FormGroup, field: string) { + return form.get(field).valueChanges.pipe( + startWith(form.get(field).value), map((value: string) => !value || value?.length === 0), ); }