user profile ui changes

This commit is contained in:
amentis 2024-05-13 14:43:44 +03:00
parent 7947df3a3a
commit c40a356058
7 changed files with 123 additions and 27 deletions

View File

@ -53,7 +53,7 @@ public class UserAdditionalInfoBuilder extends BaseBuilder<UserAdditionalInfo, A
if (fields == null || data == null || fields.isEmpty())
return new ArrayList<>();
FieldSet referenceFields = fields.extractPrefixed(this.asPrefix(DescriptionReference._reference));
FieldSet referenceFields = fields.extractPrefixed(this.asPrefix(UserAdditionalInfo._organization));
Map<UUID, Reference> referenceItemsMap = this.collectReferences(referenceFields, data);
List<UserAdditionalInfo> models = new ArrayList<>();

View File

@ -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))
);
}
}

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -111,7 +111,7 @@
<div class="row">
<div class="col organization-form">
<mat-form-field class="w-100">
<app-single-auto-complete placeholder="{{'DMP-EDITOR.PLACEHOLDER.ORGANIZATION' | translate}}" [formControl]="this.formGroup.get('additionalInfo').get('organizationId')" [configuration]="organisationsSingleAutoCompleteConfiguration"></app-single-auto-complete>
<app-single-auto-complete placeholder="{{'DMP-EDITOR.PLACEHOLDER.ORGANIZATION' | translate}}" [formControl]="this.formGroup.get('additionalInfo').get('organization')" [configuration]="organisationsSingleAutoCompleteConfiguration"></app-single-auto-complete>
</mat-form-field>
</div>
</div>

View File

@ -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,11 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
nameof<User>(x => x.additionalInfo.language),
nameof<User>(x => x.additionalInfo.timezone),
nameof<User>(x => x.additionalInfo.culture),
nameof<User>(x => x.additionalInfo.organization),
[nameof<User>(x => x.additionalInfo), nameof<UserAdditionalInfo>(x => x.organization), nameof<Reference>(x => x.id)].join('.'),
[nameof<User>(x => x.additionalInfo), nameof<UserAdditionalInfo>(x => x.organization), nameof<Reference>(x => x.label)].join('.'),
[nameof<User>(x => x.additionalInfo), nameof<UserAdditionalInfo>(x => x.organization), nameof<Reference>(x => x.type), nameof<ReferenceType>(x => x.id)].join('.'),
[nameof<User>(x => x.additionalInfo), nameof<UserAdditionalInfo>(x => x.organization), nameof<Reference>(x => x.reference)].join('.'),
[nameof<User>(x => x.additionalInfo), nameof<UserAdditionalInfo>(x => x.organization), nameof<Reference>(x => x.isActive)].join('.'),
nameof<User>(x => x.additionalInfo.roleOrganization),
nameof<User>(x => x.createdAt),
nameof<User>(x => x.updatedAt),
@ -242,6 +247,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(