diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/entities/xmlmodels/dmpprofiledefinition/Section.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/entities/xmlmodels/dmpprofiledefinition/Section.java index bcb128653..5a5da9a85 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/entities/xmlmodels/dmpprofiledefinition/Section.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/entities/xmlmodels/dmpprofiledefinition/Section.java @@ -20,6 +20,7 @@ public class Section implements XmlSerializable
{ private String description; private Integer ordinal; private List fields; + private Boolean hasTemplates; private List descriptionTemplates; public UUID getId() { @@ -57,6 +58,13 @@ public class Section implements XmlSerializable
{ this.fields = fields; } + public Boolean getHasTemplates() { + return hasTemplates; + } + public void setHasTemplates(Boolean hasTemplates) { + this.hasTemplates = hasTemplates; + } + public List getDescriptionTemplates() { return descriptionTemplates; } @@ -71,6 +79,7 @@ public class Section implements XmlSerializable
{ rootElement.setAttribute("label", this.label); rootElement.setAttribute("description", this.description); rootElement.setAttribute("ordinal", String.valueOf(this.ordinal)); + rootElement.setAttribute("hasTemplates", String.valueOf(this.hasTemplates)); List temp = this.fields.stream().filter(f -> f.getCategory().equals(FieldCategory.SYSTEM)).collect(Collectors.toList()); List systemFieldsList = temp.stream().map(FieldModel::toSystemField).collect(Collectors.toList()); Element systemFields = doc.createElement("systemFields"); @@ -100,6 +109,7 @@ public class Section implements XmlSerializable
{ this.label = item.getAttribute("label"); this.description = item.getAttribute("description"); this.ordinal = Integer.valueOf(item.getAttribute("ordinal")); + this.hasTemplates = Boolean.valueOf(item.getAttribute("hasTemplates")); this.fields = new LinkedList<>(); Element systemFields = (Element) XmlBuilder.getNodeFromListByTagName(item.getChildNodes(), "systemFields"); if (systemFields != null) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/entities/xmlmodels/dmpprofiledefinition/types/SystemFieldType.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/entities/xmlmodels/dmpprofiledefinition/types/SystemFieldType.java index 852680213..d7c36023a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/entities/xmlmodels/dmpprofiledefinition/types/SystemFieldType.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/entities/xmlmodels/dmpprofiledefinition/types/SystemFieldType.java @@ -12,8 +12,7 @@ public enum SystemFieldType { GRANT(7), PROJECT(8), LICENSE(9), - ACCESS_RIGHTS(10), - DESCRIPTION_TEMPLATES(11); + ACCESS_RIGHTS(10); private int type; @@ -49,8 +48,6 @@ public enum SystemFieldType { return LICENSE; case 10: return ACCESS_RIGHTS; - case 11: - return DESCRIPTION_TEMPLATES; default: throw new RuntimeException("Unsupported System Field Type"); } diff --git a/dmp-backend/web/src/main/resources/documents/h2020.docx b/dmp-backend/web/src/main/resources/documents/h2020.docx index c821032e1..b0e721ab0 100644 Binary files a/dmp-backend/web/src/main/resources/documents/h2020.docx and b/dmp-backend/web/src/main/resources/documents/h2020.docx differ diff --git a/dmp-frontend/src/app/core/model/dmp/dmp-blueprint/dmp-blueprint.ts b/dmp-frontend/src/app/core/model/dmp/dmp-blueprint/dmp-blueprint.ts index d9f4f4f36..eda8fd506 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp-blueprint/dmp-blueprint.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp-blueprint/dmp-blueprint.ts @@ -18,6 +18,7 @@ export interface SectionDmpBlueprint { description: string; ordinal: number; fields: FieldInSection[]; + hasTemplates: boolean; descriptionTemplates?: DescriptionTemplatesInSection[]; } diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts index f85a1a0d3..b4b9496af 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.module.ts @@ -11,6 +11,7 @@ import { DmpProfileCriteriaComponent } from './listing/criteria/dmp-profile-crit import { DmpProfileListingComponent } from './listing/dmp-profile-listing.component'; import { NgxDropzoneModule } from "ngx-dropzone"; import { DragDropModule } from '@angular/cdk/drag-drop'; +import { AutoCompleteModule } from "@app/library/auto-complete/auto-complete.module"; @NgModule({ imports: [ @@ -20,7 +21,8 @@ import { DragDropModule } from '@angular/cdk/drag-drop'; ConfirmationDialogModule, DmpProfileRoutingModule, NgxDropzoneModule, - DragDropModule + DragDropModule, + AutoCompleteModule ], declarations: [ DmpProfileEditorComponent, diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-blueprint-editor.model.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-blueprint-editor.model.ts index a2ad7e5f2..c90354afd 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-blueprint-editor.model.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-blueprint-editor.model.ts @@ -1,5 +1,8 @@ -import { FormBuilder, FormGroup } from "@angular/forms"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, FieldCategory, FieldInSection, SectionDmpBlueprint } from "@app/core/model/dmp/dmp-blueprint/dmp-blueprint"; +import { BackendErrorValidator } from "@common/forms/validation/custom-validator"; +import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model"; +import { ValidationContext } from "@common/forms/validation/validation-context"; export class DmpBlueprintEditor { public id: string; @@ -8,6 +11,7 @@ export class DmpBlueprintEditor { public status: number; public created: Date; public modified: Date; + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); fromModel(item: DmpBlueprint): DmpBlueprintEditor { this.id = item.id; @@ -19,18 +23,30 @@ export class DmpBlueprintEditor { return this; } - buildForm(): FormGroup { + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } const formGroup = new FormBuilder().group({ - id: [this.id], - label: [this.label], - status: [this.status], - created: [this.created], - modified: [this.modified] + id: [{ value: this.id, disabled: disabled }, context.getValidation('id')], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label')], + status: [{ value: this.status, disabled: disabled }, context.getValidation('status')], + created: [{ value: this.created, disabled: disabled }, context.getValidation('created')], + modified: [{ value: this.modified, disabled: disabled }, context.getValidation('modified')], }); formGroup.addControl('definition', this.definition.buildForm()); return formGroup; } + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); + baseContext.validation.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] }); + baseContext.validation.push({ key: 'definition', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'definition')] }); + baseContext.validation.push({ key: 'created', validators: [] }); + baseContext.validation.push({ key: 'modified', validators: [] }); + return baseContext; + } + } export class DmpBlueprintDefinitionEditor { @@ -61,7 +77,9 @@ export class SectionDmpBlueprintEditor { public description: string; public ordinal: number; public fields: FieldInSectionEditor[] = new Array(); + public hasTemplates: boolean; public descriptionTemplates: DescriptionTemplatesInSectionEditor[] = new Array(); + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); fromModel(item: SectionDmpBlueprint): SectionDmpBlueprintEditor { this.id = item.id; @@ -69,16 +87,19 @@ export class SectionDmpBlueprintEditor { this.description = item.description; this.ordinal = item.ordinal; if (item.fields) { item.fields.map(x => this.fields.push(new FieldInSectionEditor().fromModel(x))); } + this.hasTemplates = item.hasTemplates; if (item.descriptionTemplates) { item.descriptionTemplates.map(x => this.descriptionTemplates.push(new DescriptionTemplatesInSectionEditor().fromModel(x))); } return this; } - buildForm(): FormGroup { + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } const formGroup = new FormBuilder().group({ - id: [this.id], - label: [this.label], - description: [this.description], - ordinal: [this.ordinal] + id: [{ value: this.id, disabled: disabled }, context.getValidation('id')], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label')], + description: [{ value: this.description, disabled: disabled }, context.getValidation('description')], + ordinal: [{ value: this.ordinal, disabled: disabled }, context.getValidation('ordinal')], + hasTemplates: [{ value: this.hasTemplates, disabled: disabled }, context.getValidation('hasTemplates')] }); const formBuilder = new FormBuilder(); const fieldsFormArray = new Array(); @@ -95,6 +116,17 @@ export class SectionDmpBlueprintEditor { formGroup.addControl('descriptionTemplates', formBuilder.array(descriptionTemplatesFormArray)); return formGroup; } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); + baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] }); + baseContext.validation.push({ key: 'ordinal', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'ordinal')] }); + baseContext.validation.push({ key: 'hasTemplates', validators: [BackendErrorValidator(this.validationErrorModel, 'hasTemplates')] }); + baseContext.validation.push({ key: 'descriptionTemplates', validators: [BackendErrorValidator(this.validationErrorModel, 'descriptionTemplates')] }); + return baseContext; + } } export class FieldInSectionEditor { @@ -106,6 +138,7 @@ export class FieldInSectionEditor { public description: string; public required: boolean; public ordinal: number; + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); fromModel(item: FieldInSection): FieldInSectionEditor { this.id = item.id; @@ -119,19 +152,33 @@ export class FieldInSectionEditor { return this; } - buildForm(): FormGroup { + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } const formGroup = new FormBuilder().group({ - id: [this.id], - category: [this.category], - type: [this.type], - label: [this.label], - placeholder: [this.placeholder], - description: [this.description], - required: [this.required], - ordinal: [this.ordinal] + id: [{ value: this.id, disabled: disabled }, context.getValidation('id')], + category: [{ value: this.category, disabled: disabled }, context.getValidation('category')], + type: [{ value: this.type, disabled: disabled }, context.getValidation('type')], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label')], + placeholder: [{ value: this.placeholder, disabled: disabled }, context.getValidation('placeholder')], + description: [{ value: this.description, disabled: disabled }, context.getValidation('description')], + required: [{ value: this.required, disabled: disabled }, context.getValidation('required')], + ordinal: [{ value: this.ordinal, disabled: disabled }, context.getValidation('ordinal')] }); return formGroup; } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); + baseContext.validation.push({ key: 'category', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'category')] }); + baseContext.validation.push({ key: 'type', validators: [BackendErrorValidator(this.validationErrorModel, 'type')] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); + baseContext.validation.push({ key: 'placeholder', validators: [BackendErrorValidator(this.validationErrorModel, 'placeholder')] }); + baseContext.validation.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] }); + baseContext.validation.push({ key: 'required', validators: [BackendErrorValidator(this.validationErrorModel, 'required')] }); + baseContext.validation.push({ key: 'ordinal', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'ordinal')] }); + return baseContext; + } } export class DescriptionTemplatesInSectionEditor { @@ -140,6 +187,7 @@ export class DescriptionTemplatesInSectionEditor { public label: string; public minMultiplicity: number; public maxMultiplicity: number; + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); fromModel(item: DescriptionTemplatesInSection): DescriptionTemplatesInSectionEditor { this.id = item.id; @@ -150,16 +198,27 @@ export class DescriptionTemplatesInSectionEditor { return this; } - buildForm(): FormGroup { + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } const formGroup = new FormBuilder().group({ - id: [this.id], - descriptionTemplateId: [this.descriptionTemplateId], - label: [this.label], - minMultiplicity: [this.minMultiplicity], - maxMultiplicity: [this.maxMultiplicity] + id: [{ value: this.id, disabled: disabled }, context.getValidation('id')], + descriptionTemplateId: [{ value: this.descriptionTemplateId, disabled: disabled }, context.getValidation('descriptionTemplateId')], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label')], + minMultiplicity: [{ value: this.minMultiplicity, disabled: disabled }, context.getValidation('minMultiplicity')], + maxMultiplicity: [{ value: this.maxMultiplicity, disabled: disabled }, context.getValidation('maxMultiplicity')] }); return formGroup; } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); + baseContext.validation.push({ key: 'descriptionTemplateId', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'descriptionTemplateId')] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); + baseContext.validation.push({ key: 'minMultiplicity', validators: [BackendErrorValidator(this.validationErrorModel, 'minMultiplicity')] }); + baseContext.validation.push({ key: 'maxMultiplicity', validators: [BackendErrorValidator(this.validationErrorModel, 'maxMultiplicity')] }); + return baseContext; + } } // export class ExtraFieldsInSectionEditor { diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html index 09ec4be95..65f6940c2 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html @@ -18,10 +18,10 @@
+ [disabled]="!this.isFormValid()" type="button">{{'DMP-PROFILE-EDITOR.ACTIONS.FINALIZE' | translate }}
-
+ - + +
+
+ +
+
+ + + Section {{sectionIndex + 1}} + drag_indicator + +
+
+
+ + Section name + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+ + Section description + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} +
- -
- -
-
- -
-
-
-
-
- {{fieldIndex + 1}} -
-
- drag_indicator -
-
-
- -
- - System Field - - -
-
- - Label - - -
-
- - Placeholder - - -
-
- - Description - - -
-
- Required -
-
- delete - {{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}} -
-
- - -
- - Type - - - {{getExtraFieldTypeValue(extraFieldType)}} - - - -
-
- - Label - - -
-
- - Placeholder - - -
-
- - Description - - -
-
- - Required - -
-
- delete - {{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}} -
-
- -
-
-
-
-
- -
- - - - - -
-
-
-
- - - - - - -
-
+ +
+ +
+
+ +
+
+
+
+
+ {{fieldIndex + 1}} +
+
+ drag_indicator +
+
+
+ +
+ + System Field + + +
+
+ + Label + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+ + Placeholder + + +
+
+ + Description + + +
+
+ Required +
+
+ delete + {{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}} +
+
+ + +
+ + Type + + + {{getExtraFieldTypeValue(extraFieldType)}} + + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+ + Label + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+ + Placeholder + + +
+
+ + Description + + +
+
+ + Required + +
+
+ delete + {{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}} +
+
+ +
+
+
+
+
+ +
+ + - --> -
-
-
- -
- delete - {{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}} + +
+
+
+ + Description Templates + +
+
+
+ +
+
+
+ + Description Templates + + + + +
+
+
+ +
+ +
+
+
+ + Label + + +
+
+ + Min Multiplicity + + +
+
+ + Max Multiplicity + + +
+
+
+
+
+
+ +
+
+ +
+ delete + {{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}} +
-
- - + + - +
- +
@@ -386,7 +378,7 @@ -->
-
diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts index b8cf5cd85..5c2c65ad1 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component } from '@angular/core'; +import { AfterViewInit, Component, ViewChild } from '@angular/core'; import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { DmpProfileFieldDataType } from '@app/core/common/enum/dmp-profile-field-type'; @@ -34,9 +34,11 @@ import { AvailableProfilesComponent } from '@app/ui/dmp/editor/available-profile import { DatasetPreviewDialogComponent } from '@app/ui/dmp/dataset-preview/dataset-preview-dialog.component'; import { CdkDragDrop, CdkDropList, CdkDrag, moveItemInArray } from '@angular/cdk/drag-drop'; import { DmpBlueprint, DmpBlueprintDefinition, ExtraFieldType, FieldCategory, SystemFieldType } from '@app/core/model/dmp/dmp-blueprint/dmp-blueprint'; -import { DmpBlueprintEditor } from './dmp-blueprint-editor.model'; +import { DescriptionTemplatesInSectionEditor, DmpBlueprintEditor, FieldInSectionEditor, SectionDmpBlueprintEditor } from './dmp-blueprint-editor.model'; import { Guid } from '@common/types/guid'; import { isNullOrUndefined } from '@app/utilities/enhancers/utils'; +import { DmpBlueprintListing } from '@app/core/model/dmp/dmp-blueprint/dmp-blueprint-listing'; +import { FormValidationErrorsDialogComponent } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component'; @Component({ @@ -73,6 +75,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie {label: 'Access Rights', type: SystemFieldType.ACCESS_RIGHTS} ]; selectedSystemFields: string[] = []; + systemFieldListPerSection: Array> = new Array(); constructor( private dmpProfileService: DmpProfileService, @@ -112,12 +115,13 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie if (this.dmpProfileId != null) { this.isNew = false; - this.dmpProfileService.getSingle(this.dmpProfileId).pipe(map(data => data as DmpProfile)) + this.dmpProfileService.getSingleBlueprint(this.dmpProfileId).pipe(map(data => data as DmpBlueprint)) .pipe(takeUntil(this._destroyed)) .subscribe(data => { - this.dmpProfileModel = new DmpProfileEditorModel().fromModel(data); - this.formGroup = this.dmpProfileModel.buildForm(); - if (this.dmpProfileModel.status == DmpProfileStatus.Finalized) { + this.dmpBlueprintModel = new DmpBlueprintEditor().fromModel(data); + this.formGroup = this.dmpBlueprintModel.buildForm(); + this.buildSystemFields(); + if (this.dmpBlueprintModel.status == DmpProfileStatus.Finalized) { this.formGroup.disable(); this.viewOnly = true } @@ -133,6 +137,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie setTimeout(() => { // this.formGroup = this.dmpProfileModel.buildForm(); // this.addField(); + this.dmpBlueprintModel.status = DmpProfileStatus.Draft; this.formGroup = this.dmpBlueprintModel.buildForm(); }); this.breadCrumbs = observableOf([{ @@ -143,10 +148,20 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie } }); - this.initDmpBlueptintForm(); - } + buildSystemFields(){ + const sections = this.sectionsArray().controls.length; + for(let i = 0; i < sections; i++){ + let systemFieldsInSection = new Array(); + this.fieldsArray(i).controls.forEach((field) => { + if((field.get('category').value == FieldCategory.SYSTEM || field.get('category').value == 'SYSTEM')){ + systemFieldsInSection.push(this.fieldList.find(f => f.type == field.get('type').value).label); + } + }) + this.systemFieldListPerSection.push(systemFieldsInSection); + } + } filterProfiles(value: string): Observable { const request = new DataTableRequest(null, null, { fields: ['+label'] }); @@ -156,33 +171,17 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie return this._service.searchDMPProfiles(request); } - initDmpBlueptintForm(): void { - this.dmpBlueprintsFormGroup = this.fb.group({ - label: this.fb.control(''), - sections: this.fb.array([]) - }); - } - sectionsArray(): FormArray { - return this.dmpBlueprintsFormGroup.get('sections') as FormArray; - } - - initSection(ordinal: number): FormGroup { - return this.fb.group({ - id: this.fb.control(Guid.create().toString()), - label: this.fb.control(''), - description: this.fb.control(''), - ordinal: this.fb.control(ordinal), - fields: this.fb.array([]), - //systemFields: this.fb.array([]), - descriptionTemplates: this.fb.control(''), - // this.fb.array([this.initDescriptionTemplate()]), - //extraFields: this.fb.array([]) - }); + //return this.dmpBlueprintsFormGroup.get('sections') as FormArray; + return this.formGroup.get('definition').get('sections') as FormArray; } addSection(): void { - this.sectionsArray().push(this.initSection(this.sectionsArray().length)); + const section: SectionDmpBlueprintEditor = new SectionDmpBlueprintEditor(); + section.id = Guid.create().toString(); + section.ordinal = this.sectionsArray().length + 1; + section.hasTemplates = false; + this.sectionsArray().push(section.buildForm()); } removeSection(sectionIndex: number): void { @@ -192,22 +191,17 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie fieldsArray(sectionIndex: number): FormArray { return this.sectionsArray().at(sectionIndex).get('fields') as FormArray; } - - initField(fieldCategory: FieldCategory, fieldType?: number): FormGroup { - return this.fb.group({ - id: this.fb.control(Guid.create().toString()), - category: this.fb.control(fieldCategory), - label: this.fb.control(''), - placeholder: this.fb.control(''), - description: this.fb.control(''), - type: (isNullOrUndefined(fieldType)) ? this.fb.control('') : this.fb.control(fieldType), - required: (!isNullOrUndefined(fieldType) && (fieldType == 0 || fieldType == 1)) ? this.fb.control(true) : this.fb.control(false), - ordinal: this.fb.control('') - }); - } addField(sectionIndex: number, fieldCategory: FieldCategory, fieldType?: number): void { - this.fieldsArray(sectionIndex).push(this.initField(fieldCategory, fieldType)); + const field: FieldInSectionEditor = new FieldInSectionEditor(); + field.id = Guid.create().toString(); + field.ordinal = this.fieldsArray(sectionIndex).length + 1; + field.category = fieldCategory; + if(!isNullOrUndefined(fieldType)){ + field.type = fieldType + } + field.required = (!isNullOrUndefined(fieldType) && (fieldType == 0 || fieldType == 1)) ? true : false; + this.fieldsArray(sectionIndex).push(field.buildForm()); } removeField(sectionIndex: number, fieldIndex: number): void { @@ -231,7 +225,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie } addSystemField(sectionIndex: number, systemField?: SystemFieldType): void { - this.fieldsArray(sectionIndex).push(this.initField(FieldCategory.SYSTEM, systemField)); + this.addField(sectionIndex, FieldCategory.SYSTEM, systemField); } transfromEnumToString(type: SystemFieldType): string{ @@ -255,7 +249,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie for (let s in this.sectionsArray().controls) { if (i != sectionIndex) { for (let f of this.fieldsArray(i).controls) { - if (f.get('category').value == FieldCategory.SYSTEM && f.get('type').value == systemField) { + if ((f.get('category').value == FieldCategory.SYSTEM || f.get('category').value == 'SYSTEM') && f.get('type').value == systemField) { return true; } } @@ -272,7 +266,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie removeSystemField(sectionIndex: number, systemField: SystemFieldType): void { let i = 0; for(let f of this.fieldsArray(sectionIndex).controls){ - if(f.get('category').value == FieldCategory.SYSTEM && f.get('type').value == systemField){ + if((f.get('category').value == FieldCategory.SYSTEM || f.get('category').value == 'SYSTEM') && f.get('type').value == systemField){ this.fieldsArray(sectionIndex).removeAt(i); return; } @@ -284,15 +278,6 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie return this.sectionsArray().at(sectionIndex).get('descriptionTemplates') as FormArray; } - initDescriptionTemplate(): FormGroup { - return this.fb.group({ - descriptionTemplateId: this.fb.control(''), - label: this.fb.control(''), - minMultiplicity: this.fb.control(''), - maxMultiplicity: this.fb.control('') - }); - } - addDescriptionTemplate(descriptionTemplate, sectionIndex: number): void { this.descriptionTemplatesArray(sectionIndex).push(this.fb.group({ label: this.fb.control(descriptionTemplate.value) @@ -305,22 +290,10 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie extraFieldsArray(sectionIndex: number): FormArray { return this.sectionsArray().at(sectionIndex).get('extraFields') as FormArray; - } + } - initExtraField(): FormGroup { - return this.fb.group({ - id: this.fb.control(Guid.create().toString()), - label: this.fb.control(''), - placeholder: this.fb.control(''), - description: this.fb.control(''), - type: this.fb.control(''), - required: this.fb.control(false), - ordinal: this.fb.control('') - }); - } - addExtraField(sectionIndex: number): void { - this.fieldsArray(sectionIndex).push(this.initField(FieldCategory.EXTRA)); + this.addField(sectionIndex, FieldCategory.EXTRA); } removeExtraField(sectionIndex: number, fieldIndex: number): void { @@ -343,9 +316,6 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie } } - onSubmitTest(): void { - } - drop(event: CdkDragDrop, sectionIndex: number) { moveItemInArray(this.fieldsArray(sectionIndex).controls, event.previousIndex, event.currentIndex); moveItemInArray(this.fieldsArray(sectionIndex).value, event.previousIndex, event.currentIndex); @@ -371,86 +341,58 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie // this.dmpBlueprintsFormGroup.reset(); // } - canGoUp(index: number): boolean { - return index > 0; - } - - canGoDown(index: number): boolean { - return index < (this.sectionsArray().length - 1); - } - onRemoveTemplate(event, sectionIndex: number) { - // let found = false; - // const profiles = this.descriptionTemplatesArray(sectionIndex).value;//this.formGroup.get('profiles').value; - // this.formGroup.get('datasets')['controls'].forEach(element => { - // if (element.get('profile').value.id === event.id) { - // found = true; - // this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-REMOVE-TEMPLATE'), SnackBarNotificationLevel.Success); - // } - // }); - // if (found) { - // this.formGroup.get('profiles').setValue(profiles); - // this.profilesAutoCompleteConfiguration = { - // filterFn: this.filterProfiles.bind(this), - // initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), - // displayFn: (item) => item['label'], - // titleFn: (item) => item['label'], - // subtitleFn: (item) => item['description'], - // popupItemActionIcon: 'visibility' - // }; - - // } + const profiles = this.descriptionTemplatesArray(sectionIndex).controls; + const foundIndex = profiles.findIndex(profile => profile.get('descriptionTemplateId').value === event.id); + foundIndex !== -1 && this.descriptionTemplatesArray(sectionIndex).removeAt(foundIndex); } - onPreviewTemplate(event, sectionIndex: number) { - const dialogRef = this.dialog.open(DatasetPreviewDialogComponent, { - width: '590px', - minHeight: '200px', - restoreFocus: false, - data: { - template: event - }, - panelClass: 'custom-modalbox' - }); - dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { - if (result) { - let profiles = this.descriptionTemplatesArray(sectionIndex).value;//this.formGroup.get('profiles').value; - profiles.push(event); - this.descriptionTemplatesArray(sectionIndex).setValue(profiles);//this.formGroup.get('profiles').setValue(profiles); - this.profilesAutoCompleteConfiguration = { - filterFn: this.filterProfiles.bind(this), - initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), - displayFn: (item) => item['label'], - titleFn: (item) => item['label'], - subtitleFn: (item) => item['description'], - popupItemActionIcon: 'visibility' - }; - } - }); - } - onOptionSelected(sectionIndex: number){ - try{ - const profiles = this.descriptionTemplatesArray(sectionIndex).value as {id:string, label:string}[];//this.formGroup.get('profiles').value as {id:string, label:string}[]; - const profileCounts: Map = new Map(); - profiles.forEach((value) => profileCounts.set(value.id, (profileCounts.get(value.id) !== undefined ? profileCounts.get(value.id): 0 ) + 1)); - const duplicateProfiles = profiles.filter((value) => { - let isOk = profileCounts.get(value.id) > 1; - if (isOk) { - profileCounts.set(value.id, 0); - } - return isOk; - }); - duplicateProfiles.forEach((value) => profiles.splice(profiles.lastIndexOf(value), 1)); - profiles.sort((a,b)=> a.label.localeCompare(b.label)); - } - catch{ - console.info('Could not sort Dataset Templates') - } + // onPreviewTemplate(event, sectionIndex: number) { + // const dialogRef = this.dialog.open(DatasetPreviewDialogComponent, { + // width: '590px', + // minHeight: '200px', + // restoreFocus: false, + // data: { + // template: event + // }, + // panelClass: 'custom-modalbox' + // }); + // dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + // if (result) { + // let profiles = this.sectionsArray().at(sectionIndex).get('descriptionTemplates').value;//this.formGroup.get('profiles').value; + // const profile: DescriptionTemplatesInSectionEditor = new DescriptionTemplatesInSectionEditor(); + // profile.id = Guid.create().toString(); + // profile.descriptionTemplateId = event.id; + // profile.label = event.label; + // profiles.push(profile.buildForm()); + // this.sectionsArray().at(sectionIndex).get('descriptionTemplates').setValue(profiles);//this.formGroup.get('profiles').setValue(profiles); + // this.profilesAutoCompleteConfiguration = { + // filterFn: this.filterProfiles.bind(this), + // initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), + // displayFn: (item) => item['label'], + // titleFn: (item) => item['label'], + // subtitleFn: (item) => item['description'], + // popupItemActionIcon: 'visibility' + // }; + // } + // }); + // } + + onOptionSelected(item, sectionIndex){ + const profile: DescriptionTemplatesInSectionEditor = new DescriptionTemplatesInSectionEditor(); + profile.id = Guid.create().toString(); + profile.descriptionTemplateId = item.id; + profile.label = item.label; + this.descriptionTemplatesArray(sectionIndex).push(profile.buildForm()); } formSubmit(): void { this.formService.touchAllFormFields(this.formGroup); if (!this.isFormValid()) { return; } + if(!this.hasDescriptionTemplates()) { + this.showValidationErrorsDialog(undefined, ["At least one section should have description templates."]); + return; + } this.onSubmit(); } @@ -458,8 +400,27 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie return this.formGroup.valid; } + hasDescriptionTemplates(): boolean { + const dmpBlueprint: DmpBlueprint = this.formGroup.value; + return (dmpBlueprint.definition.sections.filter(s => s.hasTemplates == true).length > 0) ? true : false; + } + + private showValidationErrorsDialog(projectOnly?: boolean, errmess?: string[]) { + + const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, { + disableClose: true, + autoFocus: false, + restoreFocus: false, + data: { + errorMessages:errmess, + projectOnly: projectOnly + }, + }); + + } + onSubmit(): void { - this.dmpProfileService.createDmp(this.formGroup.value) + this.dmpProfileService.createBlueprint(this.formGroup.value) .pipe(takeUntil(this._destroyed)) .subscribe( complete => this.onCallbackSuccess(),