From bd8a67f6bb82b5cb8b06095e7a411e7acbb5a2a7 Mon Sep 17 00:00:00 2001 From: amentis Date: Thu, 8 Feb 2024 17:23:03 +0200 Subject: [PATCH] description editor validation changes --- .../editor/description-editor.component.html | 1 + .../editor/description-editor.component.ts | 2 +- .../editor/description-editor.model.ts | 140 ++++++++++++++++-- .../form-field-set.component.ts | 20 ++- .../form-field/form-field.component.html | 34 +++-- .../form-section/form-section.component.html | 1 + .../form-section/form-section.component.ts | 2 + .../description-form.component.html | 2 +- .../description-form.component.ts | 2 + 9 files changed, 176 insertions(+), 28 deletions(-) diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.component.html b/dmp-frontend/src/app/ui/description/editor/description-editor.component.html index dcc886716..c7df370ba 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.component.html +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.component.html @@ -134,6 +134,7 @@ [TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX" [hidden]="this.step === 0" [linkToScroll]="linkToScroll" + [validationErrorModel]="editorModel.validationErrorModel" (fieldsetFocusChange)="fieldsetIdWithFocus = $event"> {{formGroup?.value | json}} diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts b/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts index f9732bd47..12fe1f764 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts @@ -783,7 +783,7 @@ export class DescriptionEditorComponent extends BaseEditor { - this.editorModel.properties = new DescriptionPropertyDefinitionEditorModel().fromModel(null, descriptionTemplate, null); + this.editorModel.properties = new DescriptionPropertyDefinitionEditorModel(this.editorModel.validationErrorModel).fromModel(null, descriptionTemplate, null); this.formGroup.setControl('properties', this.editorModel.buildProperties()); this.item.descriptionTemplate = descriptionTemplate; diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.model.ts b/dmp-frontend/src/app/ui/description/editor/description-editor.model.ts index f6fc3f81a..8ed186087 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.model.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.model.ts @@ -1,4 +1,4 @@ -import { FormControl, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; +import { FormControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; import { DescriptionStatus } from "@app/core/common/enum/description-status"; import { IsActive } from "@app/core/common/enum/is-active.enum"; import { DescriptionTemplate, DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplateSection } from "@app/core/model/description-template/description-template"; @@ -17,7 +17,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti descriptionTemplateId: Guid; status: DescriptionStatus; description: string; - properties: DescriptionPropertyDefinitionEditorModel = new DescriptionPropertyDefinitionEditorModel(); + properties: DescriptionPropertyDefinitionEditorModel = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel); tags: string[]; references: DescriptionReferenceEditorModel[]; permissions: string[]; @@ -37,7 +37,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti this.status = item.status ?? DescriptionStatus.Draft; this.description = item.description; this.tags = item.descriptionTags?.map(x => x.tag?.label); - this.properties = new DescriptionPropertyDefinitionEditorModel().fromModel(item.properties, descriptionTemplate, item.descriptionReferences); + this.properties = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel).fromModel(item.properties, descriptionTemplate, item.descriptionReferences); //if (item.references) { item.references.map(x => this.references.push(new DescriptionReferenceEditorModel().fromModel(x))); } } return this; @@ -82,6 +82,20 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti baseContext.validation = baseValidationArray; return baseContext; } + + static reApplyPropertiesValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + }): void { + + const { formGroup, validationErrorModel } = params; + const control = formGroup?.get('properties'); + DescriptionPropertyDefinitionEditorModel.reapplyValidators({ + formArray: control.get('fieldSets') as UntypedFormArray, + rootPath: `properties.`, + validationErrorModel: validationErrorModel + }); + } } export class DescriptionPropertyDefinitionEditorModel implements DescriptionPropertyDefinitionPersist { @@ -136,6 +150,15 @@ export class DescriptionPropertyDefinitionEditorModel implements DescriptionProp return baseContext; } + static reapplyValidators(params: { + formArray: UntypedFormArray, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + //TODO + } + private calculateProperties(item: DescriptionPropertyDefinition, descriptionTemplate: DescriptionTemplate, descriptionReferences: DescriptionReference[]): Map { let result: Map = new Map(); if (descriptionTemplate) ( @@ -199,7 +222,7 @@ export class DescriptionPropertyDefinitionEditorModel implements DescriptionProp } as DescriptionPropertyDefinitionFieldSetItem] } - return new DescriptionPropertyDefinitionFieldSetEditorModel().fromModel(fieldSetValue, descriptionReferences, definitionFieldSet); + return new DescriptionPropertyDefinitionFieldSetEditorModel(this.validationErrorModel).fromModel(fieldSetValue, descriptionReferences, definitionFieldSet); } } @@ -214,7 +237,7 @@ export class DescriptionPropertyDefinitionFieldSetEditorModel implements Descrip public fromModel(item: DescriptionPropertyDefinitionFieldSet, descriptionReferences: DescriptionReference[], definitionFieldSet: DescriptionTemplateFieldSet): DescriptionPropertyDefinitionFieldSetEditorModel { if (item) { - if (item.items) { item.items.map(x => this.items.push(new DescriptionPropertyDefinitionFieldSetItemEditorModel().fromModel(x, descriptionReferences, definitionFieldSet))); } + if (item.items) { item.items.map(x => this.items.push(new DescriptionPropertyDefinitionFieldSetItemEditorModel(this.validationErrorModel).fromModel(x, descriptionReferences, definitionFieldSet))); } } return this; } @@ -238,7 +261,7 @@ export class DescriptionPropertyDefinitionFieldSetEditorModel implements Descrip (item, index) => item.buildForm({ rootPath: `${rootPath}items[${index}].` }) - ), context.getValidation('items') + ), context.getValidation('items').validators ) }); } @@ -257,6 +280,21 @@ export class DescriptionPropertyDefinitionFieldSetEditorModel implements Descrip return baseContext; } + static reapplyValidators(params: { + formArray: UntypedFormArray, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + const { validationErrorModel, rootPath, formArray } = params; + formArray?.controls?.forEach( + (control, index) => DescriptionPropertyDefinitionFieldSetItemEditorModel.reapplyValidators({ + formGroup: control as UntypedFormGroup, + rootPath: `${rootPath}items[${index}].`, + validationErrorModel: validationErrorModel + }) + ); + } + } export class DescriptionPropertyDefinitionFieldSetItemEditorModel implements DescriptionPropertyDefinitionFieldSetItemPersist { @@ -273,7 +311,7 @@ export class DescriptionPropertyDefinitionFieldSetItemEditorModel implements Des if (item) { this.comment = item.comment; this.ordinal = item.ordinal; - if (item.fields) { item.fields?.forEach((value, key) => this.fields.set(key, new DescriptionFieldEditorModel().fromModel(value, definitionFieldSet?.fields?.find(x => x.id == key), descriptionReferences))); } + if (item.fields) { item.fields?.forEach((value, key) => this.fields.set(key, new DescriptionFieldEditorModel(this.validationErrorModel).fromModel(value, definitionFieldSet?.fields?.find(x => x.id == key), descriptionReferences))); } } return this; } @@ -292,7 +330,7 @@ export class DescriptionPropertyDefinitionFieldSetItemEditorModel implements Des } const formGroup = this.formBuilder.group({}); - formGroup.addControl('comment', new FormControl({ value: 'this.comment', disabled: disabled }, context.getValidation('comment').validators)); + formGroup.addControl('comment', new FormControl({ value: this.comment, disabled: disabled }, context.getValidation('comment').validators)); formGroup.addControl('ordinal', new FormControl({ value: 5, disabled: disabled }, context.getValidation('ordinal').validators)); @@ -322,6 +360,27 @@ export class DescriptionPropertyDefinitionFieldSetItemEditorModel implements Des return baseContext; } + static reapplyValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + const { formGroup, rootPath, validationErrorModel } = params; + const context = DescriptionPropertyDefinitionFieldSetItemEditorModel.createValidationContext({ + rootPath, + validationErrorModel + }); + + //TODO + + ['comment', 'ordinal'].forEach(keyField => { + const control = formGroup?.get(keyField); + control?.clearValidators(); + control?.addValidators(context.getValidation(keyField).validators); + }) + } + } export class DescriptionFieldEditorModel implements DescriptionFieldPersist { @@ -345,7 +404,7 @@ export class DescriptionFieldEditorModel implements DescriptionFieldPersist { this.dateValue = item.dateValue; this.references = descriptionReferences?.filter(x => x.data?.fieldId == descriptionTemplateField?.id && x.isActive == IsActive.Active).map(x => x.reference); this.reference = descriptionReferences?.find(x => x.data?.fieldId == descriptionTemplateField?.id && x.isActive == IsActive.Active)?.reference; - this.externalIdentifier = new DescriptionExternalIdentifierEditorModel().fromModel(item.externalIdentifier); + this.externalIdentifier = new DescriptionExternalIdentifierEditorModel(this.validationErrorModel).fromModel(item.externalIdentifier); } return this; } @@ -388,6 +447,31 @@ export class DescriptionFieldEditorModel implements DescriptionFieldPersist { baseContext.validation = baseValidationArray; return baseContext; } + + static reapplyValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + const { formGroup, rootPath, validationErrorModel } = params; + const context = DescriptionPropertyDefinitionFieldSetItemEditorModel.createValidationContext({ + rootPath, + validationErrorModel + }); + + ['textValue', 'textListValue', 'dateValue'].forEach(keyField => { + const control = formGroup?.get(keyField); + control?.clearValidators(); + control?.addValidators(context.getValidation(keyField).validators); + }) + + DescriptionExternalIdentifierEditorModel.reapplyValidators({ + formGroup: formGroup?.get('externalIdentifier') as UntypedFormGroup, + rootPath: `${rootPath}externalIdentifier.`, + validationErrorModel: validationErrorModel + }); + } } export class DescriptionExternalIdentifierEditorModel implements DescriptionExternalIdentifierPersist { @@ -440,6 +524,25 @@ export class DescriptionExternalIdentifierEditorModel implements DescriptionExte baseContext.validation = baseValidationArray; return baseContext; } + + static reapplyValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + const { formGroup, rootPath, validationErrorModel } = params; + const context = DescriptionExternalIdentifierEditorModel.createValidationContext({ + rootPath, + validationErrorModel + }); + + ['identifier', 'type'].forEach(keyField => { + const control = formGroup?.get(keyField); + control?.clearValidators(); + control?.addValidators(context.getValidation(keyField).validators); + }); + } } export class DescriptionReferenceEditorModel implements DescriptionReferencePersist { @@ -496,4 +599,23 @@ export class DescriptionReferenceEditorModel implements DescriptionReferencePers baseContext.validation = baseValidationArray; return baseContext; } + + static reapplyValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + rootPath: string + }): void { + + const { formGroup, rootPath, validationErrorModel } = params; + const context = DescriptionExternalIdentifierEditorModel.createValidationContext({ + rootPath, + validationErrorModel + }); + + ['id', 'reference'].forEach(keyField => { + const control = formGroup?.get(keyField); + control?.clearValidators(); + control?.addValidators(context.getValidation(keyField).validators); + }); + } } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/description/editor/description-form/components/form-field-set/form-field-set.component.ts b/dmp-frontend/src/app/ui/description/editor/description-form/components/form-field-set/form-field-set.component.ts index d9687a1e7..6feef20bb 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-form/components/form-field-set/form-field-set.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-form/components/form-field-set/form-field-set.component.ts @@ -9,6 +9,7 @@ import { VisibilityRulesService } from '../../visibility-rules/visibility-rules. import { DescriptionPropertyDefinitionEditorModel, DescriptionPropertyDefinitionFieldSetEditorModel } from '../../../description-editor.model'; import { FormFieldSetEditorDialogComponent } from './dialog-editor/form-fieldset-editor-dialog.component'; import { cloneAbstractControl } from '@app/utilities/enhancers/utils'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; @Component({ selector: 'app-description-form-field-set', @@ -43,6 +44,7 @@ export class DescriptionFormFieldSetComponent extends BaseComponent { @Input() tableRow: boolean = false; @Input() showTitle: boolean = true; @Input() placeholderTitle: boolean = false; + @Input() validationErrorModel: ValidationErrorModel; constructor( private dialog: MatDialog, @@ -72,9 +74,9 @@ export class DescriptionFormFieldSetComponent extends BaseComponent { return; } - const item: DescriptionPropertyDefinitionFieldSetEditorModel = new DescriptionPropertyDefinitionEditorModel().calculateFieldSetProperties(this.fieldSet, null, null); + const item: DescriptionPropertyDefinitionFieldSetEditorModel = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel).calculateFieldSetProperties(this.fieldSet, null, null); //TODO: akis - formArray.push((item.buildForm().get('items') as UntypedFormArray).at(0)); + formArray.push((item.buildForm({rootPath: ''}).get('items') as UntypedFormArray).at(0)); } deleteMultiplicityField(fieldSetIndex: number): void { @@ -86,12 +88,14 @@ export class DescriptionFormFieldSetComponent extends BaseComponent { //TODO: akis //Reapply validators - // DmpBlueprintEditorModel.reApplySectionValidators( - // { - // formGroup: this.formGroup, - // validationErrorModel: this.editorModel.validationErrorModel - // } - // ); + DescriptionPropertyDefinitionFieldSetEditorModel.reapplyValidators( + { + formArray: this.propertiesFormGroup.get('items') as UntypedFormArray, + validationErrorModel: this.validationErrorModel, + //TODO + rootPath: '' + } + ); formArray.markAsDirty(); } diff --git a/dmp-frontend/src/app/ui/description/editor/description-form/components/form-field/form-field.component.html b/dmp-frontend/src/app/ui/description/editor/description-form/components/form-field/form-field.component.html index 585d42774..8c1d20051 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-form/components/form-field/form-field.component.html +++ b/dmp-frontend/src/app/ui/description/editor/description-form/components/form-field/form-field.component.html @@ -7,8 +7,10 @@
{{fieldSet.extendedDescription}}
+ {{propertiesFormGroup.value | json}} + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} {{'GENERAL.VALIDATION.URL.MESSAGE' | translate}} @@ -19,11 +21,13 @@ + {{propertiesFormGroup?.get(field.id).get('textListValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} {{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT" | translate }} @@ -38,6 +42,7 @@ {{opt.label}} + {{propertiesFormGroup?.get(field.id).get('textListValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} @@ -45,6 +50,7 @@ {{opt.label}} + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} @@ -56,11 +62,13 @@ + {{propertiesFormGroup?.get(field.id).get('textListValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} {{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT" | translate }} @@ -73,11 +81,13 @@ + {{propertiesFormGroup?.get(field.id).get('textListValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} {{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT" | translate }} @@ -90,11 +100,13 @@ + {{propertiesFormGroup?.get(field.id).get('textListValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} {{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.EXTERNAL-SOURCE-HINT" | translate }} @@ -104,12 +116,14 @@
{{field.data.label}} + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}}
+ {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} @@ -118,6 +132,7 @@
+ {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -146,6 +161,7 @@ {{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.ACTIONS.YES" | translate }} {{ "TYPES.DATASET-PROFILE-COMBO-BOX-TYPE.ACTIONS.NO" | translate }} + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} @@ -155,6 +171,7 @@
{{option.label}} + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} @@ -165,9 +182,8 @@ - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - + {{propertiesFormGroup?.get(field.id).get('dateValue').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -381,8 +397,8 @@
- {{'GENERAL.VALIDATION.REQUIRED' | translate}} - + {{propertiesFormGroup?.get(field.id).get('externalIdentifier')?.get('identifier').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} @@ -390,8 +406,8 @@ {{ type.name }} - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - + {{propertiesFormGroup?.get(field.id).get('externalIdentifier')?.get('type').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
@@ -401,8 +417,8 @@ - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - + {{propertiesFormGroup?.get(field.id).get('textValue').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/description/editor/description-form/components/form-section/form-section.component.html b/dmp-frontend/src/app/ui/description/editor/description-form/components/form-section/form-section.component.html index ab714539b..34b3a18fd 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-form/components/form-section/form-section.component.html +++ b/dmp-frontend/src/app/ui/description/editor/description-form/components/form-section/form-section.component.html @@ -19,6 +19,7 @@ [fieldSet]="fieldSet" [path]="path + '.' + (i+1)" [visibilityRulesService]="visibilityRulesService" + [validationErrorModel]="validationErrorModel" [isChild]="false"> diff --git a/dmp-frontend/src/app/ui/description/editor/description-form/components/form-section/form-section.component.ts b/dmp-frontend/src/app/ui/description/editor/description-form/components/form-section/form-section.component.ts index 0c95f1c26..55eabfff2 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-form/components/form-section/form-section.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-form/components/form-section/form-section.component.ts @@ -16,6 +16,7 @@ import { ToCEntry } from '../../../table-of-contents/models/toc-entry'; import { ToCEntryType } from '../../../table-of-contents/models/toc-entry-type.enum'; import { LinkToScroll } from '../../../table-of-contents/table-of-contents.component'; import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; @Component({ @@ -42,6 +43,7 @@ export class DescriptionFormSectionComponent extends BaseComponent implements On @Output() askedToScroll = new EventEmitter(); tocentriesType = ToCEntryType; @Input() TOCENTRY_ID_PREFIX = ""; + @Input() validationErrorModel: ValidationErrorModel; constructor( private changeDetector: ChangeDetectorRef diff --git a/dmp-frontend/src/app/ui/description/editor/description-form/description-form.component.html b/dmp-frontend/src/app/ui/description/editor/description-form/description-form.component.html index a9ec9f91f..41d080c5c 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-form/description-form.component.html +++ b/dmp-frontend/src/app/ui/description/editor/description-form/description-form.component.html @@ -15,7 +15,7 @@
- +
diff --git a/dmp-frontend/src/app/ui/description/editor/description-form/description-form.component.ts b/dmp-frontend/src/app/ui/description/editor/description-form/description-form.component.ts index 3b711a70e..35116709c 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-form/description-form.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-form/description-form.component.ts @@ -6,6 +6,7 @@ import { BaseComponent } from '@common/base/base.component'; import { LinkToScroll } from '../table-of-contents/table-of-contents.component'; import { Rule } from './visibility-rules/models/rule'; import { VisibilityRulesService } from './visibility-rules/visibility-rules.service'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; @Component({ selector: 'app-description-form', @@ -31,6 +32,7 @@ export class DescriptionFormComponent extends BaseComponent implements OnInit, A @Input() TOCENTRY_ID_PREFIX = ""; @Output() visibilityRulesInstance = new EventEmitter(); + @Input() validationErrorModel: ValidationErrorModel; // public hiddenEntriesIds: string[] = [];