diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/DmpQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/DmpQuery.java index 0b70cd869..5b6f6fe6c 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/DmpQuery.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/DmpQuery.java @@ -4,10 +4,7 @@ import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.authorization.Permission; import eu.eudat.commons.enums.*; import eu.eudat.commons.scope.user.UserScope; -import eu.eudat.data.DmpDescriptionTemplateEntity; -import eu.eudat.data.DmpEntity; -import eu.eudat.data.DmpReferenceEntity; -import eu.eudat.data.DmpUserEntity; +import eu.eudat.data.*; import eu.eudat.model.Dmp; import eu.eudat.model.PublicDmp; import eu.eudat.query.utils.QueryUtilsService; @@ -364,6 +361,11 @@ public class DmpQuery extends QueryBase { predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DmpEntity._id)).value(subQuery.Query)); } + if (this.entityDoiQuery != null) { + QueryContext subQuery = this.applySubQuery(this.entityDoiQuery, queryContext, UUID.class, entityDoiEntityRoot -> entityDoiEntityRoot.get(EntityDoiEntity._entityId)); + predicates.add(queryContext.CriteriaBuilder.in(queryContext.Root.get(DmpEntity._id)).value(subQuery.Query)); + } + if (!predicates.isEmpty()) { Predicate[] predicatesArray = predicates.toArray(new Predicate[0]); return queryContext.CriteriaBuilder.and(predicatesArray); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/deposit/DepositServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/deposit/DepositServiceImpl.java index 6f16bd3ad..50362a9a6 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/deposit/DepositServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/deposit/DepositServiceImpl.java @@ -5,13 +5,24 @@ import eu.eudat.authorization.Permission; import eu.eudat.authorization.authorizationcontentresolver.AuthorizationContentResolver; import eu.eudat.commonmodels.models.FileEnvelopeModel; import eu.eudat.commonmodels.models.dmp.DmpModel; +import eu.eudat.commons.JsonHandlingService; +import eu.eudat.commons.enums.ContactInfoType; +import eu.eudat.commons.enums.IsActive; import eu.eudat.commons.enums.StorageType; +import eu.eudat.commons.notification.NotificationProperties; import eu.eudat.commons.scope.user.UserScope; +import eu.eudat.commons.types.notification.*; +import eu.eudat.convention.ConventionService; import eu.eudat.data.DmpEntity; +import eu.eudat.data.DmpUserEntity; +import eu.eudat.data.UserEntity; import eu.eudat.depositinterface.repository.DepositClient; import eu.eudat.depositinterface.repository.DepositConfiguration; +import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEvent; +import eu.eudat.integrationevent.outbox.notification.NotifyIntegrationEventHandler; import eu.eudat.model.EntityDoi; import eu.eudat.model.StorageFile; +import eu.eudat.model.UserContactInfo; import eu.eudat.model.builder.commonmodels.DepositConfigurationBuilder; import eu.eudat.model.builder.commonmodels.dmp.DmpCommonModelBuilder; import eu.eudat.model.persist.StorageFilePersist; @@ -19,6 +30,9 @@ import eu.eudat.model.persist.deposit.DepositAuthenticateRequest; import eu.eudat.model.persist.deposit.DepositRequest; import eu.eudat.model.persist.EntityDoiPersist; import eu.eudat.query.DmpQuery; +import eu.eudat.query.DmpUserQuery; +import eu.eudat.query.UserContactInfoQuery; +import eu.eudat.query.UserQuery; import eu.eudat.service.entitydoi.EntityDoiService; import eu.eudat.service.storage.StorageFileProperties; import eu.eudat.service.storage.StorageFileService; @@ -28,6 +42,7 @@ import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeFilterFunction; import gr.cite.commons.web.oidc.filter.webflux.TokenExchangeModel; import gr.cite.tools.data.builder.BuilderFactory; +import gr.cite.tools.data.query.Ordering; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.exception.MyNotFoundException; import gr.cite.tools.fieldset.BaseFieldSet; @@ -42,11 +57,13 @@ import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; +import javax.management.InvalidApplicationException; import java.io.IOException; import java.net.URI; import java.net.URLConnection; import java.time.Duration; import java.util.*; +import java.util.stream.Collectors; @Service public class DepositServiceImpl implements DepositService { @@ -67,6 +84,10 @@ public class DepositServiceImpl implements DepositService { private final ValidatorFactory validatorFactory; private final StorageFileProperties storageFileProperties; private final AuthorizationContentResolver authorizationContentResolver; + private final ConventionService conventionService; + private final JsonHandlingService jsonHandlingService; + private final NotificationProperties notificationProperties; + private final NotifyIntegrationEventHandler eventHandler; @Autowired public DepositServiceImpl(DepositProperties depositProperties, TokenExchangeCacheService tokenExchangeCacheService, @@ -74,7 +95,7 @@ public class DepositServiceImpl implements DepositService { EntityDoiService doiService, QueryFactory queryFactory, MessageSource messageSource, - BuilderFactory builderFactory, DepositConfigurationCacheService depositConfigurationCacheService, FileTransformerService fileTransformerService, StorageFileService storageFileService, UserScope userScope, ValidatorFactory validatorFactory, StorageFileProperties storageFileProperties, AuthorizationContentResolver authorizationContentResolver) { + BuilderFactory builderFactory, DepositConfigurationCacheService depositConfigurationCacheService, FileTransformerService fileTransformerService, StorageFileService storageFileService, UserScope userScope, ValidatorFactory validatorFactory, StorageFileProperties storageFileProperties, AuthorizationContentResolver authorizationContentResolver, ConventionService conventionService, JsonHandlingService jsonHandlingService, NotificationProperties notificationProperties, NotifyIntegrationEventHandler eventHandler) { this.depositProperties = depositProperties; this.tokenExchangeCacheService = tokenExchangeCacheService; this.authorizationService = authorizationService; @@ -89,7 +110,11 @@ public class DepositServiceImpl implements DepositService { this.validatorFactory = validatorFactory; this.storageFileProperties = storageFileProperties; this.authorizationContentResolver = authorizationContentResolver; - this.clients = new HashMap<>(); + this.conventionService = conventionService; + this.jsonHandlingService = jsonHandlingService; + this.notificationProperties = notificationProperties; + this.eventHandler = eventHandler; + this.clients = new HashMap<>(); } private DepositClient getDepositClient(String repositoryId) { @@ -181,8 +206,47 @@ public class DepositServiceImpl implements DepositService { doiPersist.setRepositoryId(dmpDepositModel.getRepositoryId()); doiPersist.setDoi(doi); doiPersist.setEntityId(dmpEntity.getId()); + this.sendNotification(dmpEntity); return doiService.persist(doiPersist, dmpDepositModel.getProject()); } + + private void sendNotification(DmpEntity dmpEntity) throws InvalidApplicationException { + List dmpUsers = this.queryFactory.query(DmpUserQuery.class).ids(dmpEntity.getId()).isActives(IsActive.Active).collect(); + if (this.conventionService.isListNullOrEmpty(dmpUsers)){ + throw new MyNotFoundException("Dmp does not have Users"); + } + + List users = this.queryFactory.query(UserQuery.class).ids(dmpUsers.stream().map(x -> x.getUserId()).collect(Collectors.toList())).isActive(IsActive.Active).collect(); + + for (UserEntity user: users) { + if (!user.getId().equals(this.userScope.getUserIdSafe()) && !this.conventionService.isListNullOrEmpty(dmpUsers.stream().filter(x -> x.getUserId().equals(user.getId())).collect(Collectors.toList()))){ + this.createDmpDepositNotificationEvent(dmpEntity, user); + } + } + } + + private void createDmpDepositNotificationEvent(DmpEntity dmp, UserEntity user) throws InvalidApplicationException { + NotifyIntegrationEvent event = new NotifyIntegrationEvent(); + event.setUserId(user.getId()); + UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); + query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); + + List contactPairs = new ArrayList<>(); + contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue())); + NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); + event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); + event.setNotificationType(notificationProperties.getDmpDepositType()); + NotificationFieldData data = new NotificationFieldData(); + List fieldInfoList = new ArrayList<>(); + fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName())); + fieldInfoList.add(new FieldInfo("{reasonName}", DataType.String, this.queryFactory.query(UserQuery.class).ids(this.userScope.getUserId()).first().getName())); + fieldInfoList.add(new FieldInfo("{name}", DataType.String, dmp.getLabel())); + fieldInfoList.add(new FieldInfo("{id}", DataType.String, dmp.getId().toString())); + data.setFields(fieldInfoList); + event.setData(jsonHandlingService.toJsonSafe(data)); + + eventHandler.handle(event); + } private String addFileToSharedStorage(eu.eudat.model.file.FileEnvelope file) throws IOException { StorageFilePersist storageFilePersist = new StorageFilePersist(); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java index f0890cedf..636f26c5f 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/description/DescriptionServiceImpl.java @@ -302,8 +302,7 @@ public class DescriptionServiceImpl implements DescriptionService { if (!dmpUser.getUserId().equals(this.userScope.getUserIdSafe())){ UserEntity user = this.queryFactory.query(UserQuery.class).ids(dmpUser.getUserId()).first(); if (user != null){ - this.createDescriptionNotificationEvent(description, user, NotificationContactType.EMAIL); - this.createDescriptionNotificationEvent(description, user, NotificationContactType.IN_APP); + this.createDescriptionNotificationEvent(description, user); } } } @@ -353,9 +352,9 @@ public class DescriptionServiceImpl implements DescriptionService { return cleanData; } - private void createDescriptionNotificationEvent(DescriptionEntity description, UserEntity user, NotificationContactType type) throws InvalidApplicationException { + private void createDescriptionNotificationEvent(DescriptionEntity description, UserEntity user) throws InvalidApplicationException { NotifyIntegrationEvent event = new NotifyIntegrationEvent(); - event.setUserId(this.userScope.getUserId()); + event.setUserId(user.getId()); UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); @@ -364,7 +363,6 @@ public class DescriptionServiceImpl implements DescriptionService { contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue())); NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); - event.setContactTypeHint(type); event = this.applyNotificationType(description.getStatus(), event); NotificationFieldData data = new NotificationFieldData(); @@ -421,6 +419,7 @@ public class DescriptionServiceImpl implements DescriptionService { this.eventBroker.emit(new DescriptionTouchedEvent(data.getId())); this.annotationEntityTouchedIntegrationEventHandler.handleDescription(data.getId()); + if (data.getStatus().equals(DescriptionStatus.Finalized)) this.sendNotification(data); } return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Description._id), data); } diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplate/DescriptionTemplateServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplate/DescriptionTemplateServiceImpl.java index e0fb45be1..9f448b9e2 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplate/DescriptionTemplateServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/descriptiontemplate/DescriptionTemplateServiceImpl.java @@ -245,8 +245,7 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic data.setRole(user.getRole()); this.entityManager.persist(data); if (!this.userScope.getUserId().equals(user.getUserId())) { - this.sendDescriptionTemplateInvitationEvent(data, NotificationContactType.EMAIL); - this.sendDescriptionTemplateInvitationEvent(data, NotificationContactType.IN_APP); + this.sendDescriptionTemplateInvitationEvent(data); } } updatedCreatedIds.add(data.getUserId()); @@ -256,13 +255,18 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic this.deleterFactory.deleter(UserDescriptionTemplateDeleter.class).delete(toDelete); } - private void sendDescriptionTemplateInvitationEvent(UserDescriptionTemplateEntity userDescriptionTemplate, NotificationContactType type) throws InvalidApplicationException { + private void sendDescriptionTemplateInvitationEvent(UserDescriptionTemplateEntity userDescriptionTemplate) throws InvalidApplicationException { NotifyIntegrationEvent event = new NotifyIntegrationEvent(); - event.setUserId(userScope.getUserIdSafe()); UserEntity user = this.entityManager.find(UserEntity.class, userDescriptionTemplate.getUserId()); + if (user == null){ + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{userDescriptionTemplate.getUserId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale())); + } DescriptionTemplateEntity descriptionTemplate = this.queryFactory.query(DescriptionTemplateQuery.class).isActive(IsActive.Active).ids(userDescriptionTemplate.getDescriptionTemplateId()).first(); - + if (descriptionTemplate == null){ + throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{userDescriptionTemplate.getDescriptionTemplateId(), DescriptionTemplate.class.getSimpleName()}, LocaleContextHolder.getLocale())); + } + event.setUserId(user.getId()); UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); @@ -270,7 +274,6 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue())); NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); - event.setContactTypeHint(type); event.setNotificationType(notificationProperties.getDescriptionTemplateInvitationType()); NotificationFieldData data = new NotificationFieldData(); List fieldInfoList = new ArrayList<>(); 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 39f34de96..d1c24ba50 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 @@ -258,16 +258,15 @@ public class DmpServiceImpl implements DmpService { if (!dmpUser.getUserId().equals(this.userScope.getUserIdSafe())){ UserEntity user = this.queryFactory.query(UserQuery.class).ids(dmpUser.getUserId()).first(); if (user != null){ - this.createDmpNotificationEvent(dmp, user, NotificationContactType.EMAIL); - this.createDmpNotificationEvent(dmp, user, NotificationContactType.IN_APP); + this.createDmpNotificationEvent(dmp, user); } } } } - private void createDmpNotificationEvent(DmpEntity dmp, UserEntity user, NotificationContactType type) throws InvalidApplicationException { + private void createDmpNotificationEvent(DmpEntity dmp, UserEntity user) throws InvalidApplicationException { NotifyIntegrationEvent event = new NotifyIntegrationEvent(); - event.setUserId(this.userScope.getUserId()); + event.setUserId(user.getId()); UserContactInfoQuery query = this.queryFactory.query(UserContactInfoQuery.class).userIds(user.getId()); query.setOrder(new Ordering().addAscending(UserContactInfo._ordinal)); @@ -275,7 +274,6 @@ public class DmpServiceImpl implements DmpService { contactPairs.add(new ContactPair(ContactInfoType.Email, query.first().getValue())); NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); - event.setContactTypeHint(type); this.applyNotificationType(dmp.getStatus(), event); NotificationFieldData data = new NotificationFieldData(); @@ -1186,6 +1184,15 @@ public class DmpServiceImpl implements DmpService { throw new InvalidApplicationException("Dmp does not exist!"); } + List existingUsers = this.queryFactory.query(DmpUserQuery.class) + .dmpIds(dmp.getId()) + .isActives(IsActive.Active) + .collect(); + + if (this.conventionService.isListNullOrEmpty(existingUsers)){ + throw new InvalidApplicationException("Dmp does not have users!"); + } + List usersToAssign = new ArrayList<>(); for (DmpUserPersist user :users) { UUID userId = null; @@ -1200,7 +1207,7 @@ public class DmpServiceImpl implements DmpService { if (userId != null){ user.setUser(userId); usersToAssign.add(user); - if (this.userScope.getUserId() != userId){ + if (this.userScope.getUserId() != userId && !existingUsers.stream().map(x -> x.getUserId()).collect(Collectors.toList()).contains(userId)){ this.sendDmpInvitationExistingUser(user.getUser(), dmp, user.getRole()); } }else if (user.getEmail() != null) { @@ -1215,20 +1222,18 @@ public class DmpServiceImpl implements DmpService { private void sendDmpInvitationExistingUser(UUID userId, DmpEntity dmp, DmpUserRole role) throws InvalidApplicationException { UserEntity recipient = this.queryFactory.query(UserQuery.class).ids(userId).isActive(IsActive.Active).first(); String email = this.queryFactory.query(UserContactInfoQuery.class).userIds(recipient.getId()).first().getValue(); - this.createDmpInvitationExistingUserEvent(recipient, dmp, role, email, NotificationContactType.EMAIL); - this.createDmpInvitationExistingUserEvent(recipient, dmp, role, email, NotificationContactType.IN_APP); + this.createDmpInvitationExistingUserEvent(recipient, dmp, role, email); } - private void createDmpInvitationExistingUserEvent(UserEntity recipient, DmpEntity dmp, DmpUserRole role, String email, NotificationContactType type) throws InvalidApplicationException { + private void createDmpInvitationExistingUserEvent(UserEntity recipient, DmpEntity dmp, DmpUserRole role, String email) throws InvalidApplicationException { NotifyIntegrationEvent event = new NotifyIntegrationEvent(); - event.setUserId(this.userScope.getUserIdSafe()); + event.setUserId(recipient.getId()); List contactPairs = new ArrayList<>(); contactPairs.add(new ContactPair(ContactInfoType.Email, email)); NotificationContactData contactData = new NotificationContactData(contactPairs, null, null); event.setContactHint(jsonHandlingService.toJsonSafe(contactData)); - event.setContactTypeHint(type); event.setNotificationType(notificationProperties.getDmpInvitationExistingUserType()); NotificationFieldData data = new NotificationFieldData(); List fieldInfoList = new ArrayList<>(); @@ -1246,7 +1251,6 @@ public class DmpServiceImpl implements DmpService { String token = this.createActionConfirmation(email, dmp, role); NotifyIntegrationEvent event = new NotifyIntegrationEvent(); - event.setUserId(this.userScope.getUserIdSafe()); List contactPairs = new ArrayList<>(); contactPairs.add(new ContactPair(ContactInfoType.Email, email)); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/externalfetcher/ExternalFetcherServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/externalfetcher/ExternalFetcherServiceImpl.java index 0187dcba9..0590553ff 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/externalfetcher/ExternalFetcherServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/externalfetcher/ExternalFetcherServiceImpl.java @@ -117,11 +117,17 @@ public class ExternalFetcherServiceImpl implements ExternalFetcherService { Map rawData = new HashMap<>(); for (Object object: item.getOptions()) { StaticOptionEntity staticOption = (StaticOptionEntity) object; - if (!this.conventionService.isNullOrEmpty(externalReferenceCriteria.getLike()) && !externalReferenceCriteria.getLike().toUpperCase().contains(staticOption.getValue())) continue; - rawData.put(staticOption.getCode(), staticOption.getValue()); - result.put(staticOption.getCode(), staticOption.getValue()); - result.put(ReferenceEntity.KnownFields.SourceLabel, staticSource.getLabel()); - result.put(ReferenceEntity.KnownFields.Key, staticSource.getKey()); + if (this.conventionService.isNullOrEmpty(externalReferenceCriteria.getLike())){ + rawData.put(staticOption.getCode(), staticOption.getValue()); + result.put(staticOption.getCode(), staticOption.getValue()); + result.put(ReferenceEntity.KnownFields.SourceLabel, staticSource.getLabel()); + result.put(ReferenceEntity.KnownFields.Key, staticSource.getKey()); + }else if (!this.conventionService.isNullOrEmpty(externalReferenceCriteria.getLike()) && externalReferenceCriteria.getLike().toUpperCase().contains(staticOption.getValue().toUpperCase())){ + rawData.put(staticOption.getCode(), staticOption.getValue()); + result.put(staticOption.getCode(), staticOption.getValue()); + result.put(ReferenceEntity.KnownFields.SourceLabel, staticSource.getLabel()); + result.put(ReferenceEntity.KnownFields.Key, staticSource.getKey()); + } } if (!rawData.isEmpty()) externalDataResult.getRawData().add(rawData); diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/metrics/MetricsServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/metrics/MetricsServiceImpl.java index 2e86cefc5..80ee709d9 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/metrics/MetricsServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/metrics/MetricsServiceImpl.java @@ -66,15 +66,15 @@ public class MetricsServiceImpl implements MetricsService { this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP, calculatePublishedDmps(true), MetricLabels.PUBLISHED); this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP, calculateDoiedDmps(true), MetricLabels.DOIED); - this.setGaugeValue(gauges, MetricNames.DMP, calculateDraftDmpsWithGrant(false), MetricLabels.DRAFT); - this.setGaugeValue(gauges, MetricNames.DMP, calculateFinalizedDmpsWithGrant(false), MetricLabels.FINALIZED); - this.setGaugeValue(gauges, MetricNames.DMP, calculatePublishedDmpsWithGrant(false), MetricLabels.PUBLISHED); - this.setGaugeValue(gauges, MetricNames.DMP, calculateDoiedDmpsWithGrant(false), MetricLabels.DOIED); + this.setGaugeValue(gauges, MetricNames.DMP_WITH_GRANT, calculateDraftDmpsWithGrant(false), MetricLabels.DRAFT); + this.setGaugeValue(gauges, MetricNames.DMP_WITH_GRANT, calculateFinalizedDmpsWithGrant(false), MetricLabels.FINALIZED); + this.setGaugeValue(gauges, MetricNames.DMP_WITH_GRANT, calculatePublishedDmpsWithGrant(false), MetricLabels.PUBLISHED); + this.setGaugeValue(gauges, MetricNames.DMP_WITH_GRANT, calculateDoiedDmpsWithGrant(false), MetricLabels.DOIED); - this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP, calculateDraftDmpsWithGrant(true), MetricLabels.DRAFT); - this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP, calculateFinalizedDmpsWithGrant(true), MetricLabels.FINALIZED); - this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP, calculatePublishedDmpsWithGrant(true), MetricLabels.PUBLISHED); - this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP, calculateDoiedDmpsWithGrant(true), MetricLabels.DOIED); + this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP_WITH_GRANT, calculateDraftDmpsWithGrant(true), MetricLabels.DRAFT); + this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP_WITH_GRANT, calculateFinalizedDmpsWithGrant(true), MetricLabels.FINALIZED); + this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP_WITH_GRANT, calculatePublishedDmpsWithGrant(true), MetricLabels.PUBLISHED); + this.setGaugeValue(gauges, MetricNames.NEXUS_PREFIX + MetricNames.DMP_WITH_GRANT, calculateDoiedDmpsWithGrant(true), MetricLabels.DOIED); this.setGaugeValue(gauges, MetricNames.FUNDERS, calculateAllFunders(false), null); this.setGaugeValue(gauges, MetricNames.GRANTS, calculateAllGrants(false), null); @@ -181,6 +181,7 @@ public class MetricsServiceImpl implements MetricsService { dmpQuery.after(_config.getNexusDate()); EntityDoiQuery entityDoiQuery = this.queryFactory.query(EntityDoiQuery.class).types(EntityType.DMP).isActive(IsActive.Active); dmpQuery.entityDoiSubQuery(entityDoiQuery); + dmpQuery.setDistinct(true); return dmpQuery.count(); } diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/user/UserServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/user/UserServiceImpl.java index c9b696cb8..4be24d789 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/user/UserServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/user/UserServiceImpl.java @@ -423,7 +423,6 @@ public class UserServiceImpl implements UserService { String token = this.createMergeAccountConfirmation(model.getEmail()); createMergeNotificationEvent(token, user, model.getEmail(), NotificationContactType.EMAIL); - createMergeNotificationEvent(token, user, model.getEmail(), NotificationContactType.IN_APP); } private void createMergeNotificationEvent(String token, UserEntity user, String email, NotificationContactType type) throws InvalidApplicationException { @@ -453,7 +452,6 @@ public class UserServiceImpl implements UserService { String token = this.createRemoveConfirmation(data.getId()); this.createRemoveCredentialNotificationEvent(token, data.getUserId(), NotificationContactType.EMAIL); - this.createRemoveCredentialNotificationEvent(token, data.getUserId(), NotificationContactType.IN_APP); } private void createRemoveCredentialNotificationEvent(String token, UUID userId, NotificationContactType type) throws InvalidApplicationException { diff --git a/dmp-backend/web/src/main/resources/config/metrics-devel.yml b/dmp-backend/web/src/main/resources/config/metrics-devel.yml index ba506bfab..5e9147e8f 100644 --- a/dmp-backend/web/src/main/resources/config/metrics-devel.yml +++ b/dmp-backend/web/src/main/resources/config/metrics-devel.yml @@ -1,5 +1,9 @@ metrics: task: + enable: true + intervalSeconds: 600 + nexusDate: "2021-01-01T00:00:00.00Z" + usersLoginClient: ${IDP_APIKEY_CLIENT_ID_UUID:} referenceTypes: funderIds: ["538928bb-c7c6-452e-b66d-08e539f5f082"] grantIds: ["5b9c284f-f041-4995-96cc-fad7ad13289c"] diff --git a/dmp-backend/web/src/main/resources/config/metrics.yml b/dmp-backend/web/src/main/resources/config/metrics.yml index ec44ac45f..0f6163011 100644 --- a/dmp-backend/web/src/main/resources/config/metrics.yml +++ b/dmp-backend/web/src/main/resources/config/metrics.yml @@ -1,9 +1,9 @@ metrics: task: - enable: true - intervalSeconds: 600 - nexusDate: "2021-01-01T00:00:00.00Z" - usersLoginClient: ${IDP_APIKEY_CLIENT_ID_UUID:} + enable: false + intervalSeconds: null + nexusDate: null + usersLoginClient: null referenceTypes: funderIds: [] grantIds: [] diff --git a/dmp-frontend/src/app/core/common/enum/app-role.ts b/dmp-frontend/src/app/core/common/enum/app-role.ts index 585f78bcd..1213fb136 100644 --- a/dmp-frontend/src/app/core/common/enum/app-role.ts +++ b/dmp-frontend/src/app/core/common/enum/app-role.ts @@ -4,6 +4,5 @@ export enum AppRole { TenantAdmin = "TenantAdmin", TenantUser = "TenantUser", TenantManager = "TenantManager", - TenantDescriptionTemplateEditor = "TenantDescriptionTemplateEditor", - + TenantDescriptionTemplateEditor = "TenantDescriptionTemplateEditor" } diff --git a/dmp-frontend/src/app/library/guided-tour/guided-tour.component.scss b/dmp-frontend/src/app/library/guided-tour/guided-tour.component.scss index 42b9098f9..19fe28028 100644 --- a/dmp-frontend/src/app/library/guided-tour/guided-tour.component.scss +++ b/dmp-frontend/src/app/library/guided-tour/guided-tour.component.scss @@ -107,7 +107,7 @@ ngx-guided-tour { &.tour-top-right { .tour-arrow::before { transform: translateX(-100%); - left: calc(100% - 5px); + left: calc(100% - 15px); } } diff --git a/dmp-frontend/src/app/ui/admin/description-template/listing/filters/description-template-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/description-template/listing/filters/description-template-listing-filters.component.html index f8931ff0d..a81fe8422 100644 --- a/dmp-frontend/src/app/ui/admin/description-template/listing/filters/description-template-listing-filters.component.html +++ b/dmp-frontend/src/app/ui/admin/description-template/listing/filters/description-template-listing-filters.component.html @@ -7,32 +7,47 @@ -
-
-
+
+
+

{{'DESCRIPTION-TEMPLATE-LISTING.FILTER.TITLE' | translate}}

+
+
+
- - {{'DESCRIPTION-TEMPLATE-LISTING.FILTER.IS-ACTIVE' | translate}} - - -
- {{'DESCRIPTION-TEMPLATE-LISTING.FILTER.STATUS' | translate}} +
+
+
+ + {{'DESCRIPTION-TEMPLATE-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
+
+ +
+
+ + {{'DESCRIPTION-TEMPLATE-LISTING.FILTER.STATUS' | translate}} {{enumUtils.toDescriptionTemplateTypeStatusString(descriptionTemplateStatus)}} - +
+
-
- -
+
+
diff --git a/dmp-frontend/src/app/ui/admin/description-template/listing/filters/description-template-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/description-template/listing/filters/description-template-listing-filters.component.scss index ce98b0410..ac875ec51 100644 --- a/dmp-frontend/src/app/ui/admin/description-template/listing/filters/description-template-listing-filters.component.scss +++ b/dmp-frontend/src/app/ui/admin/description-template/listing/filters/description-template-listing-filters.component.scss @@ -22,4 +22,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/app/ui/admin/description-types/listing/filters/description-template-type-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/description-types/listing/filters/description-template-type-listing-filters.component.html index 3d8fbcac9..85ce31d0e 100644 --- a/dmp-frontend/src/app/ui/admin/description-types/listing/filters/description-template-type-listing-filters.component.html +++ b/dmp-frontend/src/app/ui/admin/description-types/listing/filters/description-template-type-listing-filters.component.html @@ -7,32 +7,47 @@ -
-
-
+
+
+

{{'DESCRIPTION-TEMPLATE-TYPE-LISTING.FILTER.TITLE' | translate}}

+
+
+
- - {{'DESCRIPTION-TEMPLATE-TYPE-LISTING.FILTER.IS-ACTIVE' | translate}} - +
+
+
+ + {{'DESCRIPTION-TEMPLATE-TYPE-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
+
-
- {{'DESCRIPTION-TEMPLATE-TYPE-LISTING.FILTER.STATUS' | translate}} +
+
+ + {{'DESCRIPTION-TEMPLATE-TYPE-LISTING.FILTER.STATUS' | translate}} {{enumUtils.toDescriptionTemplateTypeStatusString(descriptionTemplateTypeStatus)}} - +
+
-
- -
+
+
diff --git a/dmp-frontend/src/app/ui/admin/description-types/listing/filters/description-template-type-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/description-types/listing/filters/description-template-type-listing-filters.component.scss index 999f5a7c6..56598bd16 100644 --- a/dmp-frontend/src/app/ui/admin/description-types/listing/filters/description-template-type-listing-filters.component.scss +++ b/dmp-frontend/src/app/ui/admin/description-types/listing/filters/description-template-type-listing-filters.component.scss @@ -22,4 +22,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/app/ui/admin/dmp-blueprint/listing/filters/dmp-blueprint-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/dmp-blueprint/listing/filters/dmp-blueprint-listing-filters.component.html index 0b01f7bc8..fc34c9d97 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-blueprint/listing/filters/dmp-blueprint-listing-filters.component.html +++ b/dmp-frontend/src/app/ui/admin/dmp-blueprint/listing/filters/dmp-blueprint-listing-filters.component.html @@ -39,7 +39,7 @@
-
+
+
-
-
- - {{'LOCK-LISTING.FILTER.USERS' | translate}} - - - -
-
- - {{'LOCK-LISTING.FILTER.TARGET-TYPE' | translate}} - - {{enumUtils.toLockTargetTypeString(targetType)}} - - - -
+
+
+ + {{'LOCK-LISTING.FILTER.USERS' | translate}} + + +
+
-
- -
+
+
diff --git a/dmp-frontend/src/app/ui/admin/entity-locks/filters/lock-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/entity-locks/filters/lock-listing-filters.component.scss index ea00a215c..484fc07ba 100644 --- a/dmp-frontend/src/app/ui/admin/entity-locks/filters/lock-listing-filters.component.scss +++ b/dmp-frontend/src/app/ui/admin/entity-locks/filters/lock-listing-filters.component.scss @@ -17,5 +17,3 @@ // height: 1.2em; // } } - - diff --git a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html index 9c490b8ec..13dd39948 100644 --- a/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/language/editor/language-editor.component.html @@ -30,7 +30,7 @@
-
+
{{'LANGUAGE-EDITOR.FIELDS.CODE' | translate}} @@ -38,7 +38,7 @@ {{'GENERAL.VALIDATION.REQUIRED' | translate}}
-
+
{{'LANGUAGE-EDITOR.FIELDS.CODE' | translate}} diff --git a/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.html index 0a46845d4..0bc061945 100644 --- a/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.html +++ b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.html @@ -7,24 +7,36 @@ -
-
-
+
+
+

{{'LANGUAGE-LISTING.FILTER.TITLE' | translate}}

+
+
+
- - {{'LANGUAGE-LISTING.FILTER.IS-ACTIVE' | translate}} - +
+
+
+ + {{'LANGUAGE-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
+
-
- -
+
+
diff --git a/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.scss index ea00a215c..5a1a293b5 100644 --- a/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.scss +++ b/dmp-frontend/src/app/ui/admin/language/listing/filters/language-listing-filters.component.scss @@ -18,4 +18,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/app/ui/admin/prefilling-source/editor/prefilling-source-editor.component.html b/dmp-frontend/src/app/ui/admin/prefilling-source/editor/prefilling-source-editor.component.html index fdadd6bd4..4adb789db 100644 --- a/dmp-frontend/src/app/ui/admin/prefilling-source/editor/prefilling-source-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/prefilling-source/editor/prefilling-source-editor.component.html @@ -25,7 +25,7 @@
- + {{'PREFILLING-SOURCE-EDITOR.NEW' | translate}} @@ -42,7 +42,7 @@
- + {{'PREFILLING-SOURCE-EDITOR.FIELDS.FIXED-VALUE-FIELDS' | translate}} @@ -82,7 +82,7 @@
- + {{'PREFILLING-SOURCE-EDITOR.FIELDS.FIELDS' | translate}} @@ -122,7 +122,7 @@ - + {{'PREFILLING-SOURCE-EDITOR.FIELDS.SOURCE-CONFIGURATION' | translate}} @@ -138,7 +138,7 @@ - + {{'PREFILLING-SOURCE-EDITOR.FIELDS.GET-SOURCE-CONFIGURATION' | translate}} diff --git a/dmp-frontend/src/app/ui/admin/prefilling-source/listing/filters/prefilling-source-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/prefilling-source/listing/filters/prefilling-source-listing-filters.component.html index 0d6059198..69446ed53 100644 --- a/dmp-frontend/src/app/ui/admin/prefilling-source/listing/filters/prefilling-source-listing-filters.component.html +++ b/dmp-frontend/src/app/ui/admin/prefilling-source/listing/filters/prefilling-source-listing-filters.component.html @@ -7,24 +7,36 @@ -
-
-
+
+
+

{{'PREFILLING-SOURCE-LISTING.FILTER.TITLE' | translate}}

+
+
+
- - {{'PREFILLING-SOURCE-LISTING.FILTER.IS-ACTIVE' | translate}} - +
+
+
+ + {{'PREFILLING-SOURCE-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
+
-
- -
+
+
diff --git a/dmp-frontend/src/app/ui/admin/prefilling-source/listing/filters/prefilling-source-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/prefilling-source/listing/filters/prefilling-source-listing-filters.component.scss index c31bf588d..bc24a87e9 100644 --- a/dmp-frontend/src/app/ui/admin/prefilling-source/listing/filters/prefilling-source-listing-filters.component.scss +++ b/dmp-frontend/src/app/ui/admin/prefilling-source/listing/filters/prefilling-source-listing-filters.component.scss @@ -22,4 +22,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.html b/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.html index aaca41f97..dd0055b0a 100644 --- a/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/reference-type/editor/reference-type-editor.component.html @@ -2,7 +2,7 @@
-
+

{{'REFERENCE-TYPE-EDITOR.NEW' | translate}}

diff --git a/dmp-frontend/src/app/ui/admin/reference-type/listing/filters/reference-type-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/reference-type/listing/filters/reference-type-listing-filters.component.html index ff9454bac..9cafc882f 100644 --- a/dmp-frontend/src/app/ui/admin/reference-type/listing/filters/reference-type-listing-filters.component.html +++ b/dmp-frontend/src/app/ui/admin/reference-type/listing/filters/reference-type-listing-filters.component.html @@ -7,24 +7,36 @@ -
-
-
+
+
+

{{'REFERENCE-TYPE-LISTING.FILTER.TITLE' | translate}}

+
+
+
- - {{'REFERENCE-TYPE-LISTING.FILTER.IS-ACTIVE' | translate}} - +
+
+
+ + {{'REFERENCE-TYPE-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
+
-
- -
+
+
diff --git a/dmp-frontend/src/app/ui/admin/reference-type/listing/filters/reference-type-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/reference-type/listing/filters/reference-type-listing-filters.component.scss index 999f5a7c6..56598bd16 100644 --- a/dmp-frontend/src/app/ui/admin/reference-type/listing/filters/reference-type-listing-filters.component.scss +++ b/dmp-frontend/src/app/ui/admin/reference-type/listing/filters/reference-type-listing-filters.component.scss @@ -22,4 +22,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html index 7622b915c..dc36864f5 100644 --- a/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/reference/editor/reference-editor.component.html @@ -2,7 +2,7 @@
-
+

{{'REFERENCE-EDITOR.NEW' | translate}}

diff --git a/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.html index 12a0dd0da..ce6b28177 100644 --- a/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.html +++ b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.html @@ -7,39 +7,58 @@ -
-
-
+
+
+

{{'REFERENCE-LISTING.FILTER.TITLE' | translate}}

+
+ +
+
- - {{'REFERENCE-LISTING.FILTER.IS-ACTIVE' | translate}} - +
+
+
+ + {{'REFERENCE-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
+
-
- {{'REFERENCE-LISTING.FILTER.TYPE' | translate}} +
+
+ + {{'REFERENCE-LISTING.FILTER.TYPE' | translate}} - +
+
-
- {{'REFERENCE-LISTING.FILTER.SOURCE-TYPE' | translate}} +
+
+ + {{'REFERENCE-LISTING.FILTER.SOURCE-TYPE' | translate}} {{enumUtils.toReferenceSourceTypeString(referenceSourceType)}} - +
+
-
- -
+
+
diff --git a/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.scss index ea00a215c..5a1a293b5 100644 --- a/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.scss +++ b/dmp-frontend/src/app/ui/admin/reference/listing/filters/reference-listing-filters.component.scss @@ -18,4 +18,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html index 5baacd3e2..c3fc0a1d9 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/tenant/editor/tenant-editor.component.html @@ -2,7 +2,7 @@
-
+

{{'TENANT-EDITOR.NEW' | translate}}

diff --git a/dmp-frontend/src/app/ui/admin/tenant/listing/filters/tenant-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/tenant/listing/filters/tenant-listing-filters.component.html index 248db4c57..17884d24f 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/listing/filters/tenant-listing-filters.component.html +++ b/dmp-frontend/src/app/ui/admin/tenant/listing/filters/tenant-listing-filters.component.html @@ -7,24 +7,36 @@ -
-
-
+
+
+

{{'TENANT-LISTING.FILTER.TITLE' | translate}}

+
+
+
- - {{'TENANT-LISTING.FILTER.IS-ACTIVE' | translate}} - +
+
+
+ + {{'TENANT-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
+
-
- -
+
+
diff --git a/dmp-frontend/src/app/ui/admin/tenant/listing/filters/tenant-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/tenant/listing/filters/tenant-listing-filters.component.scss index 999f5a7c6..56598bd16 100644 --- a/dmp-frontend/src/app/ui/admin/tenant/listing/filters/tenant-listing-filters.component.scss +++ b/dmp-frontend/src/app/ui/admin/tenant/listing/filters/tenant-listing-filters.component.scss @@ -22,4 +22,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/app/ui/admin/user/listing/filters/user-listing-filters.component.html b/dmp-frontend/src/app/ui/admin/user/listing/filters/user-listing-filters.component.html index 0e15fb761..5cca69742 100644 --- a/dmp-frontend/src/app/ui/admin/user/listing/filters/user-listing-filters.component.html +++ b/dmp-frontend/src/app/ui/admin/user/listing/filters/user-listing-filters.component.html @@ -7,32 +7,47 @@ -
-
-
+
+
+

{{'USER-LISTING.FILTER.TITLE' | translate}}

+
+
+
- - {{'USER-LISTING.FILTER.IS-ACTIVE' | translate}} - +
+
+
+ + {{'USER-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
+
-
- {{'USER-LISTING.FILTER.ROLES' | translate}} +
+
+ + {{'USER-LISTING.FILTER.ROLES' | translate}} {{enumUtils.toAppRoleString(appRole)}} - +
+
-
- -
+
+
diff --git a/dmp-frontend/src/app/ui/admin/user/listing/filters/user-listing-filters.component.scss b/dmp-frontend/src/app/ui/admin/user/listing/filters/user-listing-filters.component.scss index b89c1afc8..48fddc087 100644 --- a/dmp-frontend/src/app/ui/admin/user/listing/filters/user-listing-filters.component.scss +++ b/dmp-frontend/src/app/ui/admin/user/listing/filters/user-listing-filters.component.scss @@ -22,4 +22,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.html b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.html index 7e4486d17..10c4b10b9 100644 --- a/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.html @@ -1,32 +1,39 @@  -
-
- -
- - {{enumUtils.toAppRoleString(role)}} - +
+
+
+
+
+ + {{enumUtils.toAppRoleString(role)}} + +
+
- -
-
- - - - {{enumUtils.toAppRoleString(role)}} - - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} - +
+ + + + {{enumUtils.toAppRoleString(role)}} + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+ +
+ +
+
+ +
+
- - -
diff --git a/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.scss b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.scss index 11d3bde57..5d9c920fa 100644 --- a/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.scss +++ b/dmp-frontend/src/app/ui/admin/user/listing/role-editor/user-role-editor.component.scss @@ -85,6 +85,24 @@ padding-right: 10px; } + .tenant-admin { + // display: flex; + // justify-content: center; + // align-items: center; + min-width: 77px; + min-height: 28px; + color: #ffa631; + background: #ffe6c6 0% 0% no-repeat padding-box; + border-radius: 44px; + letter-spacing: 0.11px; + font-weight: 400; + opacity: 1; + margin-top: 0.5em; + margin-bottom: 0.5em; + padding-left: 10px; + padding-right: 10px; + } + .tenant-description-template-editor { // display: flex; // justify-content: center; diff --git a/dmp-frontend/src/app/ui/dashboard/dashboard.component.html b/dmp-frontend/src/app/ui/dashboard/dashboard.component.html index be5c74704..50d088c26 100644 --- a/dmp-frontend/src/app/ui/dashboard/dashboard.component.html +++ b/dmp-frontend/src/app/ui/dashboard/dashboard.component.html @@ -1,9 +1,8 @@ -
+
-
@@ -79,7 +78,6 @@
-
@@ -108,7 +106,6 @@
-
@@ -147,13 +144,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
clear

{{'DASHBOARD.TITLE' | translate}}

@@ -163,49 +160,69 @@
-
-
-
-
{{'DASHBOARD.PUBLIC-USAGE' | translate}}
-
0
- {{'DASHBOARD.PUBLIC-DMPS' | translate}} -
0
- {{'DASHBOARD.PUBLIC-DATASETS' | translate}} -
0
+ +
+
+
+
+
{{'DASHBOARD.PUBLIC-USAGE' | translate}}
+
+ + + + -
-
{{'DASHBOARD.PUBLIC-USAGE' | translate}}
-
- {{dashboardStatistics?.dmpCount}}
+
+ +
+
+
{{'DASHBOARD.PUBLIC-USAGE' | translate}}
+
+
+
{{dashboardStatistics?.dmpCount}}
{{'DASHBOARD.PUBLIC-DMPS' | translate}} -
- {{dashboardStatistics?.descriptionCount}}
+
+ +
+
{{dashboardStatistics?.descriptionCount}}
{{'DASHBOARD.PUBLIC-DESCRIPTIONS' | translate}} -
- {{grantCount}}
+
+ +
+
{{grantCount}}
{{'DASHBOARD.GRANTS' | translate}} -
- {{organizationCount}}
+
+ +
diff --git a/dmp-frontend/src/app/ui/dashboard/dashboard.component.scss b/dmp-frontend/src/app/ui/dashboard/dashboard.component.scss index 88c19f0e9..949e0b96f 100644 --- a/dmp-frontend/src/app/ui/dashboard/dashboard.component.scss +++ b/dmp-frontend/src/app/ui/dashboard/dashboard.component.scss @@ -374,14 +374,6 @@ input[type="text"] { padding: 0rem 7em 0rem 3rem; } -.non-auth-main-container { - padding-left: 0; -} - -.non-auth-card { - margin-left: 3rem; -} - .app-info { font-size: 1rem; padding: 1rem 2rem; diff --git a/dmp-frontend/src/app/ui/description/editor/description-base-fields-editor/description-base-fields-editor.component.ts b/dmp-frontend/src/app/ui/description/editor/description-base-fields-editor/description-base-fields-editor.component.ts index c5a76d3b0..44b8ba390 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-base-fields-editor/description-base-fields-editor.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-base-fields-editor/description-base-fields-editor.component.ts @@ -1,19 +1,16 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { UntypedFormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; +import { DescriptionStatus } from '@app/core/common/enum/description-status'; +import { DescriptionTemplateVersionStatus } from '@app/core/common/enum/description-template-version-status'; import { IsActive } from '@app/core/common/enum/is-active.enum'; import { DescriptionTemplate } from '@app/core/model/description-template/description-template'; import { Description } from '@app/core/model/description/description'; -import { DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint'; -import { Dmp, DmpDescriptionTemplate } from '@app/core/model/dmp/dmp'; -import { DescriptionTemplateService } from '@app/core/services/description-template/description-template.service'; +import { DmpDescriptionTemplate } from '@app/core/model/dmp/dmp'; import { DescriptionService } from '@app/core/services/description/description.service'; -import { DmpBlueprintService } from '@app/core/services/dmp/dmp-blueprint.service'; import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; import { DeprecatedDescriptionTemplateDialog } from './dialog-description-template/deprecated-description-template-dialog.component'; -import { DescriptionTemplateVersionStatus } from '@app/core/common/enum/description-template-version-status'; -import { DescriptionStatus } from '@app/core/common/enum/description-status'; @Component({ selector: 'app-description-base-fields-editor-component', @@ -47,15 +44,17 @@ export class DescriptionBaseFieldsEditorComponent extends BaseComponent { const currentVersionsOfDescriptionTemplates = dmpDescriptionTemplates.map(x => x.currentDescriptionTemplate); this.availableDescriptionTemplates.push(...currentVersionsOfDescriptionTemplates); - const isPreviousVersion: boolean = this.description.descriptionTemplate.versionStatus === DescriptionTemplateVersionStatus.Previous; - if (isPreviousVersion === true) { - if (this.description.status === DescriptionStatus.Draft) { - this.openDeprecatedDescriptionTemplateDialog(); + if (this.description?.descriptionTemplate != null) { + const isPreviousVersion: boolean = this.description.descriptionTemplate.versionStatus === DescriptionTemplateVersionStatus.Previous; + if (isPreviousVersion === true) { + if (this.description.status === DescriptionStatus.Draft) { + this.openDeprecatedDescriptionTemplateDialog(); + } else { + this.availableDescriptionTemplates.push(this.description.descriptionTemplate); + } } else { this.availableDescriptionTemplates.push(this.description.descriptionTemplate); } - } else { - this.availableDescriptionTemplates.push(this.description.descriptionTemplate); } } @@ -67,19 +66,19 @@ export class DescriptionBaseFieldsEditorComponent extends BaseComponent { }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe( result => { - if(result) { + if (result) { this.descriptionService.updateDescriptionTemplate({ id: this.description.id, hash: this.description.hash }) - .subscribe( - result => { - this.refresh.emit(result); - }, - error => console.error(error)); + .subscribe( + result => { + this.refresh.emit(result); + }, + error => console.error(error)); } else { this.availableDescriptionTemplates.push(this.description.descriptionTemplate); } - }); + }); } } 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 c903e861c..66a6bb93c 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 @@ -111,13 +111,13 @@ chevron_left
{{'DMP-EDITOR.ACTIONS.PREVIOUS-STEP' | translate}}
-
+
{{'DMP-EDITOR.ACTIONS.NEXT-STEP' | translate}}
chevron_right
- +
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 078d541d8..5348b035f 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 @@ -88,7 +88,7 @@ export class DmpEditorComponent extends BaseEditor implemen filterFn: (searchQuery: string, data?: any) => this.dmpBlueprintService.query(this.dmpBlueprintService.buildAutocompleteLookup(searchQuery, null, null, [DmpBlueprintStatus.Finalized])).pipe(map(x => x.items)), getSelectedItem: (selectedItem: any) => this.dmpBlueprintService.query(this.dmpBlueprintService.buildAutocompleteLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])), displayFn: (item: DmpBlueprint) => item.label, - subtitleFn: (item: DmpBlueprint) => this.language.instant('DMP-EDITOR.FIELDS.DMP-BLUEPRINT-VERSION') + ' '+ item.version, + subtitleFn: (item: DmpBlueprint) => this.language.instant('DMP-EDITOR.FIELDS.DMP-BLUEPRINT-VERSION') + ' ' + item.version, titleFn: (item: DmpBlueprint) => item.label, valueAssign: (item: DmpBlueprint) => item.id, }; @@ -174,14 +174,14 @@ export class DmpEditorComponent extends BaseEditor implemen try { this.editorModel = data ? new DmpEditorModel().fromModel(data) : new DmpEditorModel(); if (data) { - if(data.descriptions){ + if (data.descriptions) { if (data.status == DmpStatus.Finalized) { data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatus.Finalized); } else { data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status !== DescriptionStatus.Canceled); } } - if(data.dmpDescriptionTemplates){ + if (data.dmpDescriptionTemplates) { data.dmpDescriptionTemplates = data.dmpDescriptionTemplates.filter(x => x.isActive === IsActive.Active); } @@ -304,6 +304,11 @@ export class DmpEditorComponent extends BaseEditor implemen // Steps // // + + get maxSteps(): number { + return this.item?.blueprint?.definition?.sections?.length ?? 0; + } + changeStep(index: number) { this.step = index; this.resetScroll(); @@ -389,7 +394,8 @@ export class DmpEditorComponent extends BaseEditor implemen DmpEditorModel.reApplyPropertiesValidators( { formGroup: this.formGroup, - validationErrorModel: this.editorModel.validationErrorModel + validationErrorModel: this.editorModel.validationErrorModel, + blueprint: this.item.blueprint } ); this.formGroup.get('properties').get('contacts').markAsDirty(); @@ -404,7 +410,8 @@ export class DmpEditorComponent extends BaseEditor implemen DmpEditorModel.reApplyPropertiesValidators( { formGroup: this.formGroup, - validationErrorModel: this.editorModel.validationErrorModel + validationErrorModel: this.editorModel.validationErrorModel, + blueprint: this.item.blueprint } ); this.formGroup.get('properties').get('contacts').markAsDirty(); @@ -455,32 +462,32 @@ export class DmpEditorComponent extends BaseEditor implemen }); } - canAddDescription(section: DmpBlueprintDefinitionSection ): boolean{ - if(section.hasTemplates){ - if (section.descriptionTemplates?.length > 0){ + canAddDescription(section: DmpBlueprintDefinitionSection): boolean { + if (section.hasTemplates) { + if (section.descriptionTemplates?.length > 0) { const descriptions = this.descriptionsInSection(section.id) - if (this.item.dmpDescriptionTemplates.filter(x => x.sectionId == section.id).length > descriptions.map(x => x.dmpDescriptionTemplate).length){ + if (this.item.dmpDescriptionTemplates.filter(x => x.sectionId == section.id).length > descriptions.map(x => x.dmpDescriptionTemplate).length) { return true; } - let multiplicityValidResults :boolean[] = []; + let multiplicityValidResults: boolean[] = []; section.descriptionTemplates.forEach(sectionDescriptionTemplate => { - if (sectionDescriptionTemplate.maxMultiplicity != null){ + if (sectionDescriptionTemplate.maxMultiplicity != null) { const count = descriptions.filter(x => x.dmpDescriptionTemplate.descriptionTemplateGroupId == sectionDescriptionTemplate.descriptionTemplateGroupId).length || 0; if (count >= sectionDescriptionTemplate.maxMultiplicity) multiplicityValidResults.push(false); else multiplicityValidResults.push(true); - }else{ + } else { multiplicityValidResults.push(true); } }) - if(multiplicityValidResults.includes(true)) return true + if (multiplicityValidResults.includes(true)) return true else return false; - }else{ + } else { return true; } - }else{ + } else { return false; } } @@ -504,10 +511,10 @@ export class DmpEditorComponent extends BaseEditor implemen dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(groupId => { if (groupId) { let data = this.formGroup.get('descriptionTemplates').get(sectionId.toString()).value as Guid[]; - if (data){ + if (data) { data.push(groupId); this.formGroup.get('descriptionTemplates').get(sectionId.toString()).patchValue(data); - } else{ + } else { this.formGroup.get('descriptionTemplates').get(sectionId.toString()).patchValue([groupId]); } } 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 86c991402..9559ca651 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,11 +1,12 @@ -import { FormArray, FormControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; +import { FormArray, FormControl, UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms"; import { DmpAccessType } from "@app/core/common/enum/dmp-access-type"; +import { DmpBlueprintFieldCategory } from "@app/core/common/enum/dmp-blueprint-field-category"; import { DmpContactType } from "@app/core/common/enum/dmp-contact-type"; 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 } from "@app/core/model/dmp-blueprint/dmp-blueprint"; +import { DmpBlueprint, FieldInSection } 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"; @@ -103,8 +104,8 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { const descriptionTemplatesFormGroup = this.formBuilder.group({}); (this.descriptionTemplates ?? []).filter(x => x?.sectionId).map(x => x.sectionId).map( - (item, index) => descriptionTemplatesFormGroup.addControl(item.toString(), - new FormControl(this.descriptionTemplates?.filter(x => x.sectionId === item)?.filter(x => x.descriptionTemplateGroupId).map(x => x.descriptionTemplateGroupId) || [], context.getValidation('descriptionTemplates').validators)) + (item, index) => descriptionTemplatesFormGroup.addControl(item.toString(), + new FormControl(this.descriptionTemplates?.filter(x => x.sectionId === item)?.filter(x => x.descriptionTemplateGroupId).map(x => x.descriptionTemplateGroupId) || [], context.getValidation('descriptionTemplates').validators)) ); // // buildForm({ // // rootPath: `descriptionTemplates[${index}].` @@ -120,13 +121,16 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); - baseValidationArray.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] }); - baseValidationArray.push({ key: 'properties', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'properties')] }); + baseValidationArray.push({ key: 'status', validators: [BackendErrorValidator(this.validationErrorModel, 'status')] }); + baseValidationArray.push({ key: 'properties', validators: [BackendErrorValidator(this.validationErrorModel, 'properties')] }); baseValidationArray.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] }); - baseValidationArray.push({ key: 'language', validators: [BackendErrorValidator(this.validationErrorModel, 'language')] }); - baseValidationArray.push({ key: 'blueprint', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'blueprint')] }); - baseValidationArray.push({ key: 'accessType', validators: [BackendErrorValidator(this.validationErrorModel, 'accessType')] }); + baseValidationArray.push({ key: 'language', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'language')] }); + baseValidationArray.push({ key: 'blueprint', validators: [BackendErrorValidator(this.validationErrorModel, 'blueprint')] }); + baseValidationArray.push({ key: 'accessType', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'accessType')] }); baseValidationArray.push({ key: 'descriptionTemplates', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'descriptionTemplates')] }); + + baseValidationArray.push({ key: 'dmpDescriptionValidator', validators: [] }); + baseValidationArray.push({ key: 'users', validators: [BackendErrorValidator(this.validationErrorModel, `users`)] }); baseValidationArray.push({ key: 'hash', validators: [] }); @@ -143,6 +147,7 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { static reApplyPropertiesValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, + blueprint: DmpBlueprint }): void { const { formGroup, validationErrorModel } = params; @@ -150,20 +155,36 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist { DmpPropertiesEditorModel.reapplyValidators({ formGroup: control as UntypedFormGroup, rootPath: `properties.`, - validationErrorModel: validationErrorModel + validationErrorModel: validationErrorModel, + blueprint: params.blueprint }); + } + + static reApplyDescriptionTemplateValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + }): void { + + const { formGroup, validationErrorModel } = params; const descriptionTemplates = formGroup?.get('descriptionTemplates') as UntypedFormGroup; const keys = Object.keys(descriptionTemplates.value as Object); keys.forEach((key) => { const control = descriptionTemplates?.get(key); - DmpBlueprintValueEditorModel.reapplyValidators({ + DmpDescriptionTemplateEditorModel.reapplyValidators({ formGroup: control as UntypedFormGroup, rootPath: `descriptionTemplates[${key}].`, validationErrorModel: validationErrorModel }) }); + } + static reApplyUsersValidators(params: { + formGroup: UntypedFormGroup, + validationErrorModel: ValidationErrorModel, + }): void { + + const { formGroup, validationErrorModel } = params; (formGroup.get('users') as FormArray).controls?.forEach( (control, index) => DmpUserEditorModel.reapplyValidators({ formGroup: control as UntypedFormGroup, @@ -186,14 +207,16 @@ export class DmpPropertiesEditorModel implements DmpPropertiesPersist { fromModel(item: DmpProperties, dmpReferences: DmpReference[], dmpBlueprint: DmpBlueprint): DmpPropertiesEditorModel { - + dmpBlueprint.definition.sections.forEach(section => { section.fields?.forEach(field => { - this.dmpBlueprintValues.set(field.id, new DmpBlueprintValueEditorModel(this.validationErrorModel).fromModel( - { - fieldId: field.id, - fieldValue: item?.dmpBlueprintValues?.find(x => x.fieldId == field.id)?.fieldValue, - }, dmpReferences)); + if (field.category !== DmpBlueprintFieldCategory.System) { + this.dmpBlueprintValues.set(field.id, new DmpBlueprintValueEditorModel(this.validationErrorModel).fromModel( + { + fieldId: field.id, + fieldValue: item?.dmpBlueprintValues?.find(x => x.fieldId == field.id)?.fieldValue, + }, dmpReferences, field)); + } }); }); if (item?.contacts) { item.contacts.map(x => this.contacts.push(new DmpContactEditorModel(this.validationErrorModel).fromModel(x))); } @@ -228,8 +251,8 @@ export class DmpPropertiesEditorModel implements DmpPropertiesPersist { const dmpBlueprintValuesFormGroup = this.formBuilder.group({}); this.dmpBlueprintValues.forEach((value, key) => dmpBlueprintValuesFormGroup.addControl(key.toString(), value.buildForm({ - rootPath: `${rootPath}dmpBlueprintValues[${key}].` - })), context.getValidation('dmpBlueprintValues') + rootPath: `${rootPath}dmpBlueprintValues[${key}].` + })), context.getValidation('dmpBlueprintValues') ) formGroup.addControl('dmpBlueprintValues', dmpBlueprintValuesFormGroup); @@ -254,7 +277,8 @@ export class DmpPropertiesEditorModel implements DmpPropertiesPersist { static reapplyValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, - rootPath: string + rootPath: string, + blueprint: DmpBlueprint }): void { const { formGroup, rootPath, validationErrorModel } = params; @@ -266,9 +290,10 @@ export class DmpPropertiesEditorModel implements DmpPropertiesPersist { DmpBlueprintValueEditorModel.reapplyValidators({ formGroup: control as UntypedFormGroup, rootPath: `${rootPath}dmpBlueprintValues[${key}].`, - validationErrorModel: validationErrorModel + validationErrorModel: validationErrorModel, + isRequired: params.blueprint.definition.sections.flatMap(x => x.fields).find(x => x.id.toString() == key).required }) - }); + }); (formGroup.get('contacts') as FormArray).controls?.forEach( (control, index) => DmpContactEditorModel.reapplyValidators({ @@ -284,6 +309,8 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { fieldId: Guid; fieldValue: string; references: DmpReferencePersist[] = []; + isRequired: boolean = false; + category: DmpBlueprintFieldCategory; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -291,7 +318,7 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { public validationErrorModel: ValidationErrorModel = new ValidationErrorModel() ) { } - fromModel(item: DmpBlueprintValue, dmpReferences: DmpReference[]): DmpBlueprintValueEditorModel { + 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 => { @@ -311,6 +338,10 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { } }); + this.isRequired = field.required; + if (this.isRequired) console.log(field); + this.category = field.category; + return this; } @@ -323,28 +354,39 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { if (context == null) { context = DmpBlueprintValueEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, - rootPath + rootPath, + isRequired: this.isRequired }); } - return this.formBuilder.group({ + const formGroup = this.formBuilder.group({ fieldId: [{ value: this.fieldId, disabled: disabled }, context.getValidation('fieldId').validators], - fieldValue: [{ value: this.fieldValue, disabled: disabled }, context.getValidation('fieldValue').validators], - references: [{ value: this.references?.map(x => x.reference), disabled: disabled }, context.getValidation('references').validators], }); + switch (this.category) { + case DmpBlueprintFieldCategory.ReferenceType: + formGroup.addControl('references', new FormControl({ value: this.references?.map(x => x.reference), disabled: disabled }, context.getValidation('references').validators)); + break; + case DmpBlueprintFieldCategory.System: + case DmpBlueprintFieldCategory.Extra: + formGroup.addControl('fieldValue', new FormControl({ value: this.fieldValue, disabled: disabled }, context.getValidation('fieldValue').validators)); + break; + } + + return formGroup; } static createValidationContext(params: { rootPath?: string, - validationErrorModel: ValidationErrorModel + validationErrorModel: ValidationErrorModel, + isRequired: boolean, }): ValidationContext { const { rootPath = '', validationErrorModel } = params; const baseContext: ValidationContext = new ValidationContext(); const baseValidationArray: Validation[] = new Array(); baseValidationArray.push({ key: 'fieldId', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}fieldId`)] }); - baseValidationArray.push({ key: 'fieldValue', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}fieldValue`)] }); - baseValidationArray.push({ key: 'references', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] }); + 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`)] }); baseContext.validation = baseValidationArray; return baseContext; @@ -353,13 +395,15 @@ export class DmpBlueprintValueEditorModel implements DmpBlueprintValuePersist { static reapplyValidators(params: { formGroup: UntypedFormGroup, validationErrorModel: ValidationErrorModel, - rootPath: string + rootPath: string, + isRequired: boolean }): void { const { formGroup, rootPath, validationErrorModel } = params; const context = DmpBlueprintValueEditorModel.createValidationContext({ rootPath, - validationErrorModel + validationErrorModel, + isRequired: params.isRequired }); ['fieldId', 'fieldValue', 'references'].forEach(keyField => { @@ -375,7 +419,7 @@ export class DmpContactEditorModel implements DmpContactPersist { firstName: string; lastName: string; email: string; - contactType: DmpContactType= DmpContactType.Internal; + contactType: DmpContactType = DmpContactType.Internal; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -384,11 +428,11 @@ export class DmpContactEditorModel implements DmpContactPersist { ) { } fromModel(item: DmpContact): DmpContactEditorModel { - if(item?.user?.id) this.userId = item.user.id; + if (item?.user?.id) this.userId = item.user.id; this.firstName = item.firstName; this.lastName = item.lastName; - this.email = item.email; - this.contactType = (item == null || this.userId != null) ? DmpContactType.Internal : DmpContactType.External; + this.email = item.email; + this.contactType = (item == null || this.userId != null) ? DmpContactType.Internal : DmpContactType.External; return this; } @@ -457,7 +501,7 @@ export class DmpUserEditorModel implements DmpUserPersist { user: Guid; role: DmpUserRole; email: string; - userType: DmpUserType= DmpUserType.Internal; + userType: DmpUserType = DmpUserType.Internal; sectionId: Guid; protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); @@ -467,10 +511,10 @@ export class DmpUserEditorModel implements DmpUserPersist { ) { } fromModel(item: DmpUser): DmpUserEditorModel { - if(item?.user?.id) this.user = item.user.id; + if (item?.user?.id) this.user = item.user.id; this.role = item.role; // TODO this.email = item.email; - this.userType = (item == null || this.user != null) ? DmpUserType.Internal : DmpUserType.External; + this.userType = (item == null || this.user != null) ? DmpUserType.Internal : DmpUserType.External; this.sectionId = item.sectionId; return this; @@ -623,7 +667,7 @@ export class DmpDescriptionTemplateEditorModel implements DmpDescriptionTemplate if (context == null) { context = DmpDescriptionTemplateEditorModel.createValidationContext({ validationErrorModel: this.validationErrorModel, - rootPath + rootPath: rootPath, }); } @@ -635,7 +679,7 @@ export class DmpDescriptionTemplateEditorModel implements DmpDescriptionTemplate static createValidationContext(params: { rootPath?: string, - validationErrorModel: ValidationErrorModel + validationErrorModel: ValidationErrorModel, }): ValidationContext { const { rootPath = '', validationErrorModel } = params; 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 7a0957885..80b7e8fe4 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 @@ -1,15 +1,16 @@ +import { DragDropModule } from '@angular/cdk/drag-drop'; import { NgModule } from '@angular/core'; import { FormattingModule } from '@app/core/formatting.module'; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; import { RichTextEditorModule } from '@app/library/rich-text-editor/rich-text-editor.module'; +import { ReferenceFieldModule } from '@app/ui/reference/reference-field/reference-field.module'; import { CommonFormsModule } from '@common/forms/common-forms.module'; import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; import { CommonUiModule } from '@common/ui/common-ui.module'; +import { DmpUserFieldModule } from '../dmp-user-field/dmp-user-field.module'; 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'; -import { DmpUserFieldModule } from '../dmp-user-field/dmp-user-field.module'; +import { DmpFormProgressIndicationModule } from './form-progress-indication/dmp-form-progress-indication.module'; @NgModule({ imports: [ @@ -22,7 +23,8 @@ import { DmpUserFieldModule } from '../dmp-user-field/dmp-user-field.module'; AutoCompleteModule, ReferenceFieldModule, DragDropModule, - DmpUserFieldModule + DmpUserFieldModule, + DmpFormProgressIndicationModule ], declarations: [ DmpEditorComponent, diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.component.html b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.component.html new file mode 100644 index 000000000..68f919097 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.component.html @@ -0,0 +1,5 @@ +
+
{{progressSoFar}} {{'GENERAL.PREPOSITIONS.OF' | translate}} {{total}}
+ +
{{value}}%
+
diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.component.scss b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.component.scss new file mode 100644 index 000000000..a15510639 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.component.scss @@ -0,0 +1,16 @@ +.percentage { + color: #212121; + opacity: 0.7; + font-weight: 400; + font-size: 0.875rem; +} + +.progress-bar { + border-radius: 20px; + height: 11px; + +} + +::ng-deep .mat-progress-bar .mat-progress-bar-fill::after { + border-radius: 20px !important; +} diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.component.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.component.ts new file mode 100644 index 000000000..f38f5c58d --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.component.ts @@ -0,0 +1,104 @@ +import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { AbstractControl, UntypedFormArray, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { VisibilityRulesService } from '@app/ui/description/editor/description-form/visibility-rules/visibility-rules.service'; +import { BaseComponent } from '@common/base/base.component'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'app-dmp-form-progress-indication', + templateUrl: './dmp-form-progress-indication.component.html', + styleUrls: ['./dmp-form-progress-indication.component.scss'] +}) +export class DmpFormProgressIndicationComponent extends BaseComponent implements OnInit, OnChanges { + @Input() formGroup: UntypedFormGroup; + + @Input() public progressValueAccuracy = 2; + progressSoFar: number; + total: number; + percent: number; + + constructor(private visibilityRulesService: VisibilityRulesService) { super(); } + + public value = 0; + ngOnInit() { + this.init(); + } + + ngOnChanges(changes: SimpleChanges) { + if (changes.formGroup) { + this.init(); + } + } + + init() { + setTimeout(() => { this.calculateValueForProgressbar(); }); + this.formGroup + .valueChanges + .pipe(takeUntil(this._destroyed)) + .subscribe(control => { + setTimeout(() => { this.calculateValueForProgressbar(); }); + }); + } + + calculateValueForProgressbar() { + this.progressSoFar = this.countFormControlsValidForProgress(this.formGroup); + this.total = this.countFormControlsRequiredFieldsForTotal(this.formGroup); + this.percent = (this.progressSoFar / this.total) * 100; + this.value = Number.parseFloat(this.percent.toPrecision(this.progressValueAccuracy)); + } + + countFormControlsValidForProgress(formControl: AbstractControl): number { + let valueCurrent = 0; + if (formControl instanceof UntypedFormControl) { + if (this.controlRequired(formControl) && this.controlEnabled(formControl) && formControl.valid) { + valueCurrent++; + } + } else if (formControl instanceof UntypedFormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + valueCurrent = valueCurrent + this.countFormControlsValidForProgress(control); + }); + } else if (formControl instanceof UntypedFormArray) { + formControl.controls.forEach(item => { + valueCurrent = valueCurrent + this.countFormControlsValidForProgress(item); + }); + } + return valueCurrent; + } + + countFormControlsRequiredFieldsForTotal(formControl: AbstractControl, checkVisibility = false): number { + let valueCurrent = 0; + if (formControl instanceof UntypedFormControl) { + if (this.controlRequired(formControl) && this.controlEnabled(formControl)) { + valueCurrent++; + } + } else if (formControl instanceof UntypedFormGroup) { + if (!checkVisibility || (!formControl.get('id')?.value || (this.visibilityRulesService.isVisibleMap[formControl.get('id').value] ?? true))) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + valueCurrent = valueCurrent + this.countFormControlsRequiredFieldsForTotal(control, checkVisibility); + }); + } + } else if (formControl instanceof UntypedFormArray) { + formControl.controls.forEach(item => { + valueCurrent = valueCurrent + this.countFormControlsRequiredFieldsForTotal(item, checkVisibility); + }); + } + return valueCurrent; + } + + controlRequired(formControl: AbstractControl) { + if (formControl.validator) { + const validator = formControl.validator({} as AbstractControl); + if (validator && validator.required) { + return true; + } + } else { return false } + } + + controlEnabled(formControl: AbstractControl) { + if (formControl.enabled) { + return true; + } else { return false } + } +} diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.module.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.module.ts new file mode 100644 index 000000000..3c004582a --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/form-progress-indication/dmp-form-progress-indication.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { DmpFormProgressIndicationComponent } from './dmp-form-progress-indication.component'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule + ], + declarations: [ + DmpFormProgressIndicationComponent + ], + exports: [ + DmpFormProgressIndicationComponent + ] +}) +export class DmpFormProgressIndicationModule { } diff --git a/dmp-frontend/src/app/ui/dmp/dmp-user-field/dmp-user-field.component.html b/dmp-frontend/src/app/ui/dmp/dmp-user-field/dmp-user-field.component.html index 0fe457109..e82c4b574 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-user-field/dmp-user-field.component.html +++ b/dmp-frontend/src/app/ui/dmp/dmp-user-field/dmp-user-field.component.html @@ -43,7 +43,7 @@
- {{'DMP-EDITOR.FIELDS.USER' | translate}}* + {{'DMP-EDITOR.FIELDS.USER' | translate}} {{user.get('user').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} @@ -51,7 +51,7 @@
- {{'DMP-EDITOR.FIELDS.EMAIL' | translate}}* + {{'DMP-EDITOR.FIELDS.EMAIL' | translate}} {{user.get('email').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} diff --git a/dmp-frontend/src/app/ui/dmp/dmp-user-field/dmp-user-field.component.ts b/dmp-frontend/src/app/ui/dmp/dmp-user-field/dmp-user-field.component.ts index 298f18318..c8e49fa56 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-user-field/dmp-user-field.component.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-user-field/dmp-user-field.component.ts @@ -57,10 +57,10 @@ export class DmpUserFieldComponent extends BaseComponent implements OnInit { removeUser(userIndex: number): void { (this.form.get('users') as FormArray).removeAt(userIndex); - DmpEditorModel.reApplyPropertiesValidators( + DmpEditorModel.reApplyUsersValidators( { formGroup: this.form, - validationErrorModel: this.validationErrorModel + validationErrorModel: this.validationErrorModel, } ); this.form.get('users').markAsDirty(); @@ -78,7 +78,7 @@ export class DmpUserFieldComponent extends BaseComponent implements OnInit { moveItemInArray(usersFormArray.controls, event.previousIndex, event.currentIndex); usersFormArray.updateValueAndValidity(); - DmpEditorModel.reApplyPropertiesValidators( + DmpEditorModel.reApplyUsersValidators( { formGroup: this.form, validationErrorModel: this.validationErrorModel diff --git a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts index ebdbd8438..b488ce9da 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts +++ b/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts @@ -131,7 +131,8 @@ export class DmpListingComponent extends BaseComponent implements OnInit { //IBr selector: '.dataset-tour', content: 'Step 2', orientation: Orientation.Right, - isStepUnique: false + isStepUnique: false, + useHighlightPadding: true } ] }; diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index 848a79c14..e0779fe4a 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -195,8 +195,8 @@

{{ 'DMP-OVERVIEW.ACTIONS.EXPORT' | translate }}

- -
+ +
diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar.component.css b/dmp-frontend/src/app/ui/sidebar/sidebar.component.css index 8101f9a7a..a7e615f2f 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar.component.css +++ b/dmp-frontend/src/app/ui/sidebar/sidebar.component.css @@ -33,6 +33,7 @@ .nav-row { display: flex; flex-direction: row; + align-items: center; width: 100%; padding: 10px 20px; text-align: left; @@ -43,6 +44,19 @@ font-family: 'Roboto',sans-serif; } +.nav-subrow { + display: flex; + flex-direction: row; + align-items: center; + width: 100%; + text-align: left; + letter-spacing: 0px; + color: #000000; + opacity: 1; + font-size: 0.93rem; + font-family: 'Roboto',sans-serif; +} + .nav-row:hover { background-color: #ececec; border-radius: 6px; diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar.component.html b/dmp-frontend/src/app/ui/sidebar/sidebar.component.html index 761a43cc0..868345c5c 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar.component.html +++ b/dmp-frontend/src/app/ui/sidebar/sidebar.component.html @@ -9,11 +9,13 @@ person {{groupMenuRoute.title | translate}} - - - {{ groupMenuRoute.icon }} - person - {{groupMenuRoute.title | translate}} + + + {{ groupMenuRoute.icon }} diff --git a/dmp-frontend/src/notification-service/ui/admin/notification-template/editor/field-options/notification-template-field-options.component.ts b/dmp-frontend/src/notification-service/ui/admin/notification-template/editor/field-options/notification-template-field-options.component.ts index ec6eb97d7..601a3f9a1 100644 --- a/dmp-frontend/src/notification-service/ui/admin/notification-template/editor/field-options/notification-template-field-options.component.ts +++ b/dmp-frontend/src/notification-service/ui/admin/notification-template/editor/field-options/notification-template-field-options.component.ts @@ -1,6 +1,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { UntypedFormArray } from '@angular/forms'; -import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { NotificationServiceEnumUtils } from '@notification-service/core/formatting/enum-utils.service'; import { BaseComponent } from '@common/base/base.component'; import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { NotificationFieldInfoEditorModel, NotificationFieldOptionsEditorModel } from '../notification-template-editor.model'; @@ -25,7 +25,7 @@ export class NotificationTemplateFieldOptionsComponent extends BaseComponent imp readonly separatorKeysCodes: number[] = [ENTER, COMMA]; constructor( - public enumUtils: EnumUtils, + public enumUtils: NotificationServiceEnumUtils, ) { super(); } ngOnInit() { diff --git a/dmp-frontend/src/notification-service/ui/admin/notification-template/editor/notification-template-editor.component.html b/dmp-frontend/src/notification-service/ui/admin/notification-template/editor/notification-template-editor.component.html index 2bfeaaa6f..9cac4ff1d 100644 --- a/dmp-frontend/src/notification-service/ui/admin/notification-template/editor/notification-template-editor.component.html +++ b/dmp-frontend/src/notification-service/ui/admin/notification-template/editor/notification-template-editor.component.html @@ -2,7 +2,7 @@
-
+

{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-EDITOR.NEW' | translate}}

diff --git a/dmp-frontend/src/notification-service/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.html b/dmp-frontend/src/notification-service/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.html index 4674a0024..9a061466f 100644 --- a/dmp-frontend/src/notification-service/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.html +++ b/dmp-frontend/src/notification-service/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.html @@ -7,48 +7,69 @@ -
-
-
+
+
+

{{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.TITLE' | translate}}

+
+
+
- - {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.IS-ACTIVE' | translate}} - +
+
+
+ + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
+
-
- {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.NOTIFICATION-TYPE' | translate}} +
+
+ + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.NOTIFICATION-TYPE' | translate}} {{enumUtils.toNotificationTypeString(type)}} - +
+
-
- {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.KIND' | translate}} +
+
+ + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.KIND' | translate}} {{enumUtils.toNotificationTemplateKindString(kind)}} - +
+
-
- {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.CHANNEL' | translate}} +
+
+ + {{'NOTIFICATION-SERVICE.NOTIFICATION-TEMPLATE-LISTING.FILTER.CHANNEL' | translate}} {{enumUtils.toNotificationTemplateChannelString(channel)}} - +
+
-
- -
+
+
diff --git a/dmp-frontend/src/notification-service/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.scss b/dmp-frontend/src/notification-service/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.scss index 999f5a7c6..56598bd16 100644 --- a/dmp-frontend/src/notification-service/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.scss +++ b/dmp-frontend/src/notification-service/ui/admin/notification-template/listing/filters/notification-template-listing-filters.component.scss @@ -22,4 +22,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.html b/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.html index 2cc76ea56..6adc22cd1 100644 --- a/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.html +++ b/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.html @@ -7,79 +7,101 @@ -
-
-
+
+
+

{{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.TITLE' | translate}}

+
+
+
- - {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.IS-ACTIVE' | translate}} - - -
-
- - {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.USERS' | translate}} - - - -
- -
- - {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.NOTIFICATION-TYPE' | translate}} - - {{enumUtils.toNotificationTypeString(type)}} - - -
- -
- - {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.CONTACT-TYPE' | translate}} - - {{enumUtils.toNotificationContactTypeString(contactType)}} - - -
- -
- - {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.NOTIFY-STATE' | translate}} - - {{enumUtils.toNotificationNotifyStateString(notifyState)}} - - -
- -
- - {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.TRACKING-STATE' | translate}} - - {{enumUtils.toNotificationTrackingStateString(trackingState)}} - - -
- -
- - {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.TRACKING-PROCESS' | translate}} - - {{enumUtils.toNotificationTrackingProcessString(trackingProcess)}} - - -
+
+
+
+ + {{'NOTIFICATION-SERVICE.NOTIFICATION-LISTING.FILTER.IS-ACTIVE' | translate}} + +
+
-
- -
+
+
diff --git a/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.scss b/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.scss index af7cd9926..5a1a293b5 100644 --- a/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.scss +++ b/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.scss @@ -1,11 +1,11 @@ -// ::ng-deep.mat-mdc-menu-panel { -// max-width: 100% !important; -// height: 100% !important; -// } +::ng-deep.mat-mdc-menu-panel { + max-width: 100% !important; + height: 100% !important; +} -// :host::ng-deep.mat-mdc-menu-content:not(:empty) { -// padding-top: 0 !important; -// } +:host::ng-deep.mat-mdc-menu-content:not(:empty) { + padding-top: 0 !important; +} .filter-button{ @@ -18,4 +18,8 @@ // } } - +::ng-deep .mdc-form-field { + label { + margin: 0; + } +} diff --git a/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.ts b/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.ts index d9bf03b27..b22ad3d02 100644 --- a/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.ts +++ b/dmp-frontend/src/notification-service/ui/admin/notification/filters/notification-listing-filters.component.ts @@ -2,7 +2,7 @@ import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; import { NotificationFilter } from '@notification-service/core/query/notification.lookup'; import { UserService } from '@app/core/services/user/user.service'; -import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { NotificationServiceEnumUtils } from '@notification-service/core/formatting/enum-utils.service'; import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; import { BaseComponent } from '@common/base/base.component'; import { Guid } from '@common/types/guid'; @@ -37,7 +37,7 @@ export class NotificationListingFiltersComponent extends BaseComponent implement protected appliedFilterCount: number = 0; constructor( - public enumUtils: EnumUtils, + public enumUtils: NotificationServiceEnumUtils, private userService: UserService, ) { super(); } diff --git a/dmp-frontend/src/notification-service/ui/inapp-notification/editor/inapp-notification-editor.component.ts b/dmp-frontend/src/notification-service/ui/inapp-notification/editor/inapp-notification-editor.component.ts index a76cce850..881751746 100644 --- a/dmp-frontend/src/notification-service/ui/inapp-notification/editor/inapp-notification-editor.component.ts +++ b/dmp-frontend/src/notification-service/ui/inapp-notification/editor/inapp-notification-editor.component.ts @@ -99,9 +99,9 @@ export class InAppNotificationEditorComponent extends BaseComponent implements O maxWidth: '300px', restoreFocus: false, data: { - message: this.language.instant('COMMONS.CONFIRMATION-DIALOG.DELETE-ITEM'), - confirmButton: this.language.instant('COMMONS.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), - cancelButton: this.language.instant('COMMONS.CONFIRMATION-DIALOG.ACTIONS.CANCEL') + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), + cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') } }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { diff --git a/dmp-frontend/src/notification-service/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.html b/dmp-frontend/src/notification-service/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.html index b8ce889af..ad04ae659 100644 --- a/dmp-frontend/src/notification-service/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.html +++ b/dmp-frontend/src/notification-service/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.html @@ -2,28 +2,26 @@
-
+
diff --git a/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/UserNotificationPreferenceController.java b/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/UserNotificationPreferenceController.java index d09539f67..54a0e3fb9 100644 --- a/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/UserNotificationPreferenceController.java +++ b/notification-service/notification-web/src/main/java/gr/cite/notification/web/controllers/UserNotificationPreferenceController.java @@ -2,6 +2,7 @@ package gr.cite.notification.web.controllers; import gr.cite.notification.audit.AuditableAction; import gr.cite.notification.authorization.AuthorizationFlags; +import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.enums.TenantConfigurationType; import gr.cite.notification.common.types.tenantconfiguration.NotifierListConfigurationDataContainer; import gr.cite.notification.data.UserNotificationPreferenceEntity; @@ -18,6 +19,7 @@ import gr.cite.notification.web.model.QueryResult; import gr.cite.tools.auditing.AuditService; import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.data.query.Ordering; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.exception.MyForbiddenException; @@ -80,15 +82,16 @@ public class UserNotificationPreferenceController { @GetMapping("user/{userId}/current") @Transactional - public UserNotificationPreference current(@PathVariable UUID userId, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException { + public List current(@PathVariable UUID userId, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException { logger.debug(new MapLogEntry("retrieving" + UserNotificationPreference.class.getSimpleName()).And("userId", userId).And("fields", fieldSet)); this.censorFactory.censor(UserNotificationPreferenceCensor.class).censor(fieldSet, userId); - UserNotificationPreferenceQuery query = this.queryFactory.query(UserNotificationPreferenceQuery.class).userId(userId); - UserNotificationPreference model = this.builderFactory.builder(UserNotificationPreferenceBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.firstAs(fieldSet)); - if (model == null) - throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{userId, TenantConfiguration.class.getSimpleName()}, LocaleContextHolder.getLocale())); + Ordering ordering = new Ordering(); + ordering.addAscending(UserNotificationPreference._ordinal); + UserNotificationPreferenceQuery query = this.queryFactory.query(UserNotificationPreferenceQuery.class).userId(userId).isActives(IsActive.Active); + query.setOrder(ordering); + List model = this.builderFactory.builder(UserNotificationPreferenceBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.collectAs(fieldSet)); this.auditService.track(AuditableAction.User_Notification_Preference_Lookup, Map.ofEntries( new AbstractMap.SimpleEntry("userId", userId), diff --git a/notification-service/notification-web/src/main/resources/config/notification-devel.yml b/notification-service/notification-web/src/main/resources/config/notification-devel.yml index d89f86b2e..c1f5527ea 100644 --- a/notification-service/notification-web/src/main/resources/config/notification-devel.yml +++ b/notification-service/notification-web/src/main/resources/config/notification-devel.yml @@ -3,7 +3,7 @@ notification: fields: - key: "{installation-url}" type: "String" - value: "http://localhost:42000" + value: "http://localhost:4200" resolver: global-policies: - #dmpInvitationExternalUser @@ -14,16 +14,16 @@ notification: contacts: [ inapp, email ] - #dpmModified type: 4542262A-22F8-4BAA-9DB6-1C8E70AC1DBB - contacts: [ email ] + contacts: [ inapp, email ] - #dmpFinalised type: 90DB0B46-42DE-BD89-AEBF-6F27EFEB256E - contacts: [ email ] + contacts: [ inapp, email ] - #descriptionModified type: 4FDBFA80-7A71-4A69-B854-67CBB70648F1 - contacts: [ email ] + contacts: [ inapp, email ] - #descriptionFinalised type: 33790bad-94d4-488a-8ee2-7f6295ca18ea - contacts: [ email ] + contacts: [ inapp, email ] - #mergeAcountConfirmation type: BFE68845-CB05-4C5A-A03D-29161A7C9660 contacts: [ email ] @@ -32,10 +32,10 @@ notification: contacts: [ email ] - #dmpDeposit type: 55736F7A-83AB-4190-AF43-9D031A6F9612 - contacts: [ email ] + contacts: [ inapp, email ] - #descriptionTemplateInvitation type: 223BB607-EFA1-4CE7-99EC-4BEABFEF9A8B - contacts: [ email ] + contacts: [ inapp, email ] - #contactSupportType type: 5B1D6C52-88F9-418B-9B8A-6F1F963D9EAD contacts: [ email ] diff --git a/notification-service/notification-web/src/main/resources/config/notification.yml b/notification-service/notification-web/src/main/resources/config/notification.yml index fd0d90609..f9cbdbb05 100644 --- a/notification-service/notification-web/src/main/resources/config/notification.yml +++ b/notification-service/notification-web/src/main/resources/config/notification.yml @@ -2,7 +2,7 @@ notification: task: processor: enable: true - interval-seconds: 3 + interval-seconds: 5 options: retry-threshold: 300 max-retry-delay-seconds: 10800 diff --git a/notification-service/notification-web/src/main/resources/config/queue.yml b/notification-service/notification-web/src/main/resources/config/queue.yml index accbbca49..c1af6b725 100644 --- a/notification-service/notification-web/src/main/resources/config/queue.yml +++ b/notification-service/notification-web/src/main/resources/config/queue.yml @@ -27,7 +27,7 @@ queue: exchange: null rabbitmq: enable: false - interval-seconds: 30 + interval-seconds: 5 options: retry-threashold: 100 retry-delay-step-seconds: 300 @@ -45,7 +45,7 @@ queue: user-touched-topic: user.touch rabbitmq: enable: false - interval-seconds: 30 + interval-seconds: 5 options: retry-threashold: 100 retry-delay-step-seconds: 300 diff --git a/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/email/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/descriptionfinalised/email/body.en.html similarity index 100% rename from notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/email/body.en.html rename to notification-service/notification-web/src/main/resources/notification_templates/descriptionfinalised/email/body.en.html diff --git a/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/email/subject.en.txt b/notification-service/notification-web/src/main/resources/notification_templates/descriptionfinalised/email/subject.en.txt similarity index 100% rename from notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/email/subject.en.txt rename to notification-service/notification-web/src/main/resources/notification_templates/descriptionfinalised/email/subject.en.txt diff --git a/notification-service/notification-web/src/main/resources/notification_templates/descriptionfinalised/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/descriptionfinalised/inapp/body.en.html new file mode 100644 index 000000000..d4b3099e9 --- /dev/null +++ b/notification-service/notification-web/src/main/resources/notification_templates/descriptionfinalised/inapp/body.en.html @@ -0,0 +1,12 @@ + + + + + + + +

Dear {recipient},

+

{reasonName} just finalised the Description {name}.

+ Click here to view it. + + \ No newline at end of file diff --git a/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/subject.en.txt b/notification-service/notification-web/src/main/resources/notification_templates/descriptionfinalised/inapp/subject.en.txt similarity index 100% rename from notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/subject.en.txt rename to notification-service/notification-web/src/main/resources/notification_templates/descriptionfinalised/inapp/subject.en.txt diff --git a/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/body.en.html index 7025e58bf..efc0f69cc 100644 --- a/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/body.en.html +++ b/notification-service/notification-web/src/main/resources/notification_templates/descriptionmodified/inapp/body.en.html @@ -3,302 +3,10 @@ - Simple Transactional Email - - - - - - - -
  -
- - - This is preheader text. Some clients will show this text as a preview. - - - - - - - - -
- - - - -
-

Dear {recipient},

-

{reasonName} just made changes to the Description {name}.

- - - - - - - -
- - - - - - -
Click here to view it.
-
- -
-
- - - - - - -
-
 
+

Dear {recipient},

+

{reasonName} just made changes to the Description {name}.

+ Click here to view it. \ No newline at end of file diff --git a/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/body.en.html index 8c2ac8ab7..81edddeac 100644 --- a/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/body.en.html +++ b/notification-service/notification-web/src/main/resources/notification_templates/descriptiontemplateinvitation/inapp/body.en.html @@ -3,303 +3,11 @@ - Simple Transactional Email - - - - - - - -
  -
- - - This is preheader text. Some clients will show this text as a preview. - - - - - - - - -
- - - - -
-

Dear {recipient},

-

You have been invited to co-develop the Template {templateName}.

-

Click the button to redirect to {templateName}.

- - - - - - - -
- - - - - - -
{templateName}
-
- -
-
- - - - - - -
-
 
+

Dear {recipient},

+

You have been invited to co-develop the Template {templateName}.

+

Click the button to redirect to {templateName}.

+ {templateName} \ No newline at end of file diff --git a/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/body.en.html deleted file mode 100644 index f34f75c23..000000000 --- a/notification-service/notification-web/src/main/resources/notification_templates/descrptionfinalised/inapp/body.en.html +++ /dev/null @@ -1,304 +0,0 @@ - - - - - - Simple Transactional Email - - - - - - - - - -
  -
- - - This is preheader text. Some clients will show this text as a preview. - - - - - - - - -
- - - - -
-

Dear {recipient},

-

{reasonName} just finalised the Description {name}.

- - - - - - - -
- - - - - - -
Click here to view it.
-
- -
-
- - - - - - -
-
 
- - \ No newline at end of file diff --git a/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/body.en.html index c80220834..8b5400605 100644 --- a/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/body.en.html +++ b/notification-service/notification-web/src/main/resources/notification_templates/dmpdeposit/inapp/body.en.html @@ -3,302 +3,10 @@ - Simple Transactional Email - - - - - - - -
  -
- - - This is preheader text. Some clients will show this text as a preview. - - - - - - - - -
- - - - -
-

Dear {recipient},

-

{reasonName} just publish the {name}.

- - - - - - - -
- - - - - - -
Click here to view it.
-
- -
-
- - - - - - -
-
 
+

Dear {recipient},

+

{reasonName} just publish the {name}.

+ Click here to view it. \ No newline at end of file diff --git a/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/body.en.html index 3e00fce2d..a3ed86e87 100644 --- a/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/body.en.html +++ b/notification-service/notification-web/src/main/resources/notification_templates/dmpfinalised/inapp/body.en.html @@ -3,302 +3,10 @@ - Simple Transactional Email - - - - - - - -
  -
- - - This is preheader text. Some clients will show this text as a preview. - - - - - - - - -
- - - - -
-

Dear {recipient},

-

{reasonName} just finalised the Dmp {name}.

- - - - - - - -
- - - - - - -
Click here to view it.
-
- -
-
- - - - - - -
-
 
+

Dear {recipient},

+

{reasonName} just finalised the Dmp {name}.

+ Click here to view it. \ No newline at end of file diff --git a/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/body.en.html index 75a586097..6f79a296a 100644 --- a/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/body.en.html +++ b/notification-service/notification-web/src/main/resources/notification_templates/dmpinvitationexistinguser/inapp/body.en.html @@ -4,301 +4,11 @@ Simple Transactional Email - - - - - - - -
  -
- - - This is preheader text. Some clients will show this text as a preview. - - - - - - - - -
- - - - -
-

Dear {recipient},

-

{reasonName} just add you to collaborate to Data Management plan {dmpname} with role {dmprole}.

-

Click the button to redirect to {dmpname}.

- - - - - - - -
- - - - - - -
Join
-
-
-
- - - - - - -
-
 
+

Dear {recipient},

+

{reasonName} just add you to collaborate to Data Management plan {dmpname} with role {dmprole}.

+

Click the button to redirect to {dmpname}.

+ Join \ No newline at end of file diff --git a/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/body.en.html index 7a36dccba..1a266243f 100644 --- a/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/body.en.html +++ b/notification-service/notification-web/src/main/resources/notification_templates/dmpmodified/inapp/body.en.html @@ -3,302 +3,11 @@ - Simple Transactional Email - - - - - - - +

Dear {recipient},

+

{reasonName} just made changes to the Dmp {name}.

+ Click here to view it.
  -
- - - This is preheader text. Some clients will show this text as a preview. - - - - - - - - -
- - - - -
-

Dear {recipient},

-

{reasonName} just made changes to the Dmp {name}.

- - - - - - - -
- - - - - - -
Click here to view it.
-
- -
-
- - - - - - -
-
 
\ No newline at end of file diff --git a/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/body.en.html index bc5bfc087..b0c78080f 100644 --- a/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/body.en.html +++ b/notification-service/notification-web/src/main/resources/notification_templates/mergeacountconfirmation/inapp/body.en.html @@ -3,302 +3,12 @@ - Simple Transactional Email - - - - - - - -
  -
- - - This is preheader text. Some clients will show this text as a preview. - - - - - - - - -
- - - - -
- OpenDMP -

User {userName} have sent you a merge Request.

-

Please confirm that you want to merge your {installation-url} account with that account. -
The link will expire in {expiration_time}.

- - - - - - -
- - - - - - -
Confirm Merge Request
-
-
-
- - - - - - -
-
 
+ OpenDMP +

User {userName} have sent you a merge Request.

+

Please confirm that you want to merge your {installation-url} account with that account. +
The link will expire in {expiration_time}.

+ Confirm Merge Request \ No newline at end of file diff --git a/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/body.en.html b/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/body.en.html index a43224531..24f36119e 100644 --- a/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/body.en.html +++ b/notification-service/notification-web/src/main/resources/notification_templates/removecredentialconfirmation/inapp/body.en.html @@ -3,302 +3,12 @@ - Simple Transactional Email - - - - - - - -
  -
- - - This is preheader text. Some clients will show this text as a preview. - - - - - - - - -
- - - - -
- OpenDMP -

You have made a request to unlink your email account in ARGOS.

-

Please confirm that you want to unlink your {email} account. -
The link will expire in {expiration_time}.

- - - - - - -
- - - - - - -
Confirm Unlink Request
-
-
-
- - - - - - -
-
 
+ OpenDMP +

You have made a request to unlink your email account in ARGOS.

+

Please confirm that you want to unlink your {email} account. +
The link will expire in {expiration_time}.

+ Confirm Unlink Request \ No newline at end of file diff --git a/notification-service/notification/src/main/java/gr/cite/notification/query/UserNotificationPreferenceQuery.java b/notification-service/notification/src/main/java/gr/cite/notification/query/UserNotificationPreferenceQuery.java index e51efad40..addbcfc7b 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/query/UserNotificationPreferenceQuery.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/query/UserNotificationPreferenceQuery.java @@ -8,6 +8,7 @@ import gr.cite.tools.data.query.FieldResolver; import gr.cite.tools.data.query.QueryBase; import gr.cite.tools.data.query.QueryContext; import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.Predicate; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; @@ -89,15 +90,20 @@ public class UserNotificationPreferenceQuery extends QueryBase inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserNotificationPreferenceEntity._isActive)); + for (IsActive item : this.isActives) + inClause.value(item); + predicates.add(inClause); } if (this.type != null) { predicates.add(queryContext.Root.get(UserNotificationPreferenceEntity._type).in(this.type)); } if (this.channel != null) { - predicates.add(queryContext.Root.get(UserNotificationPreferenceEntity._channel).in(this.channel)); + CriteriaBuilder.In inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UserNotificationPreferenceEntity._channel)); + for (NotificationContactType item : this.channel) + inClause.value(item); + predicates.add(inClause); } if (!predicates.isEmpty()) { diff --git a/notification-service/notification/src/main/java/gr/cite/notification/service/inappnotification/InAppNotificationServiceImpl.java b/notification-service/notification/src/main/java/gr/cite/notification/service/inappnotification/InAppNotificationServiceImpl.java index c42efc474..6b33a2816 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/service/inappnotification/InAppNotificationServiceImpl.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/service/inappnotification/InAppNotificationServiceImpl.java @@ -1,6 +1,7 @@ package gr.cite.notification.service.inappnotification; import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.notification.authorization.OwnedResource; import gr.cite.notification.authorization.Permission; import gr.cite.notification.common.enums.NotificationInAppTracking; import gr.cite.notification.common.scope.user.UserScope; @@ -92,7 +93,7 @@ public class InAppNotificationServiceImpl implements InAppNotificationService { public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { logger.debug("deleting in-app notification: {}", id); - this.authService.authorizeForce(Permission.DeleteInAppNotification); + this.authService.authorizeAtLeastOneForce(this.userScope.getUserId() != null ? List.of(new OwnedResource(this.userScope.getUserId())) : null, Permission.DeleteInAppNotification); this.deleterFactory.deleter(InAppNotificationDeleter.class).deleteAndSaveByIds(List.of(id)); } } diff --git a/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/InAppMessageBuilder.java b/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/InAppMessageBuilder.java index 17936dff6..bdc59e025 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/InAppMessageBuilder.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/service/message/builder/InAppMessageBuilder.java @@ -70,7 +70,7 @@ public class InAppMessageBuilder extends MessageBuilderBase implements MessageBu } NotificationProperties.Flow options = this.flowMap.get("in-app").getOrDefault(notification.getType(), null); - NotificationTemplate template = notificationTemplateService.lookupOverriddenTemplates(notification.getType(), NotificationTemplateChannel.Email, messageInfo.getLanguage()); + NotificationTemplate template = notificationTemplateService.lookupOverriddenTemplates(notification.getType(), NotificationTemplateChannel.InApp, messageInfo.getLanguage()); if (options == null && template == null) { logger.error("Could not retrieve flow options for notification " + notification.getId() + " of type " + notification.getType()); diff --git a/notification-service/notification/src/main/java/gr/cite/notification/service/message/common/MessageBuilderBase.java b/notification-service/notification/src/main/java/gr/cite/notification/service/message/common/MessageBuilderBase.java index 7327f02da..380b820b9 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/service/message/common/MessageBuilderBase.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/service/message/common/MessageBuilderBase.java @@ -165,7 +165,6 @@ public abstract class MessageBuilderBase { return formatting; } - //TODO: Here check with a language accepted list and fallback to default protected String lookupOrReadLocalizedFile(NotificationProperties.Template.TemplateCache templateCache, String path, String language) { String filename = path.replace("{language}", language); File file = null; diff --git a/notification-service/notification/src/main/java/gr/cite/notification/service/notification/NotificationServiceImpl.java b/notification-service/notification/src/main/java/gr/cite/notification/service/notification/NotificationServiceImpl.java index 3bf92b0f9..ff8c91615 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/service/notification/NotificationServiceImpl.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/service/notification/NotificationServiceImpl.java @@ -10,13 +10,16 @@ import gr.cite.notification.convention.ConventionService; import gr.cite.notification.data.TenantEntity; import gr.cite.notification.data.TenantEntityManager; import gr.cite.notification.data.NotificationEntity; +import gr.cite.notification.data.UserNotificationPreferenceEntity; import gr.cite.notification.errorcode.ErrorThesaurusProperties; import gr.cite.notification.model.SendNotificationResult; +import gr.cite.notification.model.UserNotificationPreference; import gr.cite.notification.model.builder.NotificationBuilder; import gr.cite.notification.model.Notification; import gr.cite.notification.model.deleter.NotificationDeleter; import gr.cite.notification.model.persist.NotificationPersist; import gr.cite.notification.query.NotificationQuery; +import gr.cite.notification.query.UserNotificationPreferenceQuery; import gr.cite.notification.service.channelResolution.ChannelResolutionService; import gr.cite.notification.service.contact.extractor.ContactExtractorFactory; import gr.cite.notification.service.contact.model.Contact; @@ -25,6 +28,7 @@ import gr.cite.notification.service.message.model.Message; import gr.cite.notification.service.notify.NotifierFactory; import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.deleter.DeleterFactory; +import gr.cite.tools.data.query.Ordering; import gr.cite.tools.data.query.QueryFactory; import gr.cite.tools.exception.MyApplicationException; import gr.cite.tools.exception.MyForbiddenException; @@ -49,6 +53,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; @Service @RequestScope @@ -141,7 +146,9 @@ public class NotificationServiceImpl implements NotificationService { } public SendNotificationResult doNotify(NotificationEntity notification) { - List contactTypes = this.orderContactTypes(notification); + List contactTypes = this.orderContactTypesFromPreferences(notification); + if (this.conventionService.isListNullOrEmpty(contactTypes)) contactTypes = this.orderContactTypes(notification); + for (NotificationContactType contactType: contactTypes) { SendNotificationResult result = this.sendNotification(notification, contactType); if (result.getSuccess()) return result; @@ -149,6 +156,17 @@ public class NotificationServiceImpl implements NotificationService { return null; } + private List orderContactTypesFromPreferences(NotificationEntity notification) { + Ordering ordering = new Ordering(); + ordering.addAscending(UserNotificationPreference._ordinal); + UserNotificationPreferenceQuery query = this.queryFactory.query(UserNotificationPreferenceQuery.class).userId(notification.getUserId()).type(notification.getType()).isActives(IsActive.Active); + query.setOrder(ordering); + + List preferences = query.collectAs(new BaseFieldSet().ensure(UserNotificationPreference._channel)); + if (!this.conventionService.isListNullOrEmpty(preferences)) return preferences.stream().map(x -> x.getChannel()).collect(Collectors.toList()); + return null; + } + private List orderContactTypes(NotificationEntity notification) { List contactTypes = this.channelResolutionService.resolve(notification.getType(), notification.getUserId()); if (notification.getContactTypeHint() == null) return contactTypes; diff --git a/notification-service/notification/src/main/java/gr/cite/notification/service/notificationscheduling/NotificationSchedulingServiceImpl.java b/notification-service/notification/src/main/java/gr/cite/notification/service/notificationscheduling/NotificationSchedulingServiceImpl.java index b315945e3..53136d40c 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/service/notificationscheduling/NotificationSchedulingServiceImpl.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/service/notificationscheduling/NotificationSchedulingServiceImpl.java @@ -141,8 +141,8 @@ public class NotificationSchedulingServiceImpl implements NotificationScheduling } else { tenantScope.setTempTenant(entityManager, null, tenantScope.getDefaultTenantCode()); } - notification = entityManager.merge(notification); - entityManager.persist(notification); +// notification = entityManager.merge(notification); + entityManager.merge(notification); entityManager.flush(); } finally { tenantScope.removeTempTenant(entityManager); diff --git a/notification-service/notification/src/main/java/gr/cite/notification/service/notify/InAppNotifier.java b/notification-service/notification/src/main/java/gr/cite/notification/service/notify/InAppNotifier.java index e92995be7..96fd88989 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/service/notify/InAppNotifier.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/service/notify/InAppNotifier.java @@ -70,6 +70,7 @@ public class InAppNotifier implements Notify{ inApp.setTenantId(tenantScope.getTenant()); entityManager.persist(inApp); + entityManager.flush(); InAppTrackingData trackingData = new InAppTrackingData(inApp.getId()); data = this.jsonHandlingService.toJsonSafe(trackingData); diff --git a/notification-service/notification/src/main/java/gr/cite/notification/service/userNotificationPreference/UserNotificationPreferenceServiceImpl.java b/notification-service/notification/src/main/java/gr/cite/notification/service/userNotificationPreference/UserNotificationPreferenceServiceImpl.java index 64ddd6d47..10ab5df7f 100644 --- a/notification-service/notification/src/main/java/gr/cite/notification/service/userNotificationPreference/UserNotificationPreferenceServiceImpl.java +++ b/notification-service/notification/src/main/java/gr/cite/notification/service/userNotificationPreference/UserNotificationPreferenceServiceImpl.java @@ -1,7 +1,9 @@ package gr.cite.notification.service.userNotificationPreference; import gr.cite.commons.web.authz.service.AuthorizationService; +import gr.cite.notification.authorization.OwnedResource; import gr.cite.notification.authorization.Permission; +import gr.cite.notification.common.enums.IsActive; import gr.cite.notification.common.enums.NotificationContactType; import gr.cite.notification.common.types.tenantconfiguration.NotifierListConfigurationDataContainer; import gr.cite.notification.config.notification.NotificationConfig; @@ -66,7 +68,7 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr public List persist(UserNotificationPreferencePersist model, FieldSet fieldSet) { logger.debug(new MapLogEntry("persisting").And("model", model).And("fields", fieldSet)); - this.authService.authorizeForce(Permission.EditUserNotificationPreference); + this.authService.authorizeAtLeastOneForce(model.getUserId() != null ? List.of(new OwnedResource(model.getUserId())) : null, Permission.EditUserNotificationPreference); Map> currentNotificationListPolicies; NotifierListConfigurationDataContainer tenantNotifierListPolicies = this.tenantConfigurationService.collectTenantNotifierList(); @@ -169,6 +171,7 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr preferences = this.queryFactory .query(UserNotificationPreferenceQuery.class) .type(type) + .isActives(IsActive.Active) .userId(userId).collect(); int ordinal = 0; @@ -176,6 +179,7 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr for (NotificationContactType contactType : contactTypes) { UserNotificationPreferenceEntity preference = preferences.stream().filter(x -> x.getChannel() == contactType).findFirst().orElse(null); + boolean isUpdate = preference != null; if (preference != null) { preference.setOrdinal(ordinal); @@ -186,9 +190,12 @@ public class UserNotificationPreferenceServiceImpl implements UserNotificationPr preference.setOrdinal(ordinal); preference.setChannel(contactType); preference.setCreatedAt(Instant.now()); + preference.setIsActive(IsActive.Active); } - this.entityManager.merge(preference); - this.entityManager.persist(preference); + preference.setUpdatedAt(Instant.now()); + + if(isUpdate) this.entityManager.merge(preference); + else this.entityManager.persist(preference); updatedPreferences.add(preference); ordinal++; }