diff --git a/backend/core/src/main/java/org/opencdmp/model/builder/UserAdditionalInfoBuilder.java b/backend/core/src/main/java/org/opencdmp/model/builder/UserAdditionalInfoBuilder.java index 27d5e0f89..e81e38102 100644 --- a/backend/core/src/main/java/org/opencdmp/model/builder/UserAdditionalInfoBuilder.java +++ b/backend/core/src/main/java/org/opencdmp/model/builder/UserAdditionalInfoBuilder.java @@ -53,7 +53,7 @@ public class UserAdditionalInfoBuilder extends BaseBuilder(); - FieldSet referenceFields = fields.extractPrefixed(this.asPrefix(DescriptionReference._reference)); + FieldSet referenceFields = fields.extractPrefixed(this.asPrefix(UserAdditionalInfo._organization)); Map referenceItemsMap = this.collectReferences(referenceFields, data); List models = new ArrayList<>(); diff --git a/backend/core/src/main/java/org/opencdmp/model/persist/UserAdditionalInfoPersist.java b/backend/core/src/main/java/org/opencdmp/model/persist/UserAdditionalInfoPersist.java index 76d34e882..24a89f6d6 100644 --- a/backend/core/src/main/java/org/opencdmp/model/persist/UserAdditionalInfoPersist.java +++ b/backend/core/src/main/java/org/opencdmp/model/persist/UserAdditionalInfoPersist.java @@ -1,5 +1,6 @@ package org.opencdmp.model.persist; +import gr.cite.tools.validation.ValidatorFactory; import org.opencdmp.commons.validation.BaseValidator; import gr.cite.tools.validation.specification.Specification; import org.opencdmp.convention.ConventionService; @@ -12,7 +13,6 @@ import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; -import java.util.UUID; public class UserAdditionalInfoPersist { @@ -32,9 +32,9 @@ public class UserAdditionalInfoPersist { private String roleOrganization; - private UUID organizationId; + private ReferencePersist organization; - public static final String _organizationId = "organizationId"; + public static final String _organization = "organization"; public String getAvatarUrl() { return avatarUrl; @@ -76,12 +76,12 @@ public class UserAdditionalInfoPersist { this.roleOrganization = roleOrganization; } - public UUID getOrganizationId() { - return organizationId; + public ReferencePersist getOrganization() { + return organization; } - public void setOrganizationId(UUID organizationId) { - this.organizationId = organizationId; + public void setOrganization(ReferencePersist organization) { + this.organization = organization; } @Component(UserAdditionalInfoPersistValidator.ValidatorName) @@ -91,10 +91,12 @@ public class UserAdditionalInfoPersist { public static final String ValidatorName = "UserAdditionalInfoPersistValidator"; private final MessageSource messageSource; + private final ValidatorFactory validatorFactory; - protected UserAdditionalInfoPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) { + protected UserAdditionalInfoPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource, ValidatorFactory validatorFactory) { super(conventionService, errors); this.messageSource = messageSource; + this.validatorFactory = validatorFactory; } @Override @@ -113,7 +115,12 @@ public class UserAdditionalInfoPersist { .failOn(UserAdditionalInfoPersist._culture).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserAdditionalInfoPersist._culture}, LocaleContextHolder.getLocale())), this.spec() .must(() -> !this.isEmpty(item.getLanguage())) - .failOn(UserAdditionalInfoPersist._language).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserAdditionalInfoPersist._language}, LocaleContextHolder.getLocale())) + .failOn(UserAdditionalInfoPersist._language).failWith(messageSource.getMessage("Validation_Required", new Object[]{UserAdditionalInfoPersist._language}, LocaleContextHolder.getLocale())), + this.refSpec() + .iff(() -> !this.isNull(item.getOrganization())) + .on(UserAdditionalInfoPersist._organization) + .over(item.getOrganization()) + .using(() -> this.validatorFactory.validator(ReferencePersist.ReferenceWithoutTypePersistValidator.class)) ); } } diff --git a/backend/core/src/main/java/org/opencdmp/service/user/UserServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/user/UserServiceImpl.java index c4a865f19..c3139f5f4 100644 --- a/backend/core/src/main/java/org/opencdmp/service/user/UserServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/user/UserServiceImpl.java @@ -26,10 +26,7 @@ import org.opencdmp.authorization.OwnedResource; import org.opencdmp.authorization.Permission; import org.opencdmp.commons.JsonHandlingService; import org.opencdmp.commons.XmlHandlingService; -import org.opencdmp.commons.enums.ActionConfirmationStatus; -import org.opencdmp.commons.enums.ActionConfirmationType; -import org.opencdmp.commons.enums.ContactInfoType; -import org.opencdmp.commons.enums.IsActive; +import org.opencdmp.commons.enums.*; import org.opencdmp.commons.enums.notification.NotificationContactType; import org.opencdmp.commons.notification.NotificationProperties; import org.opencdmp.commons.scope.tenant.TenantScope; @@ -37,6 +34,7 @@ import org.opencdmp.commons.scope.user.UserScope; import org.opencdmp.commons.types.actionconfirmation.MergeAccountConfirmationEntity; import org.opencdmp.commons.types.actionconfirmation.RemoveCredentialRequestEntity; import org.opencdmp.commons.types.notification.*; +import org.opencdmp.commons.types.reference.DefinitionEntity; import org.opencdmp.commons.types.user.AdditionalInfoEntity; import org.opencdmp.commons.types.usercredential.UserCredentialDataEntity; import org.opencdmp.convention.ConventionService; @@ -54,6 +52,9 @@ import org.opencdmp.model.deleter.*; import org.opencdmp.model.persist.*; import org.opencdmp.model.persist.actionconfirmation.MergeAccountConfirmationPersist; import org.opencdmp.model.persist.actionconfirmation.RemoveCredentialRequestPersist; +import org.opencdmp.model.persist.referencedefinition.DefinitionPersist; +import org.opencdmp.model.reference.Reference; +import org.opencdmp.model.referencetype.ReferenceType; import org.opencdmp.model.user.User; import org.opencdmp.model.usercredential.UserCredential; import org.opencdmp.query.*; @@ -187,10 +188,13 @@ public class UserServiceImpl implements UserService { return this.builderFactory.builder(UserBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, User._id), data); } - private @NotNull AdditionalInfoEntity buildAdditionalInfoEntity(UserAdditionalInfoPersist persist){ + private @NotNull AdditionalInfoEntity buildAdditionalInfoEntity(UserAdditionalInfoPersist persist) throws InvalidApplicationException { AdditionalInfoEntity data = new AdditionalInfoEntity(); if (persist == null) return data; - data.setOrganizationId(persist.getOrganizationId()); + if (persist.getOrganization() != null) { + ReferenceEntity organization = this.buildReferenceEntity(persist.getOrganization()); + data.setOrganizationId(organization != null ? organization.getId() : null); + } data.setRoleOrganization(persist.getRoleOrganization()); data.setCulture(persist.getCulture()); data.setTimezone(persist.getTimezone()); @@ -199,6 +203,73 @@ public class UserServiceImpl implements UserService { return data; } + private @NotNull ReferenceEntity buildReferenceEntity(ReferencePersist model) throws InvalidApplicationException { + + ReferenceEntity referenceEntity = null; + if (this.conventionService.isValidGuid(model.getId())) { + referenceEntity = this.entityManager.find(ReferenceEntity.class, model.getId()); + if (referenceEntity == null) + throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Reference.class.getSimpleName()}, LocaleContextHolder.getLocale())); + } else { + referenceEntity = this.queryFactory.query(ReferenceQuery.class).sourceTypes(model.getSourceType()).typeIds(model.getTypeId()).sources(model.getSource()).isActive(IsActive.Active).references(model.getReference()).first(); + if (referenceEntity == null) { + referenceEntity = new ReferenceEntity(); + referenceEntity.setId(UUID.randomUUID()); + referenceEntity.setLabel(model.getLabel()); + referenceEntity.setIsActive(IsActive.Active); + referenceEntity.setCreatedAt(Instant.now()); + referenceEntity.setTypeId(model.getTypeId()); + + referenceEntity.setDefinition(this.xmlHandlingService.toXmlSafe(this.buildDefinitionEntity(model.getDefinition()))); + referenceEntity.setUpdatedAt(Instant.now()); + referenceEntity.setReference(model.getReference()); + referenceEntity.setAbbreviation(model.getAbbreviation()); + referenceEntity.setSource(model.getSource()); + referenceEntity.setSourceType(model.getSourceType()); + try { + ReferenceTypeEntity referenceType = this.queryFactory.query(ReferenceTypeQuery.class).ids(model.getTypeId()).firstAs(new BaseFieldSet().ensure(ReferenceType._id).ensure(ReferenceTypeEntity._tenantId)); + if (referenceType == null) + throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getTypeId(), ReferenceType.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + if (referenceEntity.getSourceType().equals(ReferenceSourceType.External) && !this.tenantScope.isDefaultTenant() && referenceType.getTenantId() == null) { + this.tenantScope.setTempTenant(this.entityManager.getEntityManager(), null, this.tenantScope.getDefaultTenantCode()); + } + this.entityManager.persist(referenceEntity); + } finally { + this.tenantScope.removeTempTenant(this.entityManager.getEntityManager()); + } + } + } + + this.entityManager.flush(); + + return referenceEntity; + } + + private @NotNull DefinitionEntity buildDefinitionEntity(DefinitionPersist persist) { + DefinitionEntity data = new DefinitionEntity(); + if (persist == null) return data; + if (!this.conventionService.isListNullOrEmpty(persist.getFields())) { + data.setFields(new ArrayList<>()); + for (org.opencdmp.model.persist.referencedefinition.FieldPersist fieldPersist : persist.getFields()) { + data.getFields().add(this.buildFieldEntity(fieldPersist)); + } + } + + return data; + } + + private @NotNull org.opencdmp.commons.types.reference.FieldEntity buildFieldEntity(org.opencdmp.model.persist.referencedefinition.FieldPersist persist) { + org.opencdmp.commons.types.reference.FieldEntity data = new org.opencdmp.commons.types.reference.FieldEntity(); + if (persist == null) return data; + + data.setCode(persist.getCode()); + data.setDataType(persist.getDataType()); + data.setCode(persist.getCode()); + + return data; + } + //endregion //region delete diff --git a/dmp-frontend/src/app/core/model/user/user.ts b/dmp-frontend/src/app/core/model/user/user.ts index fa39e12cf..7e6b6be34 100644 --- a/dmp-frontend/src/app/core/model/user/user.ts +++ b/dmp-frontend/src/app/core/model/user/user.ts @@ -1,7 +1,7 @@ import { RoleOrganizationType } from "@app/core/common/enum/role-organization-type"; import { BaseEntity, BaseEntityPersist } from "@common/base/base-entity.model"; import { Guid } from "@common/types/guid"; -import { Reference } from "../reference/reference"; +import { Reference, ReferencePersist } from "../reference/reference"; import { ContactInfoType } from "@notification-service/core/enum/contact-info-type.enum"; export interface User extends BaseEntity { @@ -24,7 +24,7 @@ export interface UserAdditionalInfoPersist { culture: String; language: String; roleOrganization: String; - organizationId: Guid; + organization: ReferencePersist; } export interface UserAdditionalInfo { diff --git a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts index 43863854a..e19029555 100644 --- a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts +++ b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts @@ -154,6 +154,21 @@ export class ConfigurationService extends BaseComponent { return this._authProviders; } + private _researcherId: any; + get researcherId(): boolean { + return this._researcherId; + } + + private _grantId: any; + get grantId(): boolean { + return this._grantId; + } + + private _organizationId: any; + get organizationId(): boolean { + return this._organizationId; + } + public loadConfiguration(): Promise { return new Promise((r, e) => { // We need to exclude all interceptors here, for the initial configuration request. @@ -224,6 +239,10 @@ export class ConfigurationService extends BaseComponent { this._newReleaseNotificationLink = config.newReleaseNotification?.link; this._newReleaseNotificationVersionCode = config.newReleaseNotification?.versionCode; this._authProviders = AuthProviders.parseValue(config.authProviders); + this._researcherId = config.referenceTypes.researcherId; + this._grantId = config.referenceTypes.grantId; + this._organizationId = config.referenceTypes.organizationId; + } } diff --git a/dmp-frontend/src/app/core/services/reference-type/reference-type.service.ts b/dmp-frontend/src/app/core/services/reference-type/reference-type.service.ts index 100a0a5bd..d4c22fd73 100644 --- a/dmp-frontend/src/app/core/services/reference-type/reference-type.service.ts +++ b/dmp-frontend/src/app/core/services/reference-type/reference-type.service.ts @@ -131,14 +131,14 @@ export class ReferenceTypeService { } public getResearcherReferenceType(): any { - return '5a2112e7-ea99-4cfe-98a1-68665e26726e'; + return this.configurationService.researcherId; } public getGrantReferenceType(): any { - return '5b9c284f-f041-4995-96cc-fad7ad13289c'; + return this.configurationService.grantId; } public getOrganizationReferenceType(): any { - return '7eeffb98-58fb-4921-82ec-e27f32f8e738'; + return this.configurationService.organizationId; } } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile-editor.model.ts b/dmp-frontend/src/app/ui/user-profile/user-profile-editor.model.ts index bb0d15c26..0e06a9b65 100644 --- a/dmp-frontend/src/app/ui/user-profile/user-profile-editor.model.ts +++ b/dmp-frontend/src/app/ui/user-profile/user-profile-editor.model.ts @@ -1,6 +1,6 @@ import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { RoleOrganizationType } from '@app/core/common/enum/role-organization-type'; -import { Reference } from '@app/core/model/reference/reference'; +import { ReferencePersist } from '@app/core/model/reference/reference'; import { User, UserAdditionalInfo, UserAdditionalInfoPersist, UserPersist } from '@app/core/model/user/user'; import { BaseEditorModel } from '@common/base/base-form-editor-model'; import { BackendErrorValidator } from '@common/forms/validation/custom-validator'; @@ -77,7 +77,7 @@ export class UserAdditionalInfoEditorModel implements UserAdditionalInfoPersist culture: String; language: String; roleOrganization: RoleOrganizationType; - organizationId: Guid; + organization: ReferencePersist; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -92,7 +92,19 @@ export class UserAdditionalInfoEditorModel implements UserAdditionalInfoPersist this.culture = item.culture; this.language = item.language; this.roleOrganization = item.roleOrganization - this.organizationId = item.organization?.id + if (item.organization){ + this.organization = { + id: item.organization.id, + label: item.organization.label, + reference: item.organization.reference, + source: item.organization.source, + typeId: item.organization.type.id, + description: item.organization.source, + definition: item.organization.definition, + abbreviation: item.organization.abbreviation, + sourceType: item.organization.sourceType + } + } } return this; @@ -118,7 +130,7 @@ export class UserAdditionalInfoEditorModel implements UserAdditionalInfoPersist culture: [{ value: this.culture, disabled: disabled }, context.getValidation('culture').validators], language: [{ value: this.language ? availableLanguages.filter(x => x === this.language).pop() : '', disabled: disabled }, context.getValidation('language').validators], roleOrganization: [{ value: this.roleOrganization, disabled: disabled }, context.getValidation('roleOrganization').validators], - organizationId: [{ value: this.organizationId, disabled: disabled }, context.getValidation('organizationId').validators], + organization: [{ value: this.organization, disabled: disabled }, context.getValidation('organization').validators], }); } @@ -135,7 +147,7 @@ export class UserAdditionalInfoEditorModel implements UserAdditionalInfoPersist baseValidationArray.push({ key: 'culture', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}culture`)] }); baseValidationArray.push({ key: 'language', validators: [Validators.required, BackendErrorValidator(validationErrorModel, `${rootPath}language`)] }); baseValidationArray.push({ key: 'roleOrganization', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}roleOrganization`)] }); - baseValidationArray.push({ key: 'organizationId', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}organizationId`)] }); + baseValidationArray.push({ key: 'organization', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}organization`)] }); baseContext.validation = baseValidationArray; return baseContext; @@ -152,7 +164,7 @@ export class UserAdditionalInfoEditorModel implements UserAdditionalInfoPersist validationErrorModel }); - ['avatarUrl', 'timezone', 'culture', 'language', 'roleOrganization', 'organizationId'].forEach(keyField => { + ['avatarUrl', 'timezone', 'culture', 'language', 'roleOrganization', 'organization'].forEach(keyField => { const control = formGroup?.get(keyField); control?.clearValidators(); control?.addValidators(context.getValidation(keyField).validators); diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.component.html b/dmp-frontend/src/app/ui/user-profile/user-profile.component.html index e5b1353a4..701b5d4ce 100644 --- a/dmp-frontend/src/app/ui/user-profile/user-profile.component.html +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.component.html @@ -111,7 +111,7 @@
- +
diff --git a/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts b/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts index 14dac24ba..f9f0f4923 100644 --- a/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts +++ b/dmp-frontend/src/app/ui/user-profile/user-profile.component.ts @@ -6,7 +6,7 @@ import { ActivatedRoute, Params, Router } from '@angular/router'; import { RoleOrganizationType } from '@app/core/common/enum/role-organization-type'; import { CultureInfo } from '@app/core/model/culture-info'; import { Reference } from '@app/core/model/reference/reference'; -import { User, UserCredential, UserPersist } from '@app/core/model/user/user'; +import { User, UserAdditionalInfo, UserCredential, UserPersist } from '@app/core/model/user/user'; import { AuthService } from '@app/core/services/auth/auth.service'; import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; import { CultureService } from '@app/core/services/culture/culture-service'; @@ -37,6 +37,7 @@ import { ReferenceService } from '@app/core/services/reference/reference.service import { ReferenceTypeService } from '@app/core/services/reference-type/reference-type.service'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; import { ReferenceSourceType } from '@app/core/common/enum/reference-source-type'; +import { ReferenceType } from '@app/core/model/reference-type/reference-type'; @Component({ selector: 'app-user-profile', @@ -147,7 +148,13 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes nameof(x => x.additionalInfo.language), nameof(x => x.additionalInfo.timezone), nameof(x => x.additionalInfo.culture), - nameof(x => x.additionalInfo.organization), + [nameof(x => x.additionalInfo), nameof(x => x.organization), nameof(x => x.id)].join('.'), + [nameof(x => x.additionalInfo), nameof(x => x.organization), nameof(x => x.label)].join('.'), + [nameof(x => x.additionalInfo), nameof(x => x.organization), nameof(x => x.type), nameof(x => x.id)].join('.'), + [nameof(x => x.additionalInfo), nameof(x => x.organization), nameof(x => x.reference)].join('.'), + [nameof(x => x.additionalInfo), nameof(x => x.organization), nameof(x => x.source)].join('.'), + [nameof(x => x.additionalInfo), nameof(x => x.organization), nameof(x => x.sourceType)].join('.'), + [nameof(x => x.additionalInfo), nameof(x => x.organization), nameof(x => x.isActive)].join('.'), nameof(x => x.additionalInfo.roleOrganization), nameof(x => x.createdAt), nameof(x => x.updatedAt), @@ -242,6 +249,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes return; } const formData = this.formService.getValue(this.formGroup.value) as UserPersist; + formData.additionalInfo.organization.typeId = Guid.parse(this.referenceTypeService.getOrganizationReferenceType()); this.userService.persist(formData) .pipe(takeUntil(this._destroyed)) .subscribe( @@ -257,9 +265,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes }); // .subscribe(result => window.location.reload()); }, - error => { - console.log(error); - }); + error => this.onCallbackError(error)); } public unlock() { diff --git a/dmp-frontend/src/assets/config/config.json b/dmp-frontend/src/assets/config/config.json index f43a62736..83be8f664 100644 --- a/dmp-frontend/src/assets/config/config.json +++ b/dmp-frontend/src/assets/config/config.json @@ -65,5 +65,10 @@ "cultures": ["en"] } ] + }, + "referenceTypes": { + "researcherId": "5a2112e7-ea99-4cfe-98a1-68665e26726e", + "grantId": "5b9c284f-f041-4995-96cc-fad7ad13289c", + "organizationId": "7eeffb98-58fb-4921-82ec-e27f32f8e738" } } diff --git a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DatasetMigrationService.java b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DatasetMigrationService.java index b6699a062..336c67802 100644 --- a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DatasetMigrationService.java +++ b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/DatasetMigrationService.java @@ -167,7 +167,7 @@ public class DatasetMigrationService { private List getOrCreateDmpDescriptionTemplateEntity(Dataset item, UUID sectionId, List dmpDescriptionTemplateEntities){ List itemDescriptionTemplates = dmpDescriptionTemplateEntities.stream().filter(x-> x.getDescriptionTemplateGroupId().equals(item.getProfile().getGroupId()) && x.getDmpId().equals(item.getDmp().getId()) && x.getSectionId().equals(sectionId)).toList(); if (itemDescriptionTemplates.isEmpty()) { - logger.warn("Migrate Dataset " + item.getId() + " cannot found DmpDescriptionTemplateEntity for section " + item.getDmpSectionIndex()); + if (!item.getStatus().equals(Dataset.Status.DELETED.getValue())) logger.warn("Migrate Dataset " + item.getId() + " cannot found DmpDescriptionTemplateEntity for section " + item.getDmpSectionIndex()); if (dmpDescriptionTemplateEntities.stream().anyMatch(x -> x.getDmpId().equals(item.getDmp().getId()) && x.getSectionId().equals(sectionId))) { DmpDescriptionTemplateEntity dmpDescriptionTemplateEntity = new DmpDescriptionTemplateEntity(); dmpDescriptionTemplateEntity.setId(UUID.randomUUID()); @@ -176,7 +176,7 @@ public class DatasetMigrationService { dmpDescriptionTemplateEntity.setCreatedAt(item.getCreated() != null ? item.getCreated().toInstant() : Instant.now()); dmpDescriptionTemplateEntity.setUpdatedAt(item.getModified() != null ? item.getModified().toInstant() : Instant.now()); dmpDescriptionTemplateEntity.setSectionId(sectionId); - dmpDescriptionTemplateEntity.setIsActive(IsActive.Active); + dmpDescriptionTemplateEntity.setIsActive(!item.getStatus().equals(Dataset.Status.DELETED.getValue()) ? IsActive.Active : IsActive.Inactive); this.entityManager.persist(dmpDescriptionTemplateEntity); itemDescriptionTemplates = List.of(dmpDescriptionTemplateEntity); } else { @@ -189,8 +189,9 @@ public class DatasetMigrationService { private PropertyDefinitionEntity buildPropertyDefinitionEntity(Dataset item, org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity descriptionTemplateDefinitionEntity, Map referenceTypeDefinitionEntityMap, Map referenceMap) { if (this.conventionService.isNullOrEmpty(item.getProperties())) return null; JSONObject jObject = new JSONObject(item.getProperties()); - Map properties = jObject.toMap(); - + Map properties = new HashMap<>(); + for (Map.Entry entry : jObject.toMap().entrySet()) properties.put(entry.getKey().trim(), entry.getValue()); + PropertyDefinitionEntity propertyDefinitionEntity = new PropertyDefinitionEntity(); propertyDefinitionEntity.setFieldSets(new HashMap<>()); @@ -225,7 +226,7 @@ public class DatasetMigrationService { continue; } - this.addSimpleField(item, propertyDefinitionEntity, currentFieldSet, currentField, properties, referenceTypeDefinitionEntityMap, referenceMap); + this.addSimpleField(item, propertyDefinitionEntity, currentFieldSet, currentField, properties.get(key), referenceTypeDefinitionEntityMap, referenceMap); } } } @@ -315,13 +316,13 @@ public class DatasetMigrationService { if (ordinal == SimpleFieldSetOrdinal) throw new MyApplicationException("Fieldset has migration simple fieldset ordinal " + SimpleFieldSetOrdinal); - this.addMultipleField(item, propertyDefinitionFieldSetEntity, ordinal, currentField, properties, referenceTypeDefinitionEntityMap, referenceMap); + this.addMultipleField(item, propertyDefinitionFieldSetEntity, ordinal, currentField, properties.get(key), referenceTypeDefinitionEntityMap, referenceMap); } } } - private void addMultipleField(Dataset item, PropertyDefinitionFieldSetEntity propertyDefinitionFieldSetEntity, int ordinal, org.opencdmp.commons.types.descriptiontemplate.FieldEntity currentField, Map properties, Map referenceTypeDefinitionEntityMap, Map referenceMap){ + private void addMultipleField(Dataset item, PropertyDefinitionFieldSetEntity propertyDefinitionFieldSetEntity, int ordinal, org.opencdmp.commons.types.descriptiontemplate.FieldEntity currentField, Object propertyValue, Map referenceTypeDefinitionEntityMap, Map referenceMap){ PropertyDefinitionFieldSetItemEntity propertyDefinitionFieldSetItemEntity = propertyDefinitionFieldSetEntity.getItems().stream().filter(x-> x.getOrdinal() == ordinal).findFirst().orElse(null); if (propertyDefinitionFieldSetItemEntity == null){ @@ -331,10 +332,10 @@ public class DatasetMigrationService { propertyDefinitionFieldSetEntity.getItems().add(propertyDefinitionFieldSetItemEntity); } - propertyDefinitionFieldSetItemEntity.getFields().put(currentField.getId().trim(), this.buildField(item, currentField, properties, referenceTypeDefinitionEntityMap, referenceMap)); + propertyDefinitionFieldSetItemEntity.getFields().put(currentField.getId().trim(), this.buildField(item, currentField, propertyValue, referenceTypeDefinitionEntityMap, referenceMap)); } - private void addSimpleField(Dataset item, PropertyDefinitionEntity propertyDefinitionEntity, FieldSetEntity currentFieldSet, org.opencdmp.commons.types.descriptiontemplate.FieldEntity currentField, Map properties, Map referenceTypeDefinitionEntityMap, Map referenceMap){ + private void addSimpleField(Dataset item, PropertyDefinitionEntity propertyDefinitionEntity, FieldSetEntity currentFieldSet, org.opencdmp.commons.types.descriptiontemplate.FieldEntity currentField, Object propertyValue, Map referenceTypeDefinitionEntityMap, Map referenceMap){ PropertyDefinitionFieldSetEntity propertyDefinitionFieldSetEntity = propertyDefinitionEntity.getFieldSets().getOrDefault(currentFieldSet.getId().trim(), null); if (propertyDefinitionFieldSetEntity == null) { propertyDefinitionFieldSetEntity = new PropertyDefinitionFieldSetEntity(); @@ -352,7 +353,7 @@ public class DatasetMigrationService { propertyDefinitionFieldSetItemEntity = propertyDefinitionFieldSetEntity.getItems().getFirst(); } - propertyDefinitionFieldSetItemEntity.getFields().put(currentField.getId().trim(), this.buildField(item, currentField, properties, referenceTypeDefinitionEntityMap, referenceMap)); + propertyDefinitionFieldSetItemEntity.getFields().put(currentField.getId().trim(), this.buildField(item, currentField, propertyValue, referenceTypeDefinitionEntityMap, referenceMap)); } @@ -377,9 +378,9 @@ public class DatasetMigrationService { propertyDefinitionFieldSetItemEntity.setComment(comment); } - private FieldEntity buildField(Dataset item, org.opencdmp.commons.types.descriptiontemplate.FieldEntity currentField, Map properties, Map referenceTypeDefinitionEntityMap, Map referenceMap){ + private FieldEntity buildField(Dataset item, org.opencdmp.commons.types.descriptiontemplate.FieldEntity currentField, Object propertyValue, Map referenceTypeDefinitionEntityMap, Map referenceMap){ FieldEntity fieldEntity = new FieldEntity(); - String textValue = properties.get(currentField.getId()) != null ? properties.get(currentField.getId()).toString() : null; + String textValue = propertyValue != null ? propertyValue.toString() : null; if (textValue == null || textValue.isEmpty()) return fieldEntity; switch (currentField.getData().getFieldType()){ case FREE_TEXT, TEXT_AREA, RICH_TEXT_AREA, RADIO_BOX -> fieldEntity.setTextValue(textValue.trim()); @@ -416,7 +417,7 @@ public class DatasetMigrationService { if(!this.conventionService.isNullOrEmpty(textValue)) { Map valuesParsed = migrationTools.tryParseJsonAsObjectString(Map.class, textValue); if (valuesParsed == null) { - valuesParsed = (Map) properties.get(currentField.getId()); + valuesParsed = (Map) propertyValue; } if (valuesParsed == null) throw new MyApplicationException("Could not parse upload : " + textValue); String id = valuesParsed.getOrDefault("id", null); @@ -999,7 +1000,7 @@ public class DatasetMigrationService { data.setSourceType(ReferenceSourceType.Internal); data.setSource("Internal"); if (dataset.getCreator() != null) data.setCreatedById(dataset.getCreator().getId()); - logger.warn("Migrate Dataset " + dataset.getId() + " " + dataset.getLabel() + " reference auto created as internal " + referenceTypeDataEntity.getReferenceTypeId() + " for value " + this.jsonHandlingService.toJsonSafe(item)); + //logger.warn("Migrate Dataset " + dataset.getId() + " " + dataset.getLabel() + " reference auto created as internal " + referenceTypeDataEntity.getReferenceTypeId() + " for value " + this.jsonHandlingService.toJsonSafe(item)); } ReferenceEntity existingEntity = referenceMap.getOrDefault(new ReferenceKey(data), null); diff --git a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/StorageFileMigrationService.java b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/StorageFileMigrationService.java index c301362ce..bd4d602ad 100644 --- a/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/StorageFileMigrationService.java +++ b/dmp-migration-tool/web/src/main/java/eu/old/eudat/migration/StorageFileMigrationService.java @@ -63,9 +63,8 @@ public class StorageFileMigrationService { logger.debug("Migrate FileUpload " + page * PageSize + " of " + total); for (FileUpload item : items) { entityManager.detach(item); -// File file = new File(this.environment.getProperty("file.storage") + item.getId().toString()); -// if (!file.exists()) file = new File(this.environment.getProperty("temp.temp") + item.getId().toString()); -// if (!file.exists()) throw new MyApplicationException("Storage file not exist " + item.getId().toString()); + File file = new File(this.environment.getProperty("file.migration-storage") + item.getId().toString()); + if (!file.exists()) throw new MyApplicationException("Storage file not exist " + item.getId().toString()); StorageFileEntity data = new StorageFileEntity(); data.setId(item.getId()); @@ -80,11 +79,11 @@ public class StorageFileMigrationService { data.setPurgedAt(null); if (item.getCreator() == null) data.setOwnerId(item.getCreator().getId()); -// File destinationFile = new File(Paths.get(this.environment.getProperty("file.mainstorage"), data.getFileRef()).toString()); -// boolean fileCopied = FileCopyUtils.copy(file, destinationFile) > 0; -// if (!fileCopied) throw new MyApplicationException("Storage file not copied " + data.getId().toString()); + File destinationFile = new File(Paths.get(this.environment.getProperty("file.migrated-storage"), data.getFileRef()).toString()); + boolean fileCopied = FileCopyUtils.copy(file, destinationFile) > 0; + if (!fileCopied) throw new MyApplicationException("Storage file not copied " + data.getId().toString()); // -// filesToDelete.add(file); + filesToDelete.add(file); this.entityManager.persist(data); } diff --git a/dmp-migration-tool/web/src/main/java/eu/old/eudat/publicapi/migration/MigrationController.java b/dmp-migration-tool/web/src/main/java/eu/old/eudat/publicapi/migration/MigrationController.java index 91a56b536..6eeb6991f 100644 --- a/dmp-migration-tool/web/src/main/java/eu/old/eudat/publicapi/migration/MigrationController.java +++ b/dmp-migration-tool/web/src/main/java/eu/old/eudat/publicapi/migration/MigrationController.java @@ -113,12 +113,12 @@ public class MigrationController { // this.dmpMigrationService.migrate(); // this.dmpDatasetProfileMigrationService.migrate(); // this.dmpUserMigrationService.migrate(); -// - //Description - this.datasetMigrationService.migrate(); - this.datasetReferenceMigrationService.migrateDatasetReferences(); - this.tagMigrationService.migrate(); +// //Description +// this.datasetMigrationService.migrate(); +// this.datasetReferenceMigrationService.migrateDatasetReferences(); +// this.tagMigrationService.migrate(); +// this.storageFileMigrationService.migrate(); // throw new RuntimeException(""); diff --git a/docs/docs/documentation/administration/templates/conditional-questions.md b/docs/docs/documentation/administration/templates/conditional-questions.md index b7b46ed4b..9e13463b4 100644 --- a/docs/docs/documentation/administration/templates/conditional-questions.md +++ b/docs/docs/documentation/administration/templates/conditional-questions.md @@ -5,4 +5,18 @@ description: View details about the conditional questions # Conditional Questions -TODO: thgiannos \ No newline at end of file +You can set a question to be hidden by default and only show up if a certain condition is met. When you press `Make Conditional Question` on a question, you make it the source of the condition. Then, you must select the question you want to hide *(in the `then show Question` control)* and a value *(in the `If Value is` control)* for the answer that will satisfy the condition. + +There can be more than one conditions set. In that case, all of them must be met. Also, it is possible to make specific question fields conditional by selecting them in the `then show Question` dropdown. All the options are grouped as `Questions` and `Inputs` respectively. + +:::tip + +It is recommended to specify placeholder texts for all the added inputs because they are also used in the question dropdown. Otherwise, they will be listed as '*\*', making the selection of the ones you want to hide difficult. + +::: + +:::info + +All the questions that expect text, selection list, checkbox and radio box based answers can be used as a condition, as long as they are not system specific like [references](/docs/documentation/administration/reference-types). + +::: \ No newline at end of file diff --git a/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandlerImpl.java b/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandlerImpl.java index 622185c5b..bc8ae7b5f 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandlerImpl.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/integrationevent/inbox/notify/NotifyIntegrationEventHandlerImpl.java @@ -79,9 +79,6 @@ public class NotifyIntegrationEventHandlerImpl implements NotifyIntegrationEvent NotifyIntegrationEvent event = this.jsonHandlingService.fromJsonSafe(NotifyIntegrationEvent.class, message); if (event == null) return EventProcessingStatus.Error; - if (event.getUserId() == null) { - throw new MyValidationException(this.errors.getModelValidation().getCode(), "userId", messageSource.getMessage("Validation_Required", new Object[]{"userId"}, LocaleContextHolder.getLocale())); - } logger.debug("Handling {}", NotifyIntegrationEvent.class.getSimpleName()); NotificationPersist model = new NotificationPersist(); @@ -125,7 +122,7 @@ public class NotifyIntegrationEventHandlerImpl implements NotifyIntegrationEvent notificationService.persist(model, new BaseFieldSet()); auditService.track(AuditableAction.Notification_Persist, Map.ofEntries( - new AbstractMap.SimpleEntry("id", event.getUserId()) + new AbstractMap.SimpleEntry("id", event.getUserId() != null ? event.getUserId() : event.getContactHint()) )); } catch (Exception ex) { status = EventProcessingStatus.Error; diff --git a/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationBuilder.java b/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationBuilder.java index e31e5e747..c699f7b55 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationBuilder.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/model/builder/NotificationBuilder.java @@ -120,7 +120,7 @@ public class NotificationBuilder extends BaseBuilder itemMap; if (!fields.hasOtherField(this.asIndexer(User._id))) { itemMap = this.asEmpty( - data.stream().map(NotificationEntity::getUserId).distinct().collect(Collectors.toList()), + data.stream().map(NotificationEntity::getUserId).filter(Objects::nonNull).distinct().collect(Collectors.toList()), x -> { User item = new User(); item.setId(x); @@ -129,7 +129,7 @@ public class NotificationBuilder extends BaseBuilder orderContactTypesFromPreferences(NotificationEntity notification) { + if (notification.getUserId() == null) return null; Ordering ordering = new Ordering(); ordering.addAscending(UserNotificationPreference._ordinal); UserNotificationPreferenceQuery query = this.queryFactory.query(UserNotificationPreferenceQuery.class).userId(notification.getUserId()).type(notification.getType()).isActives(IsActive.Active); @@ -175,7 +176,7 @@ public class NotificationServiceImpl implements NotificationService { } private List orderContactTypes(NotificationEntity notification) { - List contactTypes = this.channelResolutionService.resolve(notification.getType(), notification.getUserId()); + List contactTypes = notification.getUserId() == null ? this.channelResolutionService.resolve(notification.getType()): this.channelResolutionService.resolve(notification.getType(), notification.getUserId()); if (notification.getContactTypeHint() == null) return contactTypes; List ordered = new ArrayList<>(Collections.singleton(notification.getContactTypeHint()));