diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpblueprint/ReferenceTypeFieldEntity.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpblueprint/ReferenceTypeFieldEntity.java index f4b1658cd..dc308a535 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpblueprint/ReferenceTypeFieldEntity.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpblueprint/ReferenceTypeFieldEntity.java @@ -12,6 +12,8 @@ public class ReferenceTypeFieldEntity extends FieldEntity { @XmlAttribute(name="referenceTypeId") private UUID referenceTypeId; + @XmlAttribute(name = "multipleSelect") + private Boolean multipleSelect; public UUID getReferenceTypeId() { return referenceTypeId; } @@ -19,4 +21,12 @@ public class ReferenceTypeFieldEntity extends FieldEntity { public void setReferenceTypeId(UUID referenceTypeId) { this.referenceTypeId = referenceTypeId; } + + public Boolean getMultipleSelect() { + return multipleSelect; + } + + public void setMultipleSelect(Boolean multipleSelect) { + this.multipleSelect = multipleSelect; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpblueprint/importexport/ReferenceTypeFieldImportExport.java b/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpblueprint/importexport/ReferenceTypeFieldImportExport.java index 969819957..3132ce86d 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpblueprint/importexport/ReferenceTypeFieldImportExport.java +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/types/dmpblueprint/importexport/ReferenceTypeFieldImportExport.java @@ -24,6 +24,9 @@ public class ReferenceTypeFieldImportExport { @XmlAttribute(name = "required") private boolean required; + @XmlAttribute(name = "multipleSelect") + private Boolean multipleSelect; + public UUID getId() { return id; } @@ -80,5 +83,11 @@ public class ReferenceTypeFieldImportExport { this.required = required; } + public Boolean getMultipleSelect() { + return multipleSelect; + } + public void setMultipleSelect(Boolean multipleSelect) { + this.multipleSelect = multipleSelect; + } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/commonmodels/dmpblueprint/ReferenceTypeFieldCommonModelBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/commonmodels/dmpblueprint/ReferenceTypeFieldCommonModelBuilder.java index 69f23d359..cd621fd8c 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/builder/commonmodels/dmpblueprint/ReferenceTypeFieldCommonModelBuilder.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/commonmodels/dmpblueprint/ReferenceTypeFieldCommonModelBuilder.java @@ -4,6 +4,7 @@ import eu.eudat.commonmodels.models.dmpblueprint.ReferenceTypeFieldModel; import eu.eudat.commons.types.dmpblueprint.ReferenceTypeFieldEntity; import eu.eudat.convention.ConventionService; import eu.eudat.model.builder.commonmodels.ReferenceTypeCommonModelBuilder; +import eu.eudat.model.dmpblueprintdefinition.ReferenceTypeField; import eu.eudat.query.ReferenceTypeQuery; import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.query.QueryFactory; @@ -31,6 +32,7 @@ public class ReferenceTypeFieldCommonModelBuilder extends FieldCommonModelBuilde protected ReferenceTypeFieldModel buildChild(ReferenceTypeFieldEntity data, ReferenceTypeFieldModel model) { if (data.getReferenceTypeId() != null ) model.setReferenceType(this.builderFactory.builder(ReferenceTypeCommonModelBuilder.class).build(this.queryFactory.query(ReferenceTypeQuery.class).ids(data.getReferenceTypeId()).first())); //TODO: Optimize + //model.setMultipleSelect(data.getMultipleSelect()); //TODO: add to common model return model; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/dmpblueprintdefinition/ReferenceFieldBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/dmpblueprintdefinition/ReferenceFieldBuilder.java index 396ae4d33..5a5e361bd 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/builder/dmpblueprintdefinition/ReferenceFieldBuilder.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/dmpblueprintdefinition/ReferenceFieldBuilder.java @@ -40,8 +40,9 @@ public class ReferenceFieldBuilder extends FieldBuilder { @@ -44,10 +58,14 @@ public class ReferenceTypeFieldPersist extends FieldPersist { @Override protected List specifications(ReferenceTypeFieldPersist item) { List specifications = getBaseSpecifications(item); - specifications.add( + specifications.addAll(Arrays.asList( this.spec() .must(() -> !this.isNull(item.getReferenceTypeId())) - .failOn(ReferenceTypeFieldPersist._referenceTypeId).failWith(messageSource.getMessage("Validation_Required", new Object[]{ReferenceTypeFieldPersist._referenceTypeId}, LocaleContextHolder.getLocale())) + .failOn(ReferenceTypeFieldPersist._referenceTypeId).failWith(messageSource.getMessage("Validation_Required", new Object[]{ReferenceTypeFieldPersist._referenceTypeId}, LocaleContextHolder.getLocale())), + this.spec() + .must(() -> !this.isNull(item.getMultipleSelect())) + .failOn(ReferenceTypeFieldPersist._multipleSelect).failWith(messageSource.getMessage("Validation_Required", new Object[]{ReferenceTypeFieldPersist._multipleSelect}, LocaleContextHolder.getLocale()))) + ); return specifications; } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpBlueprintValuePersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpBlueprintValuePersist.java index e152aa951..b39970f56 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpBlueprintValuePersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpBlueprintValuePersist.java @@ -33,6 +33,8 @@ public class DmpBlueprintValuePersist { public static final String _fieldValue = "fieldValue"; private List references; public static final String _references = "references"; + private ReferencePersist reference; + public static final String _reference = "reference"; public UUID getFieldId() { return fieldId; @@ -58,6 +60,14 @@ public class DmpBlueprintValuePersist { this.references = references; } + public ReferencePersist getReference() { + return reference; + } + + public void setReference(ReferencePersist reference) { + this.reference = reference; + } + @Component(DmpBlueprintValuePersistValidator.ValidatorName) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public static class DmpBlueprintValuePersistValidator extends BaseValidator { @@ -97,16 +107,27 @@ public class DmpBlueprintValuePersist { .must(() -> !this.isEmpty(item.getFieldValue())) .failOn(DmpBlueprintValuePersist._fieldValue).failWith(messageSource.getMessage("Validation_Required", new Object[]{fieldEntity.getLabel()}, LocaleContextHolder.getLocale())), this.spec() - .iff(() -> fieldEntity.getCategory().equals(DmpBlueprintFieldCategory.ReferenceType) && this.isEmpty(item.getFieldValue()) && required) + .iff(() -> fieldEntity.getCategory().equals(DmpBlueprintFieldCategory.ReferenceType) && this.isEmpty(item.getFieldValue()) && ((ReferenceTypeFieldEntity)fieldEntity).getMultipleSelect() && required) .must(() -> !this.isListNullOrEmpty(item.getReferences())) // TODO: Cast Exception // .failOn(DmpBlueprintValuePersist._references).failWith(messageSource.getMessage("Validation_Required", new Object[]{!this.isEmpty(fieldEntity.getLabel()) ? fieldEntity.getLabel() : this.getReferenceTypeName(fieldEntity)}, LocaleContextHolder.getLocale())), .failOn(DmpBlueprintValuePersist._references).failWith(messageSource.getMessage("Validation_Required", new Object[]{!this.isEmpty(fieldEntity.getLabel()) ? fieldEntity.getLabel() : DmpBlueprintValuePersist._references}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> fieldEntity.getCategory().equals(DmpBlueprintFieldCategory.ReferenceType) && this.isEmpty(item.getFieldValue()) && !((ReferenceTypeFieldEntity)fieldEntity).getMultipleSelect() && required) + .must(() -> !this.isNull(item.getReference())) + // TODO: Cast Exception +// .failOn(DmpBlueprintValuePersist._references).failWith(messageSource.getMessage("Validation_Required", new Object[]{!this.isEmpty(fieldEntity.getLabel()) ? fieldEntity.getLabel() : this.getReferenceTypeName(fieldEntity)}, LocaleContextHolder.getLocale())), + .failOn(DmpBlueprintValuePersist._reference).failWith(messageSource.getMessage("Validation_Required", new Object[]{!this.isEmpty(fieldEntity.getLabel()) ? fieldEntity.getLabel() : DmpBlueprintValuePersist._reference}, LocaleContextHolder.getLocale())), this.navSpec() .iff(() -> !this.isListNullOrEmpty(item.getReferences())) .on(DmpBlueprintValuePersist._references) .over(item.getReferences()) - .using((itm) -> this.validatorFactory.validator(ReferencePersist.ReferenceWithoutTypePersistValidator.class)) + .using((itm) -> this.validatorFactory.validator(ReferencePersist.ReferenceWithoutTypePersistValidator.class)), + this.refSpec() + .iff(() -> !this.isNull(item.getReference())) + .on(DmpBlueprintValuePersist._reference) + .over(item.getReferences()) + .using(() -> this.validatorFactory.validator(ReferencePersist.ReferenceWithoutTypePersistValidator.class)) ); } diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java index 638ebbc2b..22dfeedd7 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/dmp/DmpServiceImpl.java @@ -750,6 +750,10 @@ public class DmpServiceImpl implements DmpService { List dmpReferencePersists = new ArrayList<>(); if (persist.getDmpBlueprintValues() != null && !persist.getDmpBlueprintValues().isEmpty()){ for (DmpBlueprintValuePersist fieldValuePersist: persist.getDmpBlueprintValues().values()) { + if (fieldValuePersist.getReference() != null) { + if (fieldValuePersist.getReferences() == null) fieldValuePersist.setReferences(new ArrayList<>()); + fieldValuePersist.getReferences().add(fieldValuePersist.getReference()); + } if (this.conventionService.isNullOrEmpty(fieldValuePersist.getFieldValue()) && !this.conventionService.isListNullOrEmpty( fieldValuePersist.getReferences())) { for (ReferencePersist referencePersist : fieldValuePersist.getReferences()) { DmpReferencePersist dmpReferencePersist = new DmpReferencePersist(); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintServiceImpl.java index bac784ee5..ed0ca75ab 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/dmpblueprint/DmpBlueprintServiceImpl.java @@ -265,6 +265,7 @@ public class DmpBlueprintServiceImpl implements DmpBlueprintService { case ReferenceType -> { ReferenceTypeFieldEntity dataTyped = new ReferenceTypeFieldEntity(); dataTyped.setReferenceTypeId(((ReferenceTypeFieldPersist) persist).getReferenceTypeId()); + dataTyped.setMultipleSelect(((ReferenceTypeFieldPersist) persist).getMultipleSelect()); data = dataTyped; } default -> throw new InternalError("unknown type: " + persist.getCategory()); @@ -540,6 +541,7 @@ public class DmpBlueprintServiceImpl implements DmpBlueprintService { xml.setDescription(entity.getDescription()); xml.setOrdinal(entity.getOrdinal()); xml.setRequired(entity.isRequired()); + xml.setMultipleSelect(entity.getMultipleSelect()); return xml; } @@ -670,6 +672,7 @@ public class DmpBlueprintServiceImpl implements DmpBlueprintService { persist.setDescription(importXml.getDescription()); persist.setOrdinal(importXml.getOrdinal()); persist.setRequired(importXml.isRequired()); + persist.setMultipleSelect(importXml.getMultipleSelect()); return persist; } diff --git a/dmp-frontend/src/app/core/model/dmp-blueprint/dmp-blueprint.ts b/dmp-frontend/src/app/core/model/dmp-blueprint/dmp-blueprint.ts index abe85a36b..8d1c2cd89 100644 --- a/dmp-frontend/src/app/core/model/dmp-blueprint/dmp-blueprint.ts +++ b/dmp-frontend/src/app/core/model/dmp-blueprint/dmp-blueprint.ts @@ -60,11 +60,12 @@ export interface ExtraFieldInSection extends FieldInSection { export interface ReferenceTypeFieldInSection extends FieldInSection { referenceType: ReferenceType; + multipleSelect: boolean; } -// +// // Persist -// +// export interface DmpBlueprintPersist extends BaseEntityPersist { label: string; definition: DmpBlueprintDefinitionPersist; @@ -120,4 +121,5 @@ export interface ExtraFieldInSectionPersist extends FieldInSectionPersist { export interface ReferenceTypeFieldInSectionPersist extends FieldInSectionPersist { referenceTypeId: Guid; -} \ No newline at end of file + multipleSelect: boolean; +} diff --git a/dmp-frontend/src/app/core/model/dmp/dmp.ts b/dmp-frontend/src/app/core/model/dmp/dmp.ts index d8fef3f2e..02dbc9af4 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp.ts @@ -95,6 +95,7 @@ export interface DmpBlueprintValuePersist { fieldId: Guid; fieldValue: string; references: DmpReferencePersist[]; + reference: DmpReferencePersist; } export interface DmpContactPersist { diff --git a/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.component.html b/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.component.html index b7166e827..54160732f 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.component.html @@ -178,6 +178,12 @@ {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+ {{'DMP-BLUEPRINT-EDITOR.FIELDS.FIELD-MULTIPLE-SELECT' | translate}} + {{field.get('multipleSelect')?.getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} +
diff --git a/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.model.ts b/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.model.ts index 3a972cc54..decf72886 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.model.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.model.ts @@ -71,6 +71,7 @@ export class DmpBlueprintEditorModel extends BaseEditorModel implements DmpBluep const field: FieldInSectionEditorModel = new FieldInSectionEditorModel(this.validationErrorModel); field.id = Guid.create(); field.ordinal = index + 1; + field.multipleSelect = false; return field.buildForm({ rootPath: 'definition.sections[' + sectionIndex + '].fields[' + index + '].' }); } @@ -91,7 +92,7 @@ export class DmpBlueprintEditorModel extends BaseEditorModel implements DmpBluep rootPath: `definition.`, validationErrorModel: validationErrorModel }); - formGroup.updateValueAndValidity(); + formGroup.updateValueAndValidity(); } } @@ -308,6 +309,7 @@ export class FieldInSectionEditorModel implements FieldInSectionPersist { public dataType: DmpBlueprintExtraFieldDataType; public systemFieldType: DmpBlueprintSystemFieldType; public referenceTypeId: Guid; + public multipleSelect: boolean; static get alwaysRequiredSystemFieldTypes(): DmpBlueprintSystemFieldType[] { return [DmpBlueprintSystemFieldType.Title, DmpBlueprintSystemFieldType.Description, DmpBlueprintSystemFieldType.Language, DmpBlueprintSystemFieldType.AccessRights]; @@ -338,6 +340,7 @@ export class FieldInSectionEditorModel implements FieldInSectionPersist { this.dataType = (item as ExtraFieldInSection).dataType; } else if (this.category == DmpBlueprintFieldCategory.ReferenceType) { this.referenceTypeId = (item as ReferenceTypeFieldInSection).referenceType?.id; + this.multipleSelect= (item as ReferenceTypeFieldInSection).multipleSelect; } return this; @@ -369,6 +372,7 @@ export class FieldInSectionEditorModel implements FieldInSectionPersist { dataType: [{ value: this.dataType, disabled: disabled }, context.getValidation('dataType').validators], systemFieldType: [{ value: this.systemFieldType, disabled: disabled }, context.getValidation('systemFieldType').validators], referenceTypeId: [{ value: this.referenceTypeId, disabled: disabled }, context.getValidation('referenceTypeId').validators], + multipleSelect: [{ value: this.multipleSelect, disabled: disabled }, context.getValidation('multipleSelect').validators], }); } @@ -394,6 +398,7 @@ export class FieldInSectionEditorModel implements FieldInSectionPersist { baseValidationArray.push({ key: 'dataType', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}dataType`)] }); baseValidationArray.push({ key: 'systemFieldType', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}systemFieldType`)] }); baseValidationArray.push({ key: 'referenceTypeId', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}referenceTypeId`)] }); + baseValidationArray.push({ key: 'multipleSelect', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}multipleSelect`)] }); baseContext.validation = baseValidationArray; return baseContext; @@ -411,7 +416,7 @@ export class FieldInSectionEditorModel implements FieldInSectionPersist { validationErrorModel }); - ['id', 'category', 'dataType', 'systemFieldType', 'referenceTypeId', 'label', 'placeholder', 'description', 'semantics', 'required', 'ordinal'].forEach(keyField => { + ['id', 'category', 'dataType', 'systemFieldType', 'referenceTypeId', 'multipleSelect', 'label', 'placeholder', 'description', 'semantics', 'required', 'ordinal'].forEach(keyField => { const control = formGroup?.get(keyField); control?.clearValidators(); if (keyField == 'label') { @@ -419,7 +424,10 @@ export class FieldInSectionEditorModel implements FieldInSectionPersist { } else if (keyField == 'referenceTypeId') { if (formGroup.get('category').value === DmpBlueprintFieldCategory.ReferenceType) control?.addValidators([Validators.required, ...context.getValidation('referenceTypeId').validators]); else control?.addValidators([...context.getValidation('referenceTypeId').validators]); - } else if (keyField == 'systemFieldType') { + } else if (keyField == 'multipleSelect') { + if (formGroup.get('category').value === DmpBlueprintFieldCategory.ReferenceType) control?.addValidators([Validators.required, ...context.getValidation('multipleSelect').validators]); + else control?.addValidators([...context.getValidation('multipleSelect').validators]); + }else if (keyField == 'systemFieldType') { if (formGroup.get('category').value === DmpBlueprintFieldCategory.System) control?.addValidators([Validators.required, ...context.getValidation('systemFieldType').validators]); else control?.addValidators([...context.getValidation('systemFieldType').validators]); } else if (keyField == 'dataType') { @@ -508,4 +516,4 @@ export class DescriptionTemplatesInSectionEditorModel implements DescriptionTemp control?.addValidators(context.getValidation(keyField).validators); }) } -} \ No newline at end of file +} diff --git a/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.resolver.ts b/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.resolver.ts index d778d6235..6cac3d317 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.resolver.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-blueprint/editor/dmp-blueprint-editor.resolver.ts @@ -42,6 +42,7 @@ export class DmpBlueprintEditorResolver extends BaseEditorResolver { [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.referenceType), nameof(x => x.id)].join('.'), [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.referenceType), nameof(x => x.name)].join('.'), [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.referenceType), nameof(x => x.code)].join('.'), + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.multipleSelect)].join('.'), [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.descriptionTemplates), nameof(x => x.descriptionTemplateGroupId)].join('.'), [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.descriptionTemplates), nameof(x => x.label)].join('.'), @@ -50,7 +51,7 @@ export class DmpBlueprintEditorResolver extends BaseEditorResolver { [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.prefillingSources), nameof(x => x.id)].join('.'), [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.prefillingSources), nameof(x => x.label)].join('.'), - + nameof(x => x.createdAt), nameof(x => x.hash), nameof(x => x.isActive) diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html index cfdada5c2..46a02708d 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.html @@ -249,9 +249,12 @@
-
- -
+ + + + + +
diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.model.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.model.ts index 9559ca651..acf2a226e 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.model.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.model.ts @@ -6,7 +6,7 @@ import { DmpStatus } from "@app/core/common/enum/dmp-status"; import { DmpUserRole } from "@app/core/common/enum/dmp-user-role"; import { DmpUserType } from "@app/core/common/enum/dmp-user-type"; import { IsActive } from "@app/core/common/enum/is-active.enum"; -import { DmpBlueprint, FieldInSection } from "@app/core/model/dmp-blueprint/dmp-blueprint"; +import { DmpBlueprint, FieldInSection, ReferenceTypeFieldInSection } from "@app/core/model/dmp-blueprint/dmp-blueprint"; import { Dmp, DmpBlueprintValue, DmpBlueprintValuePersist, DmpContact, DmpContactPersist, DmpDescriptionTemplate, DmpDescriptionTemplatePersist, DmpPersist, DmpProperties, DmpPropertiesPersist, DmpReferenceDataPersist, DmpReferencePersist, DmpUser, DmpUserPersist } from "@app/core/model/dmp/dmp"; import { DmpReference } from "@app/core/model/dmp/dmp-reference"; import { ReferencePersist } from "@app/core/model/reference/reference"; @@ -291,7 +291,8 @@ export class DmpPropertiesEditorModel implements DmpPropertiesPersist { formGroup: control as UntypedFormGroup, rootPath: `${rootPath}dmpBlueprintValues[${key}].`, validationErrorModel: validationErrorModel, - isRequired: params.blueprint.definition.sections.flatMap(x => x.fields).find(x => x.id.toString() == key).required + isRequired: params.blueprint.definition.sections.flatMap(x => x.fields).find(x => x.id.toString() == key).required, + multipleSelect: (params.blueprint.definition.sections.flatMap(x => x.fields).find(x => x.id.toString() == key) as ReferenceTypeFieldInSection).multipleSelect }) }); @@ -309,7 +310,9 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { fieldId: Guid; fieldValue: string; references: DmpReferencePersist[] = []; + reference: DmpReferencePersist; isRequired: boolean = false; + multipleSelect: boolean = false; category: DmpBlueprintFieldCategory; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -321,7 +324,7 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { fromModel(item: DmpBlueprintValue, dmpReferences: DmpReference[], field: FieldInSection): DmpBlueprintValueEditorModel { this.fieldId = item.fieldId; this.fieldValue = item.fieldValue; - this.references = dmpReferences?.filter(x => x.data.blueprintFieldId == this.fieldId && x.isActive == IsActive.Active).map(x => { + const references = dmpReferences?.filter(x => x.data.blueprintFieldId == this.fieldId && x.isActive == IsActive.Active).map(x => { return { data: x.data, reference: { @@ -337,7 +340,18 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { } } }); + if ((field as ReferenceTypeFieldInSection).multipleSelect) { + this.references = references; + this.multipleSelect = true; + } else { + if (references?.length == 1) this.reference = references[0]; + if (references?.length > 1) { + console.error("multiple references on single reference field: " + references); + this.reference = references[0]; + } + this.multipleSelect = false; + } this.isRequired = field.required; if (this.isRequired) console.log(field); this.category = field.category; @@ -355,7 +369,8 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { context = DmpBlueprintValueEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, rootPath, - isRequired: this.isRequired + isRequired: this.isRequired, + multipleSelect: this.multipleSelect }); } @@ -365,6 +380,7 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { switch (this.category) { case DmpBlueprintFieldCategory.ReferenceType: formGroup.addControl('references', new FormControl({ value: this.references?.map(x => x.reference), disabled: disabled }, context.getValidation('references').validators)); + formGroup.addControl('reference', new FormControl({ value: this.reference?.reference, disabled: disabled }, context.getValidation('reference').validators)); break; case DmpBlueprintFieldCategory.System: case DmpBlueprintFieldCategory.Extra: @@ -378,6 +394,7 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { static createValidationContext(params: { rootPath?: string, validationErrorModel: ValidationErrorModel, + multipleSelect: boolean, isRequired: boolean, }): ValidationContext { const { rootPath = '', validationErrorModel } = params; @@ -386,7 +403,8 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'fieldId', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}fieldId`)] }); baseValidationArray.push({ key: 'fieldValue', validators: params.isRequired ? [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}fieldValue`)] : [BackendErrorValidator(validationErrorModel, `${rootPath}fieldValue`)] }); - baseValidationArray.push({ key: 'references', validators: params.isRequired ? [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}references`)] : [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] }); + baseValidationArray.push({ key: 'references', validators: params.isRequired && params.multipleSelect ? [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}references`)] : [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] }); + baseValidationArray.push({ key: 'reference', validators: params.isRequired && !params.multipleSelect ? [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}reference`)] : [BackendErrorValidator(validationErrorModel, `${rootPath}reference`)] }); baseContext.validation = baseValidationArray; return baseContext; @@ -397,13 +415,15 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { validationErrorModel: ValidationErrorModel, rootPath: string, isRequired: boolean + multipleSelect: boolean }): void { const { formGroup, rootPath, validationErrorModel } = params; const context = DmpBlueprintValueEditorModel.createValidationContext({ rootPath, validationErrorModel, - isRequired: params.isRequired + isRequired: params.isRequired, + multipleSelect: params.multipleSelect }); ['fieldId', 'fieldValue', 'references'].forEach(keyField => { @@ -710,4 +730,4 @@ export class DmpDescriptionTemplateEditorModel implements DmpDescriptionTemplate control?.addValidators(context.getValidation(keyField).validators); }) } -} \ No newline at end of file +} diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts index 8dec1ecba..2eccf2624 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts @@ -121,6 +121,7 @@ export class DmpEditorResolver extends BaseEditorResolver { (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.referenceType), nameof(x => x.id)].join('.'), (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.referenceType), nameof(x => x.name)].join('.'), (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.referenceType), nameof(x => x.code)].join('.'), + (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.multipleSelect)].join('.'), (prefix ? prefix + '.' : '') + [nameof(x => x.definition), nameof(x => x.sections), nameof(x => x.fields), nameof(x => x.referenceType), nameof(x => x.definition), nameof(x=> x.sources), nameof(x=> x.referenceTypeDependencies) , nameof(x => x.id)].join('.'), ] } diff --git a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.ts b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.ts index 7bf905924..ef7efe3c8 100644 --- a/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.ts +++ b/dmp-frontend/src/app/ui/reference/reference-field/reference-field.component.ts @@ -14,6 +14,7 @@ import { ReferenceSearchLookup } from '@app/core/query/reference-search.lookup'; import { Guid } from '@common/types/guid'; import { nameof } from 'ts-simple-nameof'; import { Subscription } from 'rxjs'; +import { FormService } from '@common/forms/form-service'; @Component({ selector: 'app-reference-field-component', @@ -42,6 +43,7 @@ export class ReferenceFieldComponent extends BaseComponent implements OnInit, On constructor( private referenceService: ReferenceService, public enumUtils: EnumUtils, + public formService: FormService, private dialog: MatDialog, ) { super(); } @@ -75,7 +77,9 @@ export class ReferenceFieldComponent extends BaseComponent implements OnInit, On const referenceToUse : Reference[]= []; Object.keys(this.dependencies.controls).forEach(controlName => { // (this.dependencies.get(controlName).get('references').value as Reference[]).filter(x=> sourcesWithDependencies.some(y => y.referenceTypeDependencies) x.type.id == this.referenceType.id &&) - const foudReferences: any[] = this.dependencies.get(controlName).get('references')?.value; + const ctrlValue = this.formService.getValue(this.dependencies.get(controlName).value); + const foudReferences: any[] = ctrlValue?.references || []; + if (ctrlValue?.reference) foudReferences.push(ctrlValue?.reference); if (foudReferences != null) { for (let i = 0; i < foudReferences.length; i++) { const foudReference = foudReferences[i]; @@ -106,7 +110,7 @@ export class ReferenceFieldComponent extends BaseComponent implements OnInit, On if (!isInitial && (!referenceToUse.map(x => x.reference).every(x => this.referenceToUse.map(y => y.reference).includes(x)) || !this.referenceToUse.map(x => x.reference).every(x => referenceToUse.map(y => y.reference).includes(x)))) { this.referenceToUse = referenceToUse; - this.form.setValue([]); + this.form.setValue(this.multiple ? [] : null); this.form.updateValueAndValidity(); } else { this.referenceToUse = referenceToUse; @@ -145,10 +149,14 @@ export class ReferenceFieldComponent extends BaseComponent implements OnInit, On .pipe(takeUntil(this._destroyed)) .subscribe(newResult => { if (!newResult) { return; } - let results = this.form.value as ReferencePersist[]; - if (results == undefined) results = []; - results.push(newResult); - this.form.setValue(results); + if (this.multiple) { + let results = this.form.value as ReferencePersist[]; + if (results == undefined) results = []; + results.push(newResult); + this.form.setValue(results); + } else { + this.form.setValue(newResult); + } }); } ); diff --git a/dmp-frontend/src/assets/i18n/de.json b/dmp-frontend/src/assets/i18n/de.json index 3c7abed97..df7c192d0 100644 --- a/dmp-frontend/src/assets/i18n/de.json +++ b/dmp-frontend/src/assets/i18n/de.json @@ -1020,6 +1020,7 @@ "TYPE": "Type", "DATATYPE": "Data Type", "REQUIRED": "Pflichtfeld", + "FIELD-MULTIPLE-SELECT": "Multiple", "EXTERNAL-AUTOCOMPLETE": { "TITLE": "Autocomplete Data", "MULTIPLE-AUTOCOMPLETE": "Multiple Autocomplete", diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 065c07a34..29346d880 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -1355,6 +1355,7 @@ "DATA-TYPE": "Data Type", "CATEGORY": "Field Type", "FIELD-REQUIRED": "Required", + "FIELD-MULTIPLE-SELECT": "Multiple", "SEMANTICS": "Semantics", "DESCRIPTION-TEMPLATES": "Description Templates", "DESCRIPTION-TEMPLATE": "Description Template", @@ -2022,4 +2023,4 @@ "CONFIRM": "Confirm" } } -} \ No newline at end of file +} diff --git a/dmp-frontend/src/assets/i18n/es.json b/dmp-frontend/src/assets/i18n/es.json index 26219253a..adf599702 100644 --- a/dmp-frontend/src/assets/i18n/es.json +++ b/dmp-frontend/src/assets/i18n/es.json @@ -1020,6 +1020,7 @@ "TYPE": "Tipo", "DATATYPE": "Tipo de datos", "REQUIRED": "Obligatorio", + "FIELD-MULTIPLE-SELECT": "Multiple", "EXTERNAL-AUTOCOMPLETE": { "TITLE": "Datos autocompletados", "MULTIPLE-AUTOCOMPLETE": "Multiple Autocomplete", diff --git a/dmp-frontend/src/assets/i18n/gr.json b/dmp-frontend/src/assets/i18n/gr.json index 004286dc7..93e433072 100644 --- a/dmp-frontend/src/assets/i18n/gr.json +++ b/dmp-frontend/src/assets/i18n/gr.json @@ -1020,6 +1020,7 @@ "TYPE": "Τύπος", "DATATYPE": "Τύπος Δεδομένων", "REQUIRED": "Υποχρεωτικά", + "FIELD-MULTIPLE-SELECT": "Πολλαπλό", "EXTERNAL-AUTOCOMPLETE": { "TITLE": "Αυτόματη Συμπλήρωση Δεδομένων", "MULTIPLE-AUTOCOMPLETE": "Πολλαπλή Αυτόματη Συμπλήρωση", diff --git a/dmp-frontend/src/assets/i18n/hr.json b/dmp-frontend/src/assets/i18n/hr.json index ee8b99a8d..771e64909 100644 --- a/dmp-frontend/src/assets/i18n/hr.json +++ b/dmp-frontend/src/assets/i18n/hr.json @@ -1020,6 +1020,7 @@ "TYPE": "Vrsta", "DATATYPE": "Tip podataka", "REQUIRED": "Obavezno", + "FIELD-MULTIPLE-SELECT": "Multiple", "EXTERNAL-AUTOCOMPLETE": { "TITLE": "Automatski unos podataka", "MULTIPLE-AUTOCOMPLETE": "Višestruki automatski unos", diff --git a/dmp-frontend/src/assets/i18n/pl.json b/dmp-frontend/src/assets/i18n/pl.json index 55f92f947..379146dfc 100644 --- a/dmp-frontend/src/assets/i18n/pl.json +++ b/dmp-frontend/src/assets/i18n/pl.json @@ -1020,6 +1020,7 @@ "TYPE": "Typ", "DATATYPE": "Typ danych", "REQUIRED": "Wymagane", + "FIELD-MULTIPLE-SELECT": "Multiple", "EXTERNAL-AUTOCOMPLETE": { "TITLE": "Autouzupełnanie danych", "MULTIPLE-AUTOCOMPLETE": "Wielokrotne autouzupełnianie", diff --git a/dmp-frontend/src/assets/i18n/pt.json b/dmp-frontend/src/assets/i18n/pt.json index d530808f1..b50b8daa8 100644 --- a/dmp-frontend/src/assets/i18n/pt.json +++ b/dmp-frontend/src/assets/i18n/pt.json @@ -1020,6 +1020,7 @@ "TYPE": "Tipo", "DATATYPE": "Tipo de Dados", "REQUIRED": "Obrigatório", + "FIELD-MULTIPLE-SELECT": "Multiple", "EXTERNAL-AUTOCOMPLETE": { "TITLE": "Autocompletar Dados", "MULTIPLE-AUTOCOMPLETE": "Autopreenchimento Múltiplo", diff --git a/dmp-frontend/src/assets/i18n/sk.json b/dmp-frontend/src/assets/i18n/sk.json index c00ccb39a..8e914bc84 100644 --- a/dmp-frontend/src/assets/i18n/sk.json +++ b/dmp-frontend/src/assets/i18n/sk.json @@ -1020,6 +1020,7 @@ "TYPE": "Typ", "DATATYPE": "Typ dát", "REQUIRED": "Povinné", + "FIELD-MULTIPLE-SELECT": "Multiple", "EXTERNAL-AUTOCOMPLETE": { "TITLE": "Automatické dopĺňanie údajov", "MULTIPLE-AUTOCOMPLETE": "Viacnásobné automatické dokončenie", diff --git a/dmp-frontend/src/assets/i18n/sr.json b/dmp-frontend/src/assets/i18n/sr.json index 0421c780f..203300ce0 100644 --- a/dmp-frontend/src/assets/i18n/sr.json +++ b/dmp-frontend/src/assets/i18n/sr.json @@ -1020,6 +1020,7 @@ "TYPE": "Tip", "DATATYPE": "Tip podataka", "REQUIRED": "Obavezno", + "FIELD-MULTIPLE-SELECT": "Multiple", "EXTERNAL-AUTOCOMPLETE": { "TITLE": "Automatski unos podataka", "MULTIPLE-AUTOCOMPLETE": "Višestruki automatski unos", diff --git a/dmp-frontend/src/assets/i18n/tr.json b/dmp-frontend/src/assets/i18n/tr.json index 9587dfd30..f03985955 100644 --- a/dmp-frontend/src/assets/i18n/tr.json +++ b/dmp-frontend/src/assets/i18n/tr.json @@ -1020,6 +1020,7 @@ "TYPE": "Tip", "DATATYPE": "Veri Tipi", "REQUIRED": "Gerekli", + "FIELD-MULTIPLE-SELECT": "Multiple", "EXTERNAL-AUTOCOMPLETE": { "TITLE": "Verileri Otomatik Tamamla", "MULTIPLE-AUTOCOMPLETE": "Çoklu Otomatik Tamamlama", diff --git a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DmpBlueprintXmlMigrationService.java b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DmpBlueprintXmlMigrationService.java index b7c59c1f1..f08394f3e 100644 --- a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DmpBlueprintXmlMigrationService.java +++ b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DmpBlueprintXmlMigrationService.java @@ -183,12 +183,30 @@ public class DmpBlueprintXmlMigrationService { case ACCESS_RIGHTS -> dataTyped.setType(DmpBlueprintSystemFieldType.AccessRights); case CONTACT -> dataTyped.setType(DmpBlueprintSystemFieldType.Contact); case LANGUAGE -> dataTyped.setType(DmpBlueprintSystemFieldType.Language); - case FUNDER -> referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Funder); - case GRANT -> referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Grants); - case LICENSE -> referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.License); - case ORGANIZATIONS -> referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Organizations); - case PROJECT -> referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Project); - case RESEARCHERS -> referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Researcher); + case FUNDER -> { + referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Funder); + referenceTypeFieldEntity.setMultipleSelect(false); + } + case GRANT -> { + referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Grants); + referenceTypeFieldEntity.setMultipleSelect(false); + } + case LICENSE -> { + referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.License); + referenceTypeFieldEntity.setMultipleSelect(true); + } + case ORGANIZATIONS -> { + referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Organizations); + referenceTypeFieldEntity.setMultipleSelect(true); + } + case PROJECT -> { + referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Project); + referenceTypeFieldEntity.setMultipleSelect(false); + } + case RESEARCHERS -> { + referenceTypeFieldEntity.setReferenceTypeId(ReferenceTypeIds.Researcher); + referenceTypeFieldEntity.setMultipleSelect(true); + } default -> throw new MyApplicationException("Type not found " + systemField.getType()); } if (systemField.getType().equals(SystemFieldType.TEXT) || systemField.getType().equals(SystemFieldType.HTML_TEXT) ||