From 285978fb58c387aead173c26240c9754579ac0be Mon Sep 17 00:00:00 2001 From: amentis Date: Wed, 31 Jan 2024 11:27:36 +0200 Subject: [PATCH] add contacts dmp editor ui --- .../eu/eudat/model/persist/DmpPersist.java | 11 +++ .../SectionPersist.java | 8 +- .../dmpproperties/DmpContactPersist.java | 31 +++++++- .../dmpproperties/DmpPropertiesPersist.java | 13 +++- .../src/main/resources/messages.properties | 3 +- .../app/core/common/enum/dmp-contact-type.ts | 4 + dmp-frontend/src/app/core/model/dmp/dmp.ts | 2 +- .../services/utilities/enum-utils.service.ts | 7 ++ .../dmp-blueprint-editor.component.html | 3 +- .../editor/dmp-blueprint-editor.model.ts | 4 +- .../dmp-editor.component.html | 75 +++++++++++++++---- .../dmp-editor.component.scss | 9 +++ .../dmp-editor.component.ts | 53 +++++++++++-- .../dmp-editor-blueprint/dmp-editor.model.ts | 22 ++++-- .../dmp-editor-blueprint/dmp-editor.module.ts | 4 +- .../dmp-editor.resolver.ts | 3 +- dmp-frontend/src/assets/i18n/en.json | 11 ++- 17 files changed, 223 insertions(+), 40 deletions(-) create mode 100644 dmp-frontend/src/app/core/common/enum/dmp-contact-type.ts diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpPersist.java index da15978af..a2ae650ac 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/DmpPersist.java @@ -36,14 +36,17 @@ public class DmpPersist { public static final String _properties = "properties"; private String description; + public static final String _description = "description"; private String language; + public static final String _language = "language"; private UUID blueprint; public static final String _blueprint = "blueprint"; private DmpAccessType accessType; + public static final String _accessType = "accessType"; // private List references; // @@ -193,6 +196,14 @@ public class DmpPersist { .on(DmpPersist._properties) .over(item.getProperties()) .using(() -> this.validatorFactory.validator(DmpPropertiesPersist.DmpPropertiesPersistValidator.class).setStatus(item.getStatus())), + this.spec() + .iff(() -> item.getStatus() == DmpStatus.Finalized) + .must(() -> !this.isNull(item.getLanguage())) + .failOn(DmpPersist._language).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpPersist._language}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> item.getStatus() == DmpStatus.Finalized) + .must(() -> !this.isNull(item.getAccessType())) + .failOn(DmpPersist._accessType).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpPersist._accessType}, LocaleContextHolder.getLocale())), this.spec() .iff(() -> item.getStatus() == DmpStatus.Finalized) .must(() -> !this.isListNullOrEmpty(item.getDescriptionTemplates())) diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpblueprintdefinition/SectionPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpblueprintdefinition/SectionPersist.java index 24b7f218f..533dc2ad7 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpblueprintdefinition/SectionPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpblueprintdefinition/SectionPersist.java @@ -13,8 +13,10 @@ import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Component; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; public class SectionPersist { @@ -148,7 +150,11 @@ public class SectionPersist { .iff(() -> !this.isListNullOrEmpty(item.getDescriptionTemplates())) .on(SectionPersist._descriptionTemplates) .over(item.getDescriptionTemplates()) - .using((itm) -> this.validatorFactory.validator(DescriptionTemplatePersist.DescriptionTemplatePersistValidator.class)) + .using((itm) -> this.validatorFactory.validator(DescriptionTemplatePersist.DescriptionTemplatePersistValidator.class)), + this.spec() + .iff(() -> !this.isListNullOrEmpty(item.getDescriptionTemplates())) + .must(() -> item.getDescriptionTemplates().stream().map(DescriptionTemplatePersist::getDescriptionTemplateGroupId).distinct().collect(Collectors.toList()).size() == item.getDescriptionTemplates().size()) + .failOn(SectionPersist._descriptionTemplates).failWith(messageSource.getMessage("Validation_Unique", new Object[]{SectionPersist._descriptionTemplates}, LocaleContextHolder.getLocale())) ); } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpContactPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpContactPersist.java index 69c573fd1..8a9a9f3a7 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpContactPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpContactPersist.java @@ -5,22 +5,28 @@ import gr.cite.tools.validation.specification.Specification; import eu.eudat.convention.ConventionService; import eu.eudat.errorcode.ErrorThesaurusProperties; import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.MessageSource; import org.springframework.context.annotation.Scope; +import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Component; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.UUID; public class DmpContactPersist { private UUID userId; + public static final String _userId = "userId"; private String firstName; + public static final String _firstName = "firstName"; private String lastName; + public static final String _lastName = "lastName"; private String email; + public static final String _email = "email"; public UUID getUserId() { return userId; @@ -59,9 +65,11 @@ public class DmpContactPersist { public static class DmpContactPersistValidator extends BaseValidator { public static final String ValidatorName = "DmpContactPersistValidator"; + private final MessageSource messageSource; - protected DmpContactPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors) { + protected DmpContactPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) { super(conventionService, errors); + this.messageSource = messageSource; } @Override @@ -71,7 +79,24 @@ public class DmpContactPersist { @Override protected List specifications(DmpContactPersist item) { - return new ArrayList<>(); + return Arrays.asList( + this.spec() + .iff(() -> this.isEmpty(item.getEmail()) && this.isEmpty(item.getFirstName()) && this.isEmpty(item.getLastName())) + .must(() -> !this.isNull(item.getUserId())) + .failOn(DmpContactPersist._userId).failWith(messageSource.getMessage("Validation_Required", new Object[]{"user"}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> this.isNull(item.getUserId())) + .must(() -> !this.isEmpty(item.getEmail())) + .failOn(DmpContactPersist._email).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpContactPersist._email}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> this.isNull(item.getUserId())) + .must(() -> !this.isEmpty(item.getFirstName())) + .failOn(DmpContactPersist._firstName).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpContactPersist._firstName}, LocaleContextHolder.getLocale())), + this.spec() + .iff(() -> this.isNull(item.getUserId())) + .must(() -> !this.isEmpty(item.getLastName())) + .failOn(DmpContactPersist._lastName).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpContactPersist._lastName}, LocaleContextHolder.getLocale())) + ); } } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpPropertiesPersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpPropertiesPersist.java index 4748f7019..c95fd4e60 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpPropertiesPersist.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/dmpproperties/DmpPropertiesPersist.java @@ -8,7 +8,9 @@ import eu.eudat.convention.ConventionService; import eu.eudat.errorcode.ErrorThesaurusProperties; import eu.eudat.model.persist.validation.StatusAware; import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.MessageSource; import org.springframework.context.annotation.Scope; +import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Component; import java.util.Arrays; @@ -49,12 +51,14 @@ public class DmpPropertiesPersist { public static final String ValidatorName = "DmpPropertiesPersistValidator"; private final ValidatorFactory validatorFactory; + private final MessageSource messageSource; private DmpStatus status; - protected DmpPropertiesPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, ValidatorFactory validatorFactory) { + protected DmpPropertiesPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, ValidatorFactory validatorFactory, MessageSource messageSource) { super(conventionService, errors); this.validatorFactory = validatorFactory; + this.messageSource = messageSource; } @Override @@ -66,13 +70,16 @@ public class DmpPropertiesPersist { protected List specifications(DmpPropertiesPersist item) { return Arrays.asList( this.mapSpec() - .iff(() -> this.status == DmpStatus.Finalized && !this.isNull(item.getDmpBlueprintValues())) + .iff(() ->!this.isNull(item.getDmpBlueprintValues())) .on(DmpPropertiesPersist._dmpBlueprintValues) .over(item.getDmpBlueprintValues()) .mapKey((k) -> ((UUID)k).toString()) .using((itm) -> this.validatorFactory.validator(DmpBlueprintValuePersist.DmpBlueprintValuePersistValidator.class)), + this.spec() + .must(() -> !this.isListNullOrEmpty(item.getContacts())) + .failOn(DmpPropertiesPersist._contacts).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpPropertiesPersist._contacts}, LocaleContextHolder.getLocale())), this.navSpec() - .iff(() -> this.status == DmpStatus.Finalized && !this.isListNullOrEmpty(item.getContacts())) + .iff(() -> !this.isListNullOrEmpty(item.getContacts())) .on(DmpPropertiesPersist._contacts) .over(item.getContacts()) .using((itm) -> this.validatorFactory.validator(DmpContactPersist.DmpContactPersistValidator.class)) diff --git a/dmp-backend/web/src/main/resources/messages.properties b/dmp-backend/web/src/main/resources/messages.properties index 5ff4a0394..2df90f56c 100644 --- a/dmp-backend/web/src/main/resources/messages.properties +++ b/dmp-backend/web/src/main/resources/messages.properties @@ -19,4 +19,5 @@ General_ItemNotFound=Item {0} of type {1} not found Validation_Required={0} is required Validation_OverPosting=Too much info Validation_MaxLength={0} too long -Validation_UnexpectedValue=Unexpected value in field {0} \ No newline at end of file +Validation_UnexpectedValue=Unexpected value in field {0} +Validation_Unique= {0} must be unique \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/dmp-contact-type.ts b/dmp-frontend/src/app/core/common/enum/dmp-contact-type.ts new file mode 100644 index 000000000..130eb1eae --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/dmp-contact-type.ts @@ -0,0 +1,4 @@ +export enum DmpContactType { + Internal = 0, + External = 1 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dmp/dmp.ts b/dmp-frontend/src/app/core/model/dmp/dmp.ts index 39610071c..23940da88 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp.ts @@ -45,7 +45,7 @@ export interface DmpBlueprintValue { } export interface DmpContact { - userId: Guid; + user?: User; firstName: string; lastName: string; email: string; diff --git a/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts b/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts index 708980f29..8a018e41c 100644 --- a/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts +++ b/dmp-frontend/src/app/core/services/utilities/enum-utils.service.ts @@ -33,6 +33,7 @@ import { NotificationNotifyState } from '@app/core/common/enum/notification-noti import { NotificationTrackingState } from '@app/core/common/enum/notification-tracking-state'; import { NotificationTrackingProcess } from '@app/core/common/enum/notification-tracking-process'; import { DmpAccessType } from '@app/core/common/enum/dmp-access-type'; +import { DmpContactType } from '@app/core/common/enum/dmp-contact-type'; @Injectable() export class EnumUtils { @@ -386,4 +387,10 @@ export class EnumUtils { } } + public toDmpContactTypeString(value: DmpContactType): string { + switch (value) { + case DmpContactType.Internal: return this.language.instant('TYPES.DMP-CONTACT-TYPE.INTERNAL'); + case DmpContactType.External: return this.language.instant('TYPES.DMP-CONTACT-TYPE.EXTERNAL'); + } + } } 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 e7df605a6..d946767de 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 @@ -190,7 +190,7 @@
drag_indicator
- {{'DMP-BLUEPRINT-EDITOR.FIELDS.DESCRIPTION-TEMPLATES' | translate}} + {{'DMP-BLUEPRINT-EDITOR.FIELDS.DESCRIPTION-TEMPLATE' | translate}} {{descriptionTemplate.get('descriptionTemplateGroupId').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} @@ -226,6 +226,7 @@
+ {{section.get('descriptionTemplates').getError('backendError').message}} 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 2ecd8e83b..9ef956366 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 @@ -234,7 +234,7 @@ export class DmpBlueprintDefinitionSectionEditorModel implements DmpBlueprintDef rootPath: `${rootPath}fields[${index}].`, disabled: disabled }) - ), context.getValidation('fields') + ), context.getValidation('fields').validators ), descriptionTemplates: this.formBuilder.array( (this.descriptionTemplates ?? []).map( @@ -244,7 +244,7 @@ export class DmpBlueprintDefinitionSectionEditorModel implements DmpBlueprintDef rootPath: `${rootPath}descriptionTemplates[${index}].`, disabled: disabled }) - ), context.getValidation('descriptionTemplates') + ), context.getValidation('descriptionTemplates').validators ) }); } 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 c850cda7d..8f47d883d 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 @@ -179,19 +179,67 @@
- +
+
+ +
+
+
+
+
+ {{contactIndex + 1}} +
+
drag_indicator
+
+ +
+ {{enumUtils.toDmpContactTypeString(contactType)}} +
+
+
+
+ + {{'DMP-EDITOR.FIELDS1.USER' | translate}} + + {{contact.get('userId').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+
+ + {{'DMP-EDITOR.FIELDS1.FIRST-NAME' | translate}} + + {{contact.get('firstName').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+ + {{'DMP-EDITOR.FIELDS1.LAST-NAME' | translate}} + + {{contact.get('lastName').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+ + {{'DMP-EDITOR.FIELDS1.EMAIL' | translate}} + + {{contact.get('email').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+ +
+ {{formGroup.get('properties').get('contacts').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} +
@@ -204,7 +252,6 @@ {{'GENERAL.VALIDATION.REQUIRED' | translate}}
-
diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.scss b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.scss index 447cb06ab..7d61731ea 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.scss +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.scss @@ -411,4 +411,13 @@ a:hover { ::ng-deep .input-form .mat-form-field-appearance-outline .mat-form-field-infix { font-size: 1rem; padding: 0.6em 0 1em 0 !important; +} + +.drag-handle { + cursor: move; + color: var(--primary-color); +} +.drag-handle-disabled { + cursor: auto; + color: rgba(0, 0, 0, 0.38);; } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts index 152498a55..eb97ea6db 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts @@ -38,10 +38,14 @@ import { LanguageInfo } from '@app/core/model/language-info'; import { LanguageInfoService } from '@app/core/services/culture/language-info-service'; import { DmpAccessType } from '@app/core/common/enum/dmp-access-type'; import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; -import { UntypedFormArray, UntypedFormGroup } from '@angular/forms'; +import { FormArray, UntypedFormArray, UntypedFormGroup } from '@angular/forms'; import { DescriptionTemplateService } from '@app/core/services/description-template/description-template.service'; import { LockPersist } from '@app/core/model/lock/lock.model'; import { LockTargetType } from '@app/core/common/enum/lock-target-type'; +import { UserService } from '@app/core/services/user/user.service'; +import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; +import { DmpContactType } from '@app/core/common/enum/dmp-contact-type'; +import { MatButtonToggleChange } from '@angular/material/button-toggle'; @Component({ selector: 'app-dmp-editor', @@ -64,6 +68,8 @@ export class DmpEditorComponent extends BaseEditor implemen referenceTypeEnum = ReferenceType; dmpAccessTypeEnum = DmpAccessType; dmpAccessTypeEnumValues = this.enumUtils.getEnumValues(DmpAccessType); + dmpContactTypeEnum = DmpContactType; + dmpContactTypeEnumValues = this.enumUtils.getEnumValues(DmpContactType); protected get canDelete(): boolean { return !this.isDeleted && !this.isNew && this.hasPermission(this.authService.permissionEnum.DeleteDmp); @@ -106,7 +112,8 @@ export class DmpEditorComponent extends BaseEditor implemen // public visibilityRulesService: VisibilityRulesService, private languageInfoService: LanguageInfoService, private enumUtils: EnumUtils, - public descriptionTemplateService: DescriptionTemplateService + public descriptionTemplateService: DescriptionTemplateService, + public userService: UserService ) { super(dialog, language, formService, router, uiNotificationService, httpErrorHandlingService, filterService, datePipe, route, queryParamsService); @@ -227,9 +234,9 @@ export class DmpEditorComponent extends BaseEditor implemen formSubmit(): void { this.formService.touchAllFormFields(this.formGroup); - if (!this.isFormValid()) { - return; - } + // if (!this.isFormValid()) { + // return; + // } this.persistEntity(); } @@ -318,6 +325,42 @@ export class DmpEditorComponent extends BaseEditor implemen this.prepareForm(dmp); } + // + // + // Contacts + // + // + addContact(): void { + const contactArray = this.formGroup.get('properties').get('contacts') as FormArray; + (this.formGroup.get('properties').get('contacts') as FormArray).push(this.editorModel.createChildContact(contactArray.length)); + } + + removeContact(contactIndex: number): void { + (this.formGroup.get('properties').get('contacts') as FormArray).removeAt(contactIndex); + + DmpEditorModel.reApplyPropertiesValidators( + { + formGroup: this.formGroup, + validationErrorModel: this.editorModel.validationErrorModel + } + ); + this.formGroup.get('properties').get('contacts').markAsDirty(); + } + + dropContacts(event: CdkDragDrop) { + const sectionsFormArray = (this.formGroup.get('properties').get('contacts') as FormArray); + + moveItemInArray(sectionsFormArray.controls, event.previousIndex, event.currentIndex); + sectionsFormArray.updateValueAndValidity(); + + DmpEditorModel.reApplyPropertiesValidators( + { + formGroup: this.formGroup, + validationErrorModel: this.editorModel.validationErrorModel + } + ); + this.formGroup.get('properties').get('contacts').markAsDirty(); + } // // 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 43836326e..ef3d0d0e0 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 @@ -1,5 +1,6 @@ import { FormArray, FormControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; import { DmpAccessType } from "@app/core/common/enum/dmp-access-type"; +import { DmpContactType } from "@app/core/common/enum/dmp-contact-type"; import { DmpStatus } from "@app/core/common/enum/dmp-status"; import { IsActive } from "@app/core/common/enum/is-active.enum"; import { DmpBlueprint } from "@app/core/model/dmp-blueprint/dmp-blueprint"; @@ -15,7 +16,7 @@ import { Guid } from "@common/types/guid"; export class DmpEditorModel extends BaseEditorModel implements DmpPersist { label: string; status: DmpStatus; - properties: DmpPropertiesEditorModel = new DmpPropertiesEditorModel(); + properties: DmpPropertiesEditorModel = new DmpPropertiesEditorModel(this.validationErrorModel); description: String; language: String; blueprint: Guid; @@ -121,6 +122,11 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { return baseContext; } + createChildContact(index: number): UntypedFormGroup { + const contact: DmpContactEditorModel = new DmpContactEditorModel(this.validationErrorModel); + return contact.buildForm({ rootPath: 'properties.contacts[' + index + '].' }); + } + static reApplyPropertiesValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, @@ -191,8 +197,8 @@ export class DmpPropertiesEditorModel implements DmpPropertiesPersist { this.validationErrorModel ).fromModel(item).buildForm({ rootPath: `${rootPath}contacts[${index}].` - }), context.getValidation('contacts') - ) + }) + ), context.getValidation('contacts').validators ), }); @@ -331,6 +337,7 @@ export class DmpContactEditorModel implements DmpContactPersist { firstName: string; lastName: string; email: string; + contactType: DmpContactType; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -339,10 +346,11 @@ export class DmpContactEditorModel implements DmpContactPersist { ) { } fromModel(item: DmpContact): DmpContactEditorModel { - this.userId = item.userId; + if(item?.user?.id) this.userId = item.user.id; this.firstName = item.firstName; this.lastName = item.lastName; - this.email = item.email; + this.email = item.email; + this.contactType = item == null ? DmpContactType.Internal : (this.userId != null ? DmpContactType.Internal : DmpContactType.External); return this; } @@ -354,7 +362,7 @@ export class DmpContactEditorModel implements DmpContactPersist { }): UntypedFormGroup { let { context = null, disabled = false, rootPath } = params ?? {} if (context == null) { - context = DmpReferenceEditorModel.createValidationContext({ + context = DmpContactEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, rootPath }); @@ -365,6 +373,7 @@ export class DmpContactEditorModel implements DmpContactPersist { firstName: [{ value: this.firstName, disabled: disabled }, context.getValidation('firstName').validators], lastName: [{ value: this.lastName, disabled: disabled }, context.getValidation('lastName').validators], email: [{ value: this.email, disabled: disabled }, context.getValidation('email').validators], + contactType: [{ value: this.contactType, disabled: disabled }, context.getValidation('contactType').validators], }); } @@ -380,6 +389,7 @@ export class DmpContactEditorModel implements DmpContactPersist { baseValidationArray.push({ key: 'firstName', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}firstName`)] }); baseValidationArray.push({ key: 'lastName', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}lastName`)] }); baseValidationArray.push({ key: 'email', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}email`)] }); + baseValidationArray.push({ key: 'contactType', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}contactType`)] }); baseContext.validation = baseValidationArray; return baseContext; diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.module.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.module.ts index fab72aad7..b4c1b6747 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.module.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.module.ts @@ -8,6 +8,7 @@ import { DmpEditorComponent } from './dmp-editor.component'; import { DmpEditorRoutingModule } from './dmp-editor.routing'; import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; import { ReferenceFieldModule } from '@app/ui/reference/reference-field/reference-field.module'; +import { DragDropModule } from '@angular/cdk/drag-drop'; @NgModule({ imports: [ @@ -18,7 +19,8 @@ import { ReferenceFieldModule } from '@app/ui/reference/reference-field/referenc DmpEditorRoutingModule, RichTextEditorModule, AutoCompleteModule, - ReferenceFieldModule + ReferenceFieldModule, + DragDropModule, ], declarations: [ DmpEditorComponent, 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 2b9e9ac2e..0ca8c6a7f 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 @@ -5,6 +5,7 @@ import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, Dm import { Dmp, DmpBlueprintValue, DmpContact, DmpDescriptionTemplate, DmpProperties } from '@app/core/model/dmp/dmp'; import { DmpReference, DmpReferenceData } from '@app/core/model/dmp/dmp-reference'; import { Reference } from '@app/core/model/reference/reference'; +import { User } from '@app/core/model/user/user'; import { DmpService } from '@app/core/services/dmp/dmp.service'; import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service'; import { BaseEditorResolver } from '@common/base/base-editor.resolver'; @@ -37,7 +38,7 @@ export class DmpEditorResolver extends BaseEditorResolver { [nameof(x => x.properties), nameof(x => x.dmpBlueprintValues), nameof(x => x.fieldId)].join('.'), [nameof(x => x.properties), nameof(x => x.dmpBlueprintValues), nameof(x => x.fieldValue)].join('.'), - [nameof(x => x.properties), nameof(x => x.contacts), nameof(x => x.userId)].join('.'), + [nameof(x => x.properties), nameof(x => x.contacts), nameof(x => x.user), nameof(x => x.id)].join('.'), [nameof(x => x.properties), nameof(x => x.contacts), nameof(x => x.firstName)].join('.'), [nameof(x => x.properties), nameof(x => x.contacts), nameof(x => x.lastName)].join('.'), [nameof(x => x.properties), nameof(x => x.contacts), nameof(x => x.email)].join('.'), diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 32185b6ea..3c72b79da 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -1611,6 +1611,7 @@ "FIELD-DATA-TYPE": "Data Type", "FIELD-REQUIRED": "Required", "DESCRIPTION-TEMPLATES": "Description Templates", + "DESCRIPTION-TEMPLATE": "Description Template", "DESCRIPTION-TEMPLATE-LABEL": "Label", "DESCRIPTION-TEMPLATE-MIN-MULTIPLICITY": "Min Multiplicity", "DESCRIPTION-TEMPLATE-MAX-MULTIPLICITY": "Max Multiplicity", @@ -1741,7 +1742,11 @@ "PUBLICATION": "Publication Date", "CONTACT": "Contact", "COST": "Costs", - "DESCRIPTIONS": "Descriptions" + "DESCRIPTIONS": "Descriptions", + "USER": "User", + "FIRST-NAME": "First Name", + "LAST-NAME": "Last Name", + "EMAIL": "Email" }, "ACTIONS1": { "GO-TO-GRANT": "Go To DMP Grant", @@ -2410,6 +2415,10 @@ "DMP-ACCESS-TYPE": { "PUBLIC": "Public", "RESTRICTED": "Restricted Access" + }, + "DMP-CONTACT-TYPE": { + "INTERNAL": "Internal", + "EXTERNAL": "External" } }, "ADDRESEARCHERS-EDITOR": {