Merge branch 'dmp-refactoring' of code-repo.d4science.org:MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Efstratios Giannopoulos 2024-07-12 13:57:40 +03:00
commit f48621303f
89 changed files with 1379 additions and 188 deletions

View File

@ -178,6 +178,11 @@ public class AuditableAction {
public static final EventId Annotation_Created_Notify = new EventId(280000, "Annotation_Created_Notify");
public static final EventId UsageLimit_Query = new EventId(290000, "UsageLimit_Query");
public static final EventId UsageLimit_Lookup = new EventId(290001, "UsageLimit_Lookup");
public static final EventId UsageLimit_Persist = new EventId(290002, "UsageLimit_Persist");
public static final EventId UsageLimit_Delete = new EventId(290003, "UsageLimit_Delete");
}

View File

@ -200,6 +200,11 @@ public final class Permission {
public static String EditPrefillingSource= "EditPrefillingSource";
public static String DeletePrefillingSource = "DeletePrefillingSource";
//UsageLimit
public static String BrowseUsageLimit = "BrowseUsageLimit";
public static String EditUsageLimit = "EditUsageLimit";
public static String DeleteUsageLimit = "DeleteUsageLimit";
//NotificationTemplate
public static String BrowseStatus = "BrowseStatus";
public static String EditStatus = "EditStatus";
@ -220,6 +225,7 @@ public final class Permission {
public static String ViewReferenceTypePage = "ViewReferenceTypePage";
public static String ViewReferencePaPlge = "ViewReferencePage";
public static String ViewEntityLockPage = "ViewEntityLockPage";
public static String ViewUsageLimitPage = "ViewUsageLimitPage";
public static String ViewDescriptionTemplatePage = "ViewDescriptionTemplatePage";
public static String ViewPlanBlueprintPage = "ViewPlanBlueprintPage";
public static String ViewPublicDescriptionPage = "ViewPublicDescriptionPage";

View File

@ -69,7 +69,7 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes
if (idsToResolve.isEmpty()) return affiliatedResources;
List<PlanUserEntity> planUsers;
try {
this.tenantEntityManager.loadExplictTenantFilters();
this.tenantEntityManager.loadExplicitTenantFilters();
planUsers = this.queryFactory.query(PlanUserQuery.class).disableTracking().planIds(ids).sectionIsEmpty(true).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(PlanUser._role).ensure(PlanUser._plan));
} catch (InvalidApplicationException e) {
log.error(e.getMessage(), e);
@ -109,7 +109,7 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes
List<UserDescriptionTemplateEntity> userDescriptionTemplates;
try {
this.tenantEntityManager.loadExplictTenantFilters();
this.tenantEntityManager.loadExplicitTenantFilters();
userDescriptionTemplates = this.queryFactory.query(UserDescriptionTemplateQuery.class).disableTracking().descriptionTemplateIds(ids).userIds(userId).isActive(IsActive.Active).collectAs(new BaseFieldSet().ensure(UserDescriptionTemplate._role).ensure(UserDescriptionTemplate._descriptionTemplate));
} catch (InvalidApplicationException e) {
log.error(e.getMessage(), e);
@ -139,7 +139,7 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes
//TODO: investigate if we want to use cache
boolean hasAny;
try {
this.tenantEntityManager.loadExplictTenantFilters();
this.tenantEntityManager.loadExplicitTenantFilters();
hasAny = this.queryFactory.query(UserDescriptionTemplateQuery.class).disableTracking().userIds(userId).isActive(IsActive.Active).count() > 0;
} catch (InvalidApplicationException e) {
log.error(e.getMessage(), e);
@ -176,7 +176,7 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes
List<PlanUserEntity> planUsers;
List<DescriptionEntity> descriptionEntities;
try {
this.tenantEntityManager.loadExplictTenantFilters();
this.tenantEntityManager.loadExplicitTenantFilters();
descriptionEntities = this.queryFactory.query(DescriptionQuery.class).disableTracking().ids(ids).collectAs(new BaseFieldSet().ensure(Description._id).ensure(Description._planDescriptionTemplate).ensure(Description._plan));
planDescriptionTemplateEntities = this.queryFactory.query(PlanDescriptionTemplateQuery.class).disableTracking().ids(descriptionEntities.stream().map(DescriptionEntity::getPlanDescriptionTemplateId).distinct().toList()).collectAs(new BaseFieldSet().ensure(PlanDescriptionTemplate._id).ensure(PlanDescriptionTemplate._sectionId));
planUsers = this.queryFactory.query(PlanUserQuery.class).disableTracking().descriptionIds(ids).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(PlanUser._role).ensure(PlanUser._sectionId).ensure(PlanUser._plan));
@ -232,7 +232,7 @@ public class AuthorizationContentResolverImpl implements AuthorizationContentRes
List<PlanUserEntity> planUsers;
try {
this.tenantEntityManager.loadExplictTenantFilters();
this.tenantEntityManager.loadExplicitTenantFilters();
planUsers = this.queryFactory.query(PlanUserQuery.class).disableTracking().planIds(planId).userIds(userId).isActives(IsActive.Active).collectAs(new BaseFieldSet().ensure(PlanUser._role).ensure(PlanUser._sectionId).ensure(PlanUser._plan));
} catch (InvalidApplicationException e) {
log.error(e.getMessage(), e);

View File

@ -0,0 +1,44 @@
package org.opencdmp.commons.enums;
import com.fasterxml.jackson.annotation.JsonValue;
import org.opencdmp.data.converters.enums.DatabaseEnum;
import java.util.Map;
public enum UsageLimitMetricValue implements DatabaseEnum<String> {
USER_COUNT(MetricValues.UserCount),
PLAN_COUNT(MetricValues.PlanCount),
BLUEPRINT_COUNT(MetricValues.BlueprintCount),
DESCRIPTION_COUNT(MetricValues.DescriptionCount),
DESCRIPTION_TEMPLATE_COUNT(MetricValues.DescriptionTemplateCount),
DESCRIPTION_TEMPLATE_TYPE_COUNT(MetricValues.DescriptionTemplateTypeCount),
PREFILLING_SOURCES_COUNT(MetricValues.PrefillingSourcesCount),
REFERENCE_TYPE_COUNT(MetricValues.ReferenceTypeCount);
private final String value;
public static class MetricValues {
public static final String UserCount = "user_count";
public static final String PlanCount = "plan_count";
public static final String BlueprintCount = "blueprint_count";
public static final String DescriptionCount = "description_count";
public static final String DescriptionTemplateCount = "description_template_count";
public static final String DescriptionTemplateTypeCount = "description_template_type_count";
public static final String PrefillingSourcesCount = "prefilling_sources_count";
public static final String ReferenceTypeCount = "reference_type_count";
}
UsageLimitMetricValue(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return this.value;
}
private static final Map<String, UsageLimitMetricValue> map = EnumUtils.getEnumValueMap(UsageLimitMetricValue.class);
public static UsageLimitMetricValue of(String i) {
return map.get(i);
}
}

View File

@ -114,7 +114,7 @@ public class TenantEntityManager {
this.tenantFiltersDisabled = false;
}
public void loadExplictTenantFilters() throws InvalidApplicationException {
public void loadExplicitTenantFilters() throws InvalidApplicationException {
if (!this.entityManager.isOpen()) return;
this.disableTenantFilters();

View File

@ -0,0 +1,111 @@
package org.opencdmp.data;
import jakarta.persistence.*;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.enums.UsageLimitMetricValue;
import org.opencdmp.data.converters.enums.IsActiveConverter;
import org.opencdmp.data.tenant.TenantScopedBaseEntity;
import java.time.Instant;
import java.util.UUID;
@Entity
@Table(name = "\"UsageLimit\"")
public class UsageLimitEntity extends TenantScopedBaseEntity {
@Id
@Column(name = "id", columnDefinition = "uuid", updatable = false, nullable = false)
private UUID id;
public static final String _id = "id";
@Column(name = "label", length = _labelLength, nullable = false)
private String label;
public static final String _label = "label";
public static final int _labelLength = 250;
@Column(name = "metric_value", nullable = false)
private UsageLimitMetricValue metricValue;
public static final String _metricValue = "metricValue";
@Column(name = "value", nullable = false)
private Long value;
public static final String _value = "value";
@Column(name = "is_active", nullable = false)
@Convert(converter = IsActiveConverter.class)
private IsActive isActive;
public static final String _isActive = "isActive";
@Column(name = "created_at", nullable = false)
private Instant createdAt;
public static final String _createdAt = "createdAt";
@Column(name = "updated_at", nullable = false)
private Instant updatedAt;
public static final String _updatedAt = "updatedAt";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public UsageLimitMetricValue getMetricValue() {
return metricValue;
}
public void setMetricValue(UsageLimitMetricValue metricValue) {
this.metricValue = metricValue;
}
public Long getValue() {
return value;
}
public void setValue(Long value) {
this.value = value;
}
public IsActive getIsActive() {
return isActive;
}
public void setIsActive(IsActive isActive) {
this.isActive = isActive;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public Instant getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Instant updatedAt) {
this.updatedAt = updatedAt;
}
}

View File

@ -0,0 +1,109 @@
package org.opencdmp.model;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.enums.UsageLimitMetricValue;
import java.time.Instant;
import java.util.UUID;
public class UsageLimit {
private UUID id;
public static final String _id = "id";
private String label;
public static final String _label = "label";
private UsageLimitMetricValue metricValue;
public static final String _metricValue = "metricValue";
private Long value;
public static final String _value = "value";
private IsActive isActive;
public static final String _isActive = "isActive";
private Instant createdAt;
public static final String _createdAt = "createdAt";
private Instant updatedAt;
public static final String _updatedAt = "updatedAt";
private String hash;
public static final String _hash = "hash";
private Boolean belongsToCurrentTenant;
public static final String _belongsToCurrentTenant = "belongsToCurrentTenant";
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public UsageLimitMetricValue getMetricValue() {
return metricValue;
}
public void setMetricValue(UsageLimitMetricValue metricValue) {
this.metricValue = metricValue;
}
public Long getValue() {
return value;
}
public void setValue(Long value) {
this.value = value;
}
public IsActive getIsActive() {
return isActive;
}
public void setIsActive(IsActive isActive) {
this.isActive = isActive;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public Instant getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Instant updatedAt) {
this.updatedAt = updatedAt;
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
public Boolean getBelongsToCurrentTenant() {
return belongsToCurrentTenant;
}
public void setBelongsToCurrentTenant(Boolean belongsToCurrentTenant) {
this.belongsToCurrentTenant = belongsToCurrentTenant;
}
}

View File

@ -0,0 +1,74 @@
package org.opencdmp.model.builder;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.UsageLimitEntity;
import org.opencdmp.model.UsageLimit;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UsageLimitBuilder extends BaseBuilder<UsageLimit, UsageLimitEntity> {
private final TenantScope tenantScope;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public UsageLimitBuilder(
ConventionService conventionService,
TenantScope tenantScope) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(UsageLimitBuilder.class)));
this.tenantScope = tenantScope;
}
public UsageLimitBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
public List<UsageLimit> build(FieldSet fields, List<UsageLimitEntity> data) throws MyApplicationException {
this.logger.debug("building for {} items requesting {} fields", Optional.ofNullable(data).map(List::size).orElse(0), Optional.ofNullable(fields).map(FieldSet::getFields).map(Set::size).orElse(0));
this.logger.trace(new DataLogEntry("requested fields", fields));
if (fields == null || data == null || fields.isEmpty())
return new ArrayList<>();
List<UsageLimit> models = new ArrayList<>();
for (UsageLimitEntity d : data) {
UsageLimit m = new UsageLimit();
if (fields.hasField(this.asIndexer(UsageLimit._id)))
m.setId(d.getId());
if (fields.hasField(this.asIndexer(UsageLimit._label)))
m.setLabel(d.getLabel());
if (fields.hasField(this.asIndexer(UsageLimit._metricValue)))
m.setMetricValue(d.getMetricValue());
if (fields.hasField(this.asIndexer(UsageLimit._value)))
m.setValue(d.getValue());
if (fields.hasField(this.asIndexer(UsageLimit._createdAt)))
m.setCreatedAt(d.getCreatedAt());
if (fields.hasField(this.asIndexer(UsageLimit._updatedAt)))
m.setUpdatedAt(d.getUpdatedAt());
if (fields.hasField(this.asIndexer(UsageLimit._isActive)))
m.setIsActive(d.getIsActive());
if (fields.hasField(this.asIndexer(UsageLimit._hash)))
m.setHash(this.hashValue(d.getUpdatedAt()));
if (fields.hasField(this.asIndexer(UsageLimit._belongsToCurrentTenant))) m.setBelongsToCurrentTenant(this.getBelongsToCurrentTenant(d, this.tenantScope));
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
}

View File

@ -0,0 +1,40 @@
package org.opencdmp.model.censorship;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.censor.CensorFactory;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.Permission;
import org.opencdmp.convention.ConventionService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UsageLimitsCensor extends BaseCensor {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UsageLimitsCensor.class));
protected final AuthorizationService authService;
protected final CensorFactory censorFactory;
public UsageLimitsCensor(ConventionService conventionService,
AuthorizationService authService,
CensorFactory censorFactory) {
super(conventionService);
this.authService = authService;
this.censorFactory = censorFactory;
}
public void censor(FieldSet fields) {
logger.debug(new DataLogEntry("censoring fields", fields));
if (fields == null || fields.isEmpty())
return;
this.authService.authorizeForce(Permission.BrowseUsageLimit);
}
}

View File

@ -0,0 +1,79 @@
package org.opencdmp.model.deleter;
import gr.cite.tools.data.deleter.Deleter;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.UsageLimitEntity;
import org.opencdmp.query.UsageLimitQuery;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.management.InvalidApplicationException;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UsageLimitDeleter implements Deleter {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UsageLimitDeleter.class));
private final TenantEntityManager entityManager;
protected final QueryFactory queryFactory;
protected final DeleterFactory deleterFactory;
@Autowired
public UsageLimitDeleter(
TenantEntityManager entityManager,
QueryFactory queryFactory,
DeleterFactory deleterFactory
) {
this.entityManager = entityManager;
this.queryFactory = queryFactory;
this.deleterFactory = deleterFactory;
}
public void deleteAndSaveByIds(List<UUID> ids) throws InvalidApplicationException {
logger.debug(new MapLogEntry("collecting to delete").And("count", Optional.ofNullable(ids).map(List::size).orElse(0)).And("ids", ids));
List<UsageLimitEntity> data = this.queryFactory.query(UsageLimitQuery.class).ids(ids).collect();
logger.trace("retrieved {} items", Optional.ofNullable(data).map(List::size).orElse(0));
this.deleteAndSave(data);
}
public void deleteAndSave(List<UsageLimitEntity> data) throws InvalidApplicationException {
logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0));
this.delete(data);
logger.trace("saving changes");
this.entityManager.flush();
logger.trace("changes saved");
}
public void delete(List<UsageLimitEntity> data) throws InvalidApplicationException {
logger.debug("will delete {} items", Optional.ofNullable(data).map(List::size).orElse(0));
if (data == null || data.isEmpty())
return;
Instant now = Instant.now();
for (UsageLimitEntity item : data) {
logger.trace("deleting item {}", item.getId());
item.setIsActive(IsActive.Inactive);
item.setUpdatedAt(now);
logger.trace("updating item");
this.entityManager.merge(item);
logger.trace("updated item");
}
}
}

View File

@ -0,0 +1,122 @@
package org.opencdmp.model.persist;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.enums.UsageLimitMetricValue;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.UsageLimitEntity;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class UsageLimitPersist {
private UUID id;
public static final String _id = "id";
private String label;
public static final String _label = "label";
private UsageLimitMetricValue metricValue;;
public static final String _metricValue = "metricValue";
private Long value;
public static final String _value = "value";
private String hash;
public static final String _hash = "hash";
public UUID getId() {
return this.id;
}
public void setId(UUID id) {
this.id = id;
}
public String getLabel() {
return this.label;
}
public void setLabel(String label) {
this.label = label;
}
public UsageLimitMetricValue getMetricValue() {
return metricValue;
}
public void setMetricValue(UsageLimitMetricValue metricValue) {
this.metricValue = metricValue;
}
public Long getValue() {
return value;
}
public void setValue(Long value) {
this.value = value;
}
public String getHash() {
return this.hash;
}
public void setHash(String hash) {
this.hash = hash;
}
@Component(UsageLimitPersistValidator.ValidatorName)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class UsageLimitPersistValidator extends BaseValidator<UsageLimitPersist> {
public static final String ValidatorName = "UsageLimitPersistValidator";
private final MessageSource messageSource;
protected UsageLimitPersistValidator(ConventionService conventionService, ErrorThesaurusProperties errors, MessageSource messageSource) {
super(conventionService, errors);
this.messageSource = messageSource;
}
@Override
protected Class<UsageLimitPersist> modelClass() {
return UsageLimitPersist.class;
}
@Override
protected List<Specification> specifications(UsageLimitPersist item) {
return Arrays.asList(
this.spec()
.iff(() -> this.isValidGuid(item.getId()))
.must(() -> this.isValidHash(item.getHash()))
.failOn(UsageLimitPersist._hash).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{UsageLimitPersist._hash}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isValidGuid(item.getId()))
.must(() -> !this.isValidHash(item.getHash()))
.failOn(UsageLimitPersist._hash).failWith(this.messageSource.getMessage("Validation_OverPosting", new Object[]{}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isEmpty(item.getLabel()))
.failOn(UsageLimitPersist._label).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{UsageLimitPersist._label}, LocaleContextHolder.getLocale())),
this.spec()
.iff(() -> !this.isEmpty(item.getLabel()))
.must(() -> this.lessEqualLength(item.getLabel(), UsageLimitEntity._labelLength))
.failOn(UsageLimitPersist._label).failWith(this.messageSource.getMessage("Validation_MaxLength", new Object[]{UsageLimitPersist._label}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isNull(item.getMetricValue()))
.failOn(UsageLimitPersist._metricValue).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{UsageLimitPersist._metricValue}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> !this.isNull(item.getValue()))
.failOn(UsageLimitPersist._value).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{UsageLimitPersist._value}, LocaleContextHolder.getLocale()))
);
}
}
}

View File

@ -0,0 +1,227 @@
package org.opencdmp.query;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.query.FieldResolver;
import gr.cite.tools.data.query.QueryBase;
import gr.cite.tools.data.query.QueryContext;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Predicate;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.enums.UsageLimitMetricValue;
import org.opencdmp.commons.scope.user.UserScope;
import org.opencdmp.data.*;
import org.opencdmp.model.UsageLimit;
import org.opencdmp.query.utils.QueryUtilsService;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.*;
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class UsageLimitQuery extends QueryBase<UsageLimitEntity> {
private String like;
private Collection<UUID> ids;
private Collection<IsActive> isActives;
private Collection<UsageLimitMetricValue> usageLimitMetricValues;
private Collection<UUID> excludedIds;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
public UsageLimitQuery like(String value) {
this.like = value;
return this;
}
public UsageLimitQuery ids(UUID value) {
this.ids = List.of(value);
return this;
}
public UsageLimitQuery ids(UUID... value) {
this.ids = Arrays.asList(value);
return this;
}
public UsageLimitQuery ids(Collection<UUID> values) {
this.ids = values;
return this;
}
public UsageLimitQuery isActive(IsActive value) {
this.isActives = List.of(value);
return this;
}
public UsageLimitQuery isActive(IsActive... value) {
this.isActives = Arrays.asList(value);
return this;
}
public UsageLimitQuery isActive(Collection<IsActive> values) {
this.isActives = values;
return this;
}
public UsageLimitQuery excludedIds(Collection<UUID> values) {
this.excludedIds = values;
return this;
}
public UsageLimitQuery excludedIds(UUID value) {
this.excludedIds = List.of(value);
return this;
}
public UsageLimitQuery excludedIds(UUID... value) {
this.excludedIds = Arrays.asList(value);
return this;
}
public UsageLimitQuery usageLimitMetricValues(UsageLimitMetricValue value) {
this.usageLimitMetricValues = List.of(value);
return this;
}
public UsageLimitQuery usageLimitMetricValues(UsageLimitMetricValue... value) {
this.usageLimitMetricValues = Arrays.asList(value);
return this;
}
public UsageLimitQuery usageLimitMetricValues(Collection<UsageLimitMetricValue> values) {
this.usageLimitMetricValues = values;
return this;
}
public UsageLimitQuery authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
public UsageLimitQuery enableTracking() {
this.noTracking = false;
return this;
}
public UsageLimitQuery disableTracking() {
this.noTracking = true;
return this;
}
private final UserScope userScope;
private final AuthorizationService authService;
private final QueryUtilsService queryUtilsService;
private final TenantEntityManager tenantEntityManager;
public UsageLimitQuery(
UserScope userScope, AuthorizationService authService, QueryUtilsService queryUtilsService, TenantEntityManager tenantEntityManager) {
this.userScope = userScope;
this.authService = authService;
this.queryUtilsService = queryUtilsService;
this.tenantEntityManager = tenantEntityManager;
}
@Override
protected EntityManager entityManager(){
return this.tenantEntityManager.getEntityManager();
}
@Override
protected Class<UsageLimitEntity> entityClass() {
return UsageLimitEntity.class;
}
@Override
protected Boolean isFalseQuery() {
return this.isEmpty(this.ids) || this.isEmpty(this.isActives) || this.isEmpty(this.excludedIds) || this.isEmpty(this.usageLimitMetricValues);
}
@Override
protected <X, Y> Predicate applyFilters(QueryContext<X, Y> queryContext) {
List<Predicate> predicates = new ArrayList<>();
if (this.ids != null) {
CriteriaBuilder.In<UUID> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UsageLimitEntity._id));
for (UUID item : this.ids)
inClause.value(item);
predicates.add(inClause);
}
if (this.like != null && !this.like.isBlank()) {
predicates.add(this.queryUtilsService.ilike(queryContext.CriteriaBuilder, queryContext.Root.get(UsageLimitEntity._label), this.like));
}
if (this.isActives != null) {
CriteriaBuilder.In<IsActive> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UsageLimitEntity._isActive));
for (IsActive item : this.isActives)
inClause.value(item);
predicates.add(inClause);
}
if (this.usageLimitMetricValues != null) {
CriteriaBuilder.In<UsageLimitMetricValue> inClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(UsageLimitEntity._metricValue));
for (UsageLimitMetricValue item : this.usageLimitMetricValues)
inClause.value(item);
predicates.add(inClause);
}
if (this.excludedIds != null) {
CriteriaBuilder.In<UUID> notInClause = queryContext.CriteriaBuilder.in(queryContext.Root.get(ReferenceEntity._id));
for (UUID item : this.excludedIds)
notInClause.value(item);
predicates.add(notInClause.not());
}
if (!predicates.isEmpty()) {
Predicate[] predicatesArray = predicates.toArray(new Predicate[0]);
return queryContext.CriteriaBuilder.and(predicatesArray);
} else {
return null;
}
}
@Override
protected UsageLimitEntity convert(Tuple tuple, Set<String> columns) {
UsageLimitEntity item = new UsageLimitEntity();
item.setId(QueryBase.convertSafe(tuple, columns, UsageLimitEntity._id, UUID.class));
item.setTenantId(QueryBase.convertSafe(tuple, columns, UsageLimitEntity._tenantId, UUID.class));
item.setLabel(QueryBase.convertSafe(tuple, columns, UsageLimitEntity._label, String.class));
item.setMetricValue(QueryBase.convertSafe(tuple, columns, UsageLimitEntity._metricValue, UsageLimitMetricValue.class));
item.setValue(QueryBase.convertSafe(tuple, columns, UsageLimitEntity._value, Long.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, UsageLimitEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, UsageLimitEntity._updatedAt, Instant.class));
item.setIsActive(QueryBase.convertSafe(tuple, columns, UsageLimitEntity._isActive, IsActive.class));
return item;
}
@Override
protected String fieldNameOf(FieldResolver item) {
if (item.match(UsageLimit._id))
return UsageLimitEntity._id;
else if (item.match(UsageLimit._label))
return UsageLimitEntity._label;
else if (item.match(UsageLimit._metricValue))
return UsageLimitEntity._metricValue;
else if (item.match(UsageLimit._value))
return UsageLimitEntity._value;
else if (item.match(UsageLimit._createdAt))
return UsageLimitEntity._createdAt;
else if (item.match(UsageLimit._updatedAt))
return UsageLimitEntity._updatedAt;
else if (item.match(UsageLimit._hash))
return UsageLimitEntity._updatedAt;
else if (item.match(UsageLimit._isActive))
return UsageLimitEntity._isActive;
else if (item.prefix(UsageLimit._belongsToCurrentTenant))
return UsageLimitEntity._tenantId;
else
return null;
}
}

View File

@ -0,0 +1,70 @@
package org.opencdmp.query.lookup;
import gr.cite.tools.data.query.Lookup;
import gr.cite.tools.data.query.QueryFactory;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.enums.UsageLimitMetricValue;
import org.opencdmp.query.UsageLimitQuery;
import java.util.List;
import java.util.UUID;
public class UsageLimitLookup extends Lookup {
private String like;
private List<IsActive> isActive;
private List<UUID> ids;
private List<UsageLimitMetricValue> usageLimitMetricValues;
private List<UUID> excludedIds;
public String getLike() {
return like;
}
public void setLike(String like) {
this.like = like;
}
public List<IsActive> getIsActive() {
return isActive;
}
public void setIsActive(List<IsActive> isActive) {
this.isActive = isActive;
}
public List<UUID> getIds() {
return ids;
}
public void setIds(List<UUID> ids) { this.ids = ids; }
public List<UsageLimitMetricValue> getUsageLimitsMetricValues() {
return usageLimitMetricValues;
}
public void setUsageLimitsMetricValues(List<UsageLimitMetricValue> usageLimitMetricValues) {
this.usageLimitMetricValues = usageLimitMetricValues;
}
public List<UUID> getExcludedIds() {
return excludedIds;
}
public void setExcludedIds(List<UUID> excludeIds) {
this.excludedIds = excludeIds;
}
public UsageLimitQuery enrich(QueryFactory queryFactory) {
UsageLimitQuery query = queryFactory.query(UsageLimitQuery.class);
if (this.like != null) query.like(this.like);
if (this.isActive != null) query.isActive(this.isActive);
if (this.ids != null) query.ids(this.ids);
if (this.usageLimitMetricValues != null) query.usageLimitMetricValues(this.usageLimitMetricValues);
if (this.excludedIds != null) query.excludedIds(this.excludedIds);
this.enrichCommon(query);
return query;
}
}

View File

@ -0,0 +1,26 @@
package org.opencdmp.service.accounting;
public class AccountingService {
private Integer getCurrentMetricValue(String metric) {
return 10;
}
private void set(String metric) {
//Get/Calculate current metric value
//Find metric value from db
// compare these two and throw UsageLimitException when current > metric value
}
private void increase(String metric) {
//Get/Calculate current metric value
//Find metric value from db
// compare these two and throw UsageLimitException when current > metric value
}
private void decrease(String metric) {
//Get/Calculate current metric value
//Find metric value from db
// compare these two and throw UsageLimitException when current > metric value
}
}

View File

@ -222,6 +222,8 @@ public class DescriptionServiceImpl implements DescriptionService {
if (!data.getPlanId().equals(model.getPlanId())) throw new MyValidationException(this.errors.getPlanCanNotChange().getCode(), this.errors.getPlanCanNotChange().getMessage());
if (!data.getPlanDescriptionTemplateId().equals(model.getPlanDescriptionTemplateId())) throw new MyValidationException(this.errors.getPlanDescriptionTemplateCanNotChange().getCode(), this.errors.getPlanDescriptionTemplateCanNotChange().getMessage());
} else {
//this.usageLimitService.checkIncrease("description_count");
PlanEntity planEntity = this.entityManager.find(PlanEntity.class, model.getPlanId(), true);
if (planEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getPlanId(), Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));

View File

@ -0,0 +1,23 @@
package org.opencdmp.service.usagelimit;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.FieldSet;
import org.opencdmp.commons.enums.UsageLimitMetricValue;
import org.opencdmp.model.UsageLimit;
import org.opencdmp.model.persist.UsageLimitPersist;
import javax.management.InvalidApplicationException;
import java.util.UUID;
public interface UsageLimitService {
UsageLimit persist(UsageLimitPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException;
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
void checkIncrease(UsageLimitMetricValue metric);
}

View File

@ -0,0 +1,126 @@
package org.opencdmp.service.usagelimit;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.authorization.Permission;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.enums.UsageLimitMetricValue;
import org.opencdmp.commons.scope.user.UserScope;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.UsageLimitEntity;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.model.Tag;
import org.opencdmp.model.UsageLimit;
import org.opencdmp.model.builder.UsageLimitBuilder;
import org.opencdmp.model.deleter.UsageLimitDeleter;
import org.opencdmp.model.persist.UsageLimitPersist;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import javax.management.InvalidApplicationException;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
@Service
public class UsageLimitServiceImpl implements UsageLimitService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UsageLimitServiceImpl.class));
private final TenantEntityManager entityManager;
private final AuthorizationService authorizationService;
private final DeleterFactory deleterFactory;
private final BuilderFactory builderFactory;
private final ConventionService conventionService;
private final ErrorThesaurusProperties errors;
private final MessageSource messageSource;
private final UserScope userScope;
@Autowired
public UsageLimitServiceImpl(
TenantEntityManager entityManager,
AuthorizationService authorizationService,
DeleterFactory deleterFactory,
BuilderFactory builderFactory,
ConventionService conventionService,
ErrorThesaurusProperties errors,
MessageSource messageSource,
UserScope userScope) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
this.builderFactory = builderFactory;
this.conventionService = conventionService;
this.errors = errors;
this.messageSource = messageSource;
this.userScope = userScope;
}
public UsageLimit persist(UsageLimitPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
logger.debug(new MapLogEntry("persisting data tag").And("model", model).And("fields", fields));
this.authorizationService.authorizeForce(Permission.EditUsageLimit);
Boolean isUpdate = this.conventionService.isValidGuid(model.getId());
UsageLimitEntity data;
if (isUpdate) {
data = this.entityManager.find(UsageLimitEntity.class, model.getId());
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Tag.class.getSimpleName()}, LocaleContextHolder.getLocale()));
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
} else {
data = new UsageLimitEntity();
data.setId(UUID.randomUUID());
data.setIsActive(IsActive.Active);
data.setCreatedAt(Instant.now());
}
data.setLabel(model.getLabel());
data.setMetricValue(model.getMetricValue());
data.setValue(model.getValue());
data.setUpdatedAt(Instant.now());
if (isUpdate)
this.entityManager.merge(data);
else
this.entityManager.persist(data);
this.entityManager.flush();
return this.builderFactory.builder(UsageLimitBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(BaseFieldSet.build(fields, UsageLimit._id), data);
}
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug("deleting UsageLimit: {}", id);
this.authorizationService.authorizeForce(Permission.DeleteUsageLimit);
this.deleterFactory.deleter(UsageLimitDeleter.class).deleteAndSaveByIds(List.of(id));
}
public void checkIncrease(UsageLimitMetricValue metric) {
//TODO
}
}

View File

@ -326,7 +326,9 @@ public class UserServiceImpl implements UserService {
@Override
public User patchRoles(UserRolePatchPersist model, FieldSet fields) throws InvalidApplicationException {
logger.debug(new MapLogEntry("persisting data UserRole").And("model", model).And("fields", fields));
this.authorizationService.authorizeAtLeastOneForce(this.userScope.getUserId() != null ? List.of(new OwnedResource(this.userScope.getUserId())) : null, Permission.EditUser, Permission.EditTenantUserRole);
if (!model.getHasTenantAdminMode()) this.authorizationService.authorizeForce(Permission.EditUser);
else this.authorizationService.authorizeForce(Permission.EditTenantUserRole);
UserEntity data = this.entityManager.find(UserEntity.class, model.getId(), true);
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), User.class.getSimpleName()}, LocaleContextHolder.getLocale()));

View File

@ -0,0 +1,142 @@
package org.opencdmp.controllers;
import com.fasterxml.jackson.core.JsonProcessingException;
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.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.ValidationFilterAnnotation;
import jakarta.transaction.Transactional;
import jakarta.xml.bind.JAXBException;
import org.opencdmp.audit.AuditableAction;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.data.UsageLimitEntity;
import org.opencdmp.model.UsageLimit;
import org.opencdmp.model.builder.UsageLimitBuilder;
import org.opencdmp.model.censorship.UsageLimitsCensor;
import org.opencdmp.model.persist.UsageLimitPersist;
import org.opencdmp.model.result.QueryResult;
import org.opencdmp.query.UsageLimitQuery;
import org.opencdmp.query.lookup.UsageLimitLookup;
import org.opencdmp.service.usagelimit.UsageLimitService;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.bind.annotation.*;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.management.InvalidApplicationException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping(path = "api/usage-limit")
public class UsageFilterController {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(UsageFilterController.class));
private final BuilderFactory builderFactory;
private final AuditService auditService;
private final UsageLimitService usageLimitService;
private final CensorFactory censorFactory;
private final QueryFactory queryFactory;
private final MessageSource messageSource;
public UsageFilterController(
BuilderFactory builderFactory,
AuditService auditService,
UsageLimitService usageLimitService,
CensorFactory censorFactory,
QueryFactory queryFactory,
MessageSource messageSource) {
this.builderFactory = builderFactory;
this.auditService = auditService;
this.usageLimitService = usageLimitService;
this.censorFactory = censorFactory;
this.queryFactory = queryFactory;
this.messageSource = messageSource;
}
@PostMapping("query")
public QueryResult<UsageLimit> query(@RequestBody UsageLimitLookup lookup) throws MyApplicationException, MyForbiddenException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, InvalidApplicationException {
logger.debug("querying {}", UsageLimit.class.getSimpleName());
this.censorFactory.censor(UsageLimitsCensor.class).censor(lookup.getProject());
UsageLimitQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.AllExceptPublic);
List<UsageLimitEntity> data = query.collectAs(lookup.getProject());
List<UsageLimit> models = this.builderFactory.builder(UsageLimitBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(lookup.getProject(), data);
long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size();
this.auditService.track(AuditableAction.UsageLimit_Query, "lookup", lookup);
return new QueryResult<>(models, count);
}
@GetMapping("{id}")
public UsageLimit get(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidApplicationException {
logger.debug(new MapLogEntry("retrieving" + UsageLimit.class.getSimpleName()).And("id", id).And("fields", fieldSet));
this.censorFactory.censor(UsageLimitsCensor.class).censor(fieldSet);
UsageLimitQuery query = this.queryFactory.query(UsageLimitQuery.class).disableTracking().authorize(AuthorizationFlags.AllExceptPublic).ids(id);
UsageLimit model = this.builderFactory.builder(UsageLimitBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(fieldSet, query.firstAs(fieldSet));
if (model == null)
throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, UsageLimit.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.auditService.track(AuditableAction.UsageLimit_Lookup, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id),
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
));
return model;
}
@PostMapping("persist")
@Transactional
@ValidationFilterAnnotation(validator = UsageLimitPersist.UsageLimitPersistValidator.ValidatorName, argumentName = "model")
public UsageLimit persist(@RequestBody UsageLimitPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, JAXBException, ParserConfigurationException, JsonProcessingException, TransformerException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("persisting" + UsageLimit.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
this.censorFactory.censor(UsageLimitsCensor.class).censor(fieldSet);
UsageLimit persisted = this.usageLimitService.persist(model, fieldSet);
this.auditService.track(AuditableAction.UsageLimit_Persist, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("model", model),
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
));
return persisted;
}
@DeleteMapping("{id}")
@Transactional
public void delete(@PathVariable("id") UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug(new MapLogEntry("retrieving" + UsageLimit.class.getSimpleName()).And("id", id));
this.usageLimitService.deleteAndSave(id);
this.auditService.track(AuditableAction.UsageLimit_Delete, "id", id);
}
}

View File

@ -1063,6 +1063,28 @@ permissions:
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
# Tenant Permissions
BrowseUsageLimit:
roles:
- Admin
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
EditUsageLimit:
roles:
- Admin
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
DeleteUsageLimit:
roles:
- Admin
claims: [ ]
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
# Status
BrowseStatus:
roles:
@ -1179,6 +1201,12 @@ permissions:
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
ViewUsageLimitPage:
roles:
- Admin
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
ViewDescriptionTemplatePage:
roles:
- Admin

View File

@ -0,0 +1,27 @@
DO $$DECLARE
this_version CONSTANT varchar := '00.01.067';
BEGIN
PERFORM * FROM "DBVersion" WHERE version = this_version;
IF FOUND THEN RETURN; END IF;
CREATE TABLE public."UsageLimit"
(
id uuid NOT NULL,
label character varying NOT NULL,
target_metric character varying NOT NULL,
value integer NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
is_active smallint NOT NULL,
tenant uuid,
PRIMARY KEY (id),
CONSTRAINT "UsageLimit_tenant_fkey" FOREIGN KEY (tenant)
REFERENCES public."Tenant" (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
NOT VALID
);
INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.01.067', '2024-11-07 12:00:00.000000+02', now(), 'Add UsageLimit table.');
END$$;

View File

@ -7,7 +7,6 @@ import { TranslateService } from '@ngx-translate/core';
import { filter, map, switchMap } from 'rxjs/operators';
import { AuthService, LoginStatus } from './core/services/auth/auth.service';
import { CultureService } from './core/services/culture/culture-service';
// import { BreadCrumbResolverService } from './ui/misc/breadcrumb/service/breadcrumb.service';
import { DomSanitizer, Title } from '@angular/platform-browser';
import { CookieService } from "ngx-cookie-service";
import { NgcCookieConsentService, NgcStatusChangeEvent } from "ngx-cookieconsent";
@ -34,7 +33,6 @@ declare var $: any;
export class AppComponent implements OnInit, AfterViewInit {
hasBreadCrumb = observableOf(false);
// sideNavOpen = false;
private sideNavSubscription: Subscription;
helpContentEnabled: boolean;
private statusChangeSubscription: Subscription;
@ -48,7 +46,6 @@ export class AppComponent implements OnInit, AfterViewInit {
private route: ActivatedRoute,
private authentication: AuthService,
private translate: TranslateService,
// private breadCrumbResolverService: BreadCrumbResolverService,
private titleService: Title,
private cultureService: CultureService,
private timezoneService: TimezoneService,
@ -106,16 +103,13 @@ export class AppComponent implements OnInit, AfterViewInit {
}
onActivate(event: any) {
// this.breadCrumbResolverService.push(event);
}
onDeactivate(event: any) {
//this.breadCrumbResolverService.clear()
}
ngOnInit() {
if (!this.cookieService.check("cookiesConsent")) {
// this.cookieService.set("cookiesConsent", "false", 356);
this.cookieService.set("cookiesConsent", "false", 356, null, null, false, 'Lax');
}
@ -179,16 +173,10 @@ export class AppComponent implements OnInit, AfterViewInit {
if (this.authentication.getSelectedTenantName() && this.authentication.getSelectedTenantName() !== '')
this.breadcrumbService.addIdResolvedValue(this.authentication.selectedTenant(), this.authentication.getSelectedTenantName());
// const enrichedUrl = this.tenantHandlingService.getUrlEnrichedWithTenantCode(event.url, this.authentication.selectedTenant() ?? 'default');
// if (event.url != enrichedUrl) {
// this.router.navigateByUrl(enrichedUrl);
// }
});
this.statusChangeSubscription = this.ccService.statusChange$.subscribe((event: NgcStatusChangeEvent) => {
if (event.status == "dismiss") {
// this.cookieService.set("cookiesConsent", "true", 365);
this.cookieService.set("cookiesConsent", "true", 356, null, null, false, 'Lax');
}
});

View File

@ -8,7 +8,7 @@ export interface PreprocessingPlanModel {
preprocessingDescriptionModels: PreprocessingDescriptionModel[];
}
// rda config
// common config
export interface PlanCommonModelConfig {
fileId: Guid;
label: string;

View File

@ -66,8 +66,8 @@ export interface PlanUser extends BaseEntity {
export interface PlanDescriptionTemplate extends BaseEntity {
plan?: Plan;
currentDescriptionTemplate?: DescriptionTemplate; //TODO: what is this?
descriptionTemplates?: DescriptionTemplate[]; //TODO: why it is array?
currentDescriptionTemplate?: DescriptionTemplate;
descriptionTemplates?: DescriptionTemplate[];
descriptionTemplateGroupId?: Guid;
sectionId?: Guid;
}

View File

@ -350,10 +350,7 @@ export class AuthService extends BaseService {
onAuthenticateError(errorResponse: HttpErrorResponse) {
this.zone.run(() => {
// const error: HttpError =
// this.httpErrorHandlingService.getError(errorResponse);
this.uiNotificationService.snackBarNotification(
// error.getMessagesString(),
errorResponse.message,
SnackBarNotificationLevel.Warning
);

View File

@ -65,7 +65,6 @@ export class LanguageInfoService {
if (selectedLocale) {
registerLocaleData(selectedLocale.default);
} else {
// locale = newCulture.code.split('-')[0];
import(`/node_modules/@angular/common/locales/${locale}.mjs`).catch(reason => {
this.logger.error('Could not load locale: ' + locale);
}).then(selectedDefaultLocale => {

View File

@ -26,13 +26,11 @@ export class FileTransformerHttpService extends BaseService {
}
exportPlan(planId: Guid, repositoryId: string, format: string): Observable<any> {
//TODO: implement
const url = `${this.apiBase}/export-plan`;
return this.http.post<any>(url, {id: planId, repositoryId: repositoryId, format: format}, {responseType: 'blob', observe: 'response'}).pipe(catchError((error: any) => throwError(error)));
}
exportDescription(id: Guid, repositoryId: string, format: string): Observable<any> {
//TODO: implement
const url = `${this.apiBase}/export-description`;
return this.http.post<any>(url, {id: id, repositoryId: repositoryId, format: format}, {responseType: 'blob', observe: 'response'}).pipe(catchError((error: any) => throwError(error)));
}

View File

@ -43,9 +43,6 @@ export class MatomoService {
var principalid = this.authService.userId();
if (principalid != null) { this.matomoTracker.setUserId(principalid.toString()); }
this.matomoTracker.trackLink(this.configurationService.server + category + "/" + type + "/" + id, "download");
// this.matomoTracker.trackLink(url, "download");
// this.matomoTracker.trackEvent(category, "Downloaded", type);
}
}
}

View File

@ -149,11 +149,6 @@ export class UserSettingsService extends BaseService {
}
return this.userSettingsHttpService.getSingle(userSettingsInformation.key).pipe(
// catchError(() => {
// const result: UserSettings<T> = this.defaultValue(userSettingsInformation);
// this.persistUserSettings(userSettingsInformation.key, result, userSettingsInformation, false);
// return observableOf(result);
// }),
map(x => {
const result: UserSettings<T> = (x ? this.toTypedUserSettings<T>(x as UserSettingsObject) : null);
this.persistUserSettings(userSettingsInformation.key, result, userSettingsInformation, false);

View File

@ -11,8 +11,6 @@ export class QueryParamsService {
serializeLookup(lookup: Lookup): string {
return JSON.stringify(lookup, (key: string, value: any) => {
switch (key) {
// case nameof<Lookup>(x => x.page):
// case nameof<Lookup>(x => x.order):
case nameof<Lookup>(x => x.metadata):
case nameof<Lookup>(x => x.project):
return undefined;
@ -24,8 +22,6 @@ export class QueryParamsService {
deSerializeLookup(serializedLookup: string): any {
const json = JSON.parse(serializedLookup);
// delete json[nameof<Lookup>(x => x.page)];
// delete json[nameof<Lookup>(x => x.order)];
delete json[nameof<Lookup>(x => x.metadata)];
delete json[nameof<Lookup>(x => x.project)];
return json;

View File

@ -26,7 +26,6 @@
<span *ngIf="_groupedItems">
<mat-optgroup *ngFor="let group of _groupedItems | async" [label]="group.title">
<mat-option *ngFor="let item of group.items" [value]="item" class="option autocomplete-option" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item) && !_optionComponent(item)" (optionActivated)="clickedOnPanel()">
<!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> -->
<ng-container *ngIf="_optionComponent(item)">
<ng-container *ngComponentOutlet="_optionComponent(item); inputs: { item };" />
</ng-container>
@ -59,7 +58,6 @@
<div *ngIf="_items | async as autocompleteItems; else loading">
<ng-container *ngIf="autocompleteItems.length; else noItems">
<mat-option *ngFor="let item of autocompleteItems" class="option autocomplete-option" [value]="item" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item) && !_optionComponent(item)" (optionActivated)="clickedOnPanel()">
<!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> -->
<ng-container *ngIf="_optionComponent(item)">
<ng-container *ngComponentOutlet="_optionComponent(item); inputs: { item };" />
</ng-container>

View File

@ -67,8 +67,6 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
valueOnBlur = new BehaviorSubject<any>(null);
onSelectAutoCompleteValue = new BehaviorSubject<any>(null);
// valueAssignSubscription: Subscription;
queryValue: string = "";
focused = false;
@ -406,16 +404,9 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
//Chip Functions
_addItem(event: MatChipInputEvent): void {
const input = event.input;
const value = event.value;
// Add our fruit
// if ((value || '').trim()) {
// this.selectedItems.push(value.trim());
// }
// Reset the input value
if (input) {
this.inputValue = '';
}
//this.inputFormControl.setValue(null);
}
public reset(): void {
this._inputSubject.unsubscribe();

View File

@ -8,7 +8,6 @@
<span *ngIf="_groupedItems">
<mat-optgroup *ngFor="let group of _groupedItems | async" [label]="group.title">
<mat-option *ngFor="let item of group.items" [value]="item" class="autocomplete-option" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item)">
<!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> -->
<ng-template #cellTemplate *ngIf="_optionTemplate(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{
item: item
}"></ng-template>
@ -29,7 +28,6 @@
<div *ngIf="_items | async as autocompleteItems; else loading">
<ng-container *ngIf="autocompleteItems.length; else noItems">
<mat-option *ngFor="let item of autocompleteItems" [value]="item" class="autocomplete-option" [class.two-line-mat-option]="_subtitleFn(item) && !_optionTemplate(item)">
<!-- <img style="vertical-align:middle;" aria-hidden src="{{state.flag}}" height="25" /> -->
<ng-template #cellTemplate *ngIf="_optionTemplate(item)" [ngTemplateOutlet]="_optionTemplate(item)" [ngTemplateOutletContext]="{
item: item
}"></ng-template>

View File

@ -375,7 +375,4 @@ export class SingleAutoCompleteComponent extends _CustomComponentMixinBase imple
this.configuration.valueAssign != null ? this.configuration.valueAssign(item) : item
)
}
// get forceFocus(): boolean {
// return this.configuration.forceFocus != null ? this.configuration.forceFocus : false;
// }
}

View File

@ -30,7 +30,6 @@ export class CanDeactivateGuard extends BaseComponent implements CanDeactivate<C
warning: this.language.instant('GENERAL.CONFIRMATION-DIALOG.LEAVE-WARNING'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.LEAVE'),
// icon: 'error_outline'
}
});
return dialogRef.afterClosed().pipe(map(x => x ? true : false));

View File

@ -337,8 +337,6 @@ export class GuidedTourComponent implements AfterViewInit, OnDestroy {
public get overlayTop(): number {
if (this.selectedElementRect) {
// return this.selectedElementRect.top - this.getHighlightPadding();
/*custom add*/
let customTopOffset = 0;
if (this.currentTourStep.customTopOffset) {

View File

@ -12,10 +12,6 @@ import { Subscription } from "rxjs";
placeholder="{{(placeholder? (placeholder | translate) : '') + (required ? ' *': '')}}"
(paste)="pasteWithoutFormatting($event)"></angular-editor>
<mat-icon *ngIf="form.value && editable" (click)="parentFormGroup.get(controlName).patchValue('')" class="clear">close</mat-icon>
<!-- <mat-form-field class="full-width editor">
<mat-label>{{(placeholder? (placeholder | translate) : '')}}</mat-label>
<textarea matInput [formControl]="form" rows="5"></textarea>
</mat-form-field> -->
</div>
`,
styleUrls: ['./rich-text-editor.component.scss'],
@ -68,10 +64,8 @@ export class RichTextEditorComponent implements OnInit, OnChanges, OnDestroy {
[
'fontSize',
'backgroundColor',
// 'customClasses',
'insertImage',
'insertVideo',
// 'removeFormat',
'toggleEditorMode'
],
[

View File

@ -1,7 +1,6 @@
export class PaginationService {
getPagination(groups, totalGroups: number, currentPage: number = 1, pageSize: number = 3) {
// calculate total pages
//let totalPages = Math.ceil(totalGroups / pageSize);
let totalPages = 0 ; //totalpages based on pages from xml, each group and section has each one page
groups.forEach(group => {

View File

@ -75,7 +75,6 @@
<!-- DatePicker -->
<mat-form-field class="col-12" *ngIf="fieldType === descriptionTemplateFieldTypeEnum.DATE_PICKER">
<!--(focus)="date.open()" (click)="date.open()"-->
<mat-label>{{placeHolder}}</mat-label>
<input matInput [placeholder]="placeHolder" class="table-input" [matDatepicker]="date" [formControl]="form" [required]="required">
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>

View File

@ -1,5 +1,4 @@
<div class="row" *ngIf="form.get('data')">
<!-- <h5 style="font-weight: bold" class="col-12">{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-LICENSES-TITLE' | translate}}</h5> -->
<mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multipleSelect')">
{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}}
</mat-checkbox>

View File

@ -46,7 +46,6 @@
</mat-option>
<mat-divider></mat-divider>
<mat-option [value]="descriptionTemplateFieldTypeEnum.UPLOAD">
<!-- <img src="/assets/images/editor/icons/text_area.svg" class="input_icon" alt="Upload icon">-->
<mat-icon class="input_icon" style="font-size: 14px; color: #129d99; display: inline-flex; align-items: center">upload</mat-icon>
{{enumUtils.toDescriptionTemplateFieldTypeString(descriptionTemplateFieldTypeEnum.UPLOAD)}}
</mat-option>

View File

@ -212,10 +212,6 @@ export class DescriptionTemplateEditorFieldComponent extends BaseComponent imple
}
this.clearVisibilityRulesValue();
// setTimeout(() => { //TODO
// this.showPreview = true;
// });
}

View File

@ -138,8 +138,7 @@ export class DescriptionTemplateEditorSectionFieldSetComponent implements OnInit
this._selectedFieldSetId = this.tocentry.id;
this.scroller.next(this.tocentry.id);
} else {//scroll on top
// this._scrollOnTop();
} else {
this.scroller.next(null);
}
}

View File

@ -70,10 +70,6 @@ export class DescriptionTemplateEditorRuleComponent implements OnInit {
return type == DescriptionTemplateFieldType.VALIDATION || type == DescriptionTemplateFieldType.DATASET_IDENTIFIER;;
}
targetValidation() {
//TODO
}
deleteRule(index) {
this.form.removeAt(index);
this.form.controls?.forEach(
@ -187,12 +183,10 @@ export class DescriptionTemplateEditorRuleComponent implements OnInit {
const result: OptionItem[] = [];
// parentIds.push(form.get('id').value);
const currentOptionItem: OptionItem = {
id: form.get('id').value,
type: type,
label: type === ToCEntryType.Field ? form.get('data').get('label').value : form.get('title').value,
// parentsIds: [form.get('id').value]
parentsIds: [...parentIds, form.get('id').value],
form: form,
hiddenBy: []

View File

@ -32,9 +32,6 @@
<mat-horizontal-stepper [linear]="!isFinalized" #stepper class="stepper" (selectionChange)="onMatStepperSelectionChange($event)" style="padding-left: 8px; padding-right: 15px;">
<!-- IMPORTANT TO BE !INVALID (WHEN THE TEMPLATE IS FINALIZED THE CONTORLS ARE DISABLED) -->
<!-- <ng-template matStepLabel>{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.GENERAL-INFO.TITLE' | translate}}
</ng-template> -->
<mat-step [label]="generalInfoStepperLabel" [completed]="(!formGroup.get('label').invalid && !formGroup.get('description').invalid && !formGroup.get('language').invalid)">
<div class="col-9">
<div class="col">

View File

@ -382,8 +382,6 @@ export class DescriptionTemplateEditorComponent extends BaseEditor<DescriptionTe
if (event.selectedIndex === (this.steps.length - 1)) {//preview selected
this.generatePreviewForm();
} else {
// this.formGroup = null;
}
this.formGroup.markAsUntouched();

View File

@ -49,7 +49,7 @@ export class DescriptionTemplateEditorResolver extends BaseEditorResolver {
[nameof<DescriptionTemplate>(x => x.definition), nameof<DescriptionTemplateDefinition>(x => x.pages), nameof<DescriptionTemplatePage>(x => x.sections), nameof<DescriptionTemplateSection>(x => x.title)].join('.'),
[nameof<DescriptionTemplate>(x => x.definition), nameof<DescriptionTemplateDefinition>(x => x.pages), nameof<DescriptionTemplatePage>(x => x.sections), nameof<DescriptionTemplateSection>(x => x.description)].join('.'),
[nameof<DescriptionTemplate>(x => x.definition), nameof<DescriptionTemplateDefinition>(x => x.pages), nameof<DescriptionTemplatePage>(x => x.sections), nameof<DescriptionTemplateSection>(x => x.ordinal)].join('.'),
[nameof<DescriptionTemplate>(x => x.definition), nameof<DescriptionTemplateDefinition>(x => x.pages), nameof<DescriptionTemplatePage>(x => x.sections), nameof<DescriptionTemplateSection>(x => x.sections)].join('.'), // TODO: it is recursive here
[nameof<DescriptionTemplate>(x => x.definition), nameof<DescriptionTemplateDefinition>(x => x.pages), nameof<DescriptionTemplatePage>(x => x.sections), nameof<DescriptionTemplateSection>(x => x.sections)].join('.'),
[nameof<DescriptionTemplate>(x => x.definition), nameof<DescriptionTemplateDefinition>(x => x.pages), nameof<DescriptionTemplatePage>(x => x.sections), nameof<DescriptionTemplateSection>(x => x.fieldSets), nameof<DescriptionTemplateFieldSet>(x => x.id)].join('.'),
[nameof<DescriptionTemplate>(x => x.definition), nameof<DescriptionTemplateDefinition>(x => x.pages), nameof<DescriptionTemplatePage>(x => x.sections), nameof<DescriptionTemplateSection>(x => x.fieldSets), nameof<DescriptionTemplateFieldSet>(x => x.ordinal)].join('.'),

View File

@ -1,6 +1,5 @@
import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { IsActive } from '@app/core/common/enum/is-active.enum';
import { LockTargetType } from '@app/core/common/enum/lock-target-type';
import { LockFilter } from '@app/core/query/lock.lookup';
import { UserService } from '@app/core/services/user/user.service';
@ -90,9 +89,6 @@ export class LockListingFiltersComponent extends BaseComponent implements OnInit
private _computeAppliedFilters(filters: LockListingFilters): number {
let count = 0;
// if (filters?.isActive) {
// count++
// }
return count;
}

View File

@ -33,7 +33,6 @@ export class LanguageListingComponent extends BaseListingComponent<Language, Lan
userSettingsKey = { key: 'LanguageListingUserSettings' };
propertiesAvailableForOrder: ColumnDefinition[];
// @ViewChild('LanguageStatus', { static: true }) LanguageStatus?: TemplateRef<any>;
@ViewChild('actions', { static: true }) actions?: TemplateRef<any>;
@ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent;

View File

@ -536,22 +536,21 @@ export class PlanBlueprintEditorComponent extends BaseEditor<PlanBlueprintEditor
checkValidity() {
this.formService.touchAllFormFields(this.formGroup);
// if (!this.isFormValid()) { return false; }
let errorMessages = [];
if (!this.hasTitle()) {
errorMessages.push("Title should be set.");
errorMessages.push(this.language.instant('PLAN-BLUEPRINT-EDITOR.FORM-VALIDATION-DISPLAY-DIALOG.TITLE-REQUIRED'));
}
if (!this.hasDescription()) {
errorMessages.push("Description should be set.");
errorMessages.push(this.language.instant('PLAN-BLUEPRINT-EDITOR.FORM-VALIDATION-DISPLAY-DIALOG.DESCRIPTION-REQUIRED'));
}
if (!this.hasLanguage()) {
errorMessages.push("Language should be set.");
errorMessages.push(this.language.instant('PLAN-BLUEPRINT-EDITOR.FORM-VALIDATION-DISPLAY-DIALOG.LANGUAGE-REQUIRED'));
}
if (!this.hasAccess()) {
errorMessages.push("Access should be set.");
errorMessages.push(this.language.instant('PLAN-BLUEPRINT-EDITOR.FORM-VALIDATION-DISPLAY-DIALOG.ACCESS-REQUIRED'));
}
if (!this.hasDescriptionTemplates()) {
errorMessages.push("At least one section should have description templates.");
errorMessages.push(this.language.instant('PLAN-BLUEPRINT-EDITOR.FORM-VALIDATION-DISPLAY-DIALOG.DESCRIPTION-TEMPLATES-REQUIRED'));
}
if (errorMessages.length > 0) {
this.showValidationErrorsDialog(undefined, errorMessages);

View File

@ -33,7 +33,6 @@ export class PrefillingSourceListingComponent extends BaseListingComponent<Prefi
userSettingsKey = { key: 'PrefillingSourceListingUserSettings' };
propertiesAvailableForOrder: ColumnDefinition[];
// @ViewChild('PrefillingSourceStatus', { static: true }) PrefillingSourceStatus?: TemplateRef<any>;
@ViewChild('actions', { static: true }) actions?: TemplateRef<any>;
@ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent;

View File

@ -32,9 +32,7 @@ export class ReferenceTypeListingComponent extends BaseListingComponent<Referenc
publish = false;
userSettingsKey = { key: 'ReferenceTypeListingUserSettings' };
propertiesAvailableForOrder: ColumnDefinition[];
//ReferenceTypeStatuses = ReferenceTypeStatus;
//@ViewChild('ReferenceTypeStatus', { static: true }) ReferenceTypeStatus?: TemplateRef<any>;
@ViewChild('actions', { static: true }) actions?: TemplateRef<any>;
@ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent;

View File

@ -33,7 +33,6 @@ export class TenantListingComponent extends BaseListingComponent<Tenant, TenantL
userSettingsKey = { key: 'TenantListingUserSettings' };
propertiesAvailableForOrder: ColumnDefinition[];
// @ViewChild('TenantStatus', { static: true }) TenantStatus?: TemplateRef<any>;
@ViewChild('actions', { static: true }) actions?: TemplateRef<any>;
@ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent;

View File

@ -113,7 +113,6 @@ export class AnnotationDialogComponent extends BaseComponent {
}
replyThread(threadId: Guid) {
// if (!this.threadReplyTexts[threadId.toString()] || this.threadReplyTexts[threadId.toString()].length === 0) { return; }
this.formService.removeAllBackEndErrors(this.threadReplyTextsFG[threadId.toString()]);
this.formService.touchAllFormFields(this.threadReplyTextsFG[threadId.toString()]);
if (!this.isFormValid(this.threadReplyTextsFG[threadId.toString()])) {
@ -178,7 +177,6 @@ export class AnnotationDialogComponent extends BaseComponent {
this.resetFormGroup();
this.comments = data.items.sort((a1, a2) => new Date(a2.timeStamp).getTime() - new Date(a1.timeStamp).getTime());
this.comments.forEach(element => {
// this.threadReplyTextsFG.addControl(element.id.toString(), new FormControl(null));
this.threadReplyTextsFG[element.threadId.toString()] = this.formBuilder.group({ replyText: new FormControl(null, [Validators.required]) });
this.annotationsPerThread[element.threadId.toString()] = data.items.filter(x => x.threadId === element.threadId && x.id !== element.id).sort((a1, a2) => new Date(a1.timeStamp).getTime() - new Date(a2.timeStamp).getTime());
this.parentAnnotationsPerThread[element.threadId.toString()] = data.items.filter(x => x.threadId === element.threadId && x.id === element.id)[0];
@ -257,11 +255,6 @@ export class AnnotationDialogComponent extends BaseComponent {
this.dialogRef.close(this.changesMade);
}
startWizard() { // not used
this.router.navigate([this.routerUtils.generateUrl('/plans/new')]);
this.close();
}
showReplies(threadId: string): void {
this.showRepliesPerThread[threadId] = true;
}

View File

@ -5,7 +5,6 @@ import { MergeEmailConfirmation } from './merge-email-confirmation/merge-email-c
import { UnlinkEmailConfirmation } from './unlink-email-confirmation/unlink-email-confirmation.component';
import { AuthGuard } from '@app/core/auth-guard.service';
import { UserInviteConfirmation } from './user-invite-confirmation/user-invite-confirmation.component';
// import { PostLoginComponent } from './post-login/post-login.component';
const routes: Routes = [
{ path: '', component: LoginComponent },
@ -14,10 +13,6 @@ const routes: Routes = [
component: MergeEmailConfirmation,
canActivate: [AuthGuard]
},
// {
// path: 'post',
// component: PostLoginComponent
// },
{ path: 'unlink/confirmation/:token', component: UnlinkEmailConfirmation },
{ path: 'invitation/confirmation/:token', component: UserInviteConfirmation },

View File

@ -16,7 +16,6 @@ export class LogoutComponent implements OnInit {
this.authService.clear();
this.keycloak.logout(location.origin).then(() => {
localStorage.clear();
// this.router.navigate(['./'], { replaceUrl: true });
});
}
}

View File

@ -31,7 +31,7 @@ export class DescriptionCopyDialogComponent {
sections: PlanBlueprintDefinitionSection[] = [];
descriptionDescriptionTemplateLabel: String;
planAutoCompleteConfiguration: SingleAutoCompleteConfiguration = { //TODO: add filter to only get plans that have connection with the same Description Template group.
planAutoCompleteConfiguration: SingleAutoCompleteConfiguration = {
initialItems: (data?: any) => this.planService.query(this.buildPlanLookup(null,null,null, this.planDescriptionTemplateLookup)).pipe(map(x => x.items)),
filterFn: (searchQuery: string, data?: any) => this.planService.query(this.buildPlanLookup(searchQuery, null, null, this.planDescriptionTemplateLookup)).pipe(map(x => x.items)),
getSelectedItem: (selectedItem: any) => this.planService.query(this.buildPlanLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])),

View File

@ -501,7 +501,6 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
const errors: string[] = [];
Object.keys(formControl.errors).forEach(key => {
if (key === 'required') {
// errors.push(this.language.instant(name + ": " + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.REQUIRED')));
if (name == 'label') errors.push(this.language.instant(this.language.instant('DESCRIPTION-EDITOR.BASE-INFO.FIELDS.TITLE') + ": " + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.REQUIRED')));
else if (name == 'descriptionTemplateId') errors.push(this.language.instant(this.language.instant('DESCRIPTION-EDITOR.BASE-INFO.FIELDS.DESCRIPTION-TEMPLATE') + ": " + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.REQUIRED')));
}
@ -539,7 +538,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
//
isDirty() {
return this.formGroup.dirty; //TODO: check if needed //&& this.hasChanges; // do we need this.formGroup.dirty
return this.formGroup.dirty;
}
isPristine() {
@ -697,7 +696,6 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
if (section.sections) {
const subNestedSectionIds: string[] = section.sections.flatMap((subsection: DescriptionTemplateSection) => this.getNestedSectionIdsByField(subsection, fieldSetId))
if (subNestedSectionIds.length > 0) return [section.id, ...subNestedSectionIds];
// return [section.id, ...section.sections.flatMap((subsection: DescriptionTemplateSection) => this.getNestedSectionIdsByField(subsection, fieldSetId))];
}
else if (section.fieldSets.find(fieldSet => fieldSet.id == fieldSetId)) return [section.id];

View File

@ -241,7 +241,7 @@ export class DescriptionFormFieldComponent extends BaseComponent implements OnIn
let messages: string[] = [];
if (this.filesToUpload.length == 0) {
messages.push(this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.NO-FILES-SELECTED')); // fix
messages.push(this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.NO-FILES-SELECTED'));
return;
} else {
let fileToUpload = this.filesToUpload[0];
@ -253,9 +253,9 @@ export class DescriptionFormFieldComponent extends BaseComponent implements OnIn
this.upload();
} else {
this.filesToUpload = null;
messages.push(this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.LARGE-FILE-OR-UNACCEPTED-TYPE')); // fix
messages.push(this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-UPLOAD-MAX-FILE-SIZE', { 'maxfilesize': data.maxFileSizeInMB })); // fix FIELD-UPLOAD-MAX-FILE-SIZE
messages.push(this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.ACCEPTED-FILE-TRANSFOMER') + data.types.map(type => type.value).join(", ")); // fix
messages.push(this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.LARGE-FILE-OR-UNACCEPTED-TYPE'));
messages.push(this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-UPLOAD-MAX-FILE-SIZE', { 'maxfilesize': data.maxFileSizeInMB }));
messages.push(this.language.instant('DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.FIELD.FIELDS.ACCEPTED-FILE-TRANSFOMER') + data.types.map(type => type.value).join(", "));
}
if (messages && messages.length > 0) {

View File

@ -27,10 +27,6 @@ export class DescriptionFormSectionComponent extends BaseComponent implements On
@Input() path: string;
@Input() descriptionId: Guid;
@Input() planUsers: PlanUser[] = [];
// @Input() descriptionTemplateId: String;
// @Input() form: UntypedFormGroup;
@Input() tocentry: ToCEntry;
@Input() pathName: string;
@Input() linkToScroll: LinkToScroll;

View File

@ -7,7 +7,6 @@ export interface ToCEntry {
subEntriesType: ToCEntryType;
subEntries: ToCEntry[];
type: ToCEntryType;
// form: AbstractControl;
numbering: string;
ordinal: number;
hidden?: boolean;

View File

@ -222,7 +222,6 @@ export class TableOfContentsComponent extends BaseComponent implements OnInit, O
});
}
return {
// form: form,
id: item.id,
label: item.title,
numbering: '',
@ -239,7 +238,6 @@ export class TableOfContentsComponent extends BaseComponent implements OnInit, O
if (!item) return null;
return {
// form: form,
id: item.id,
label: item.title,
numbering: 's',

View File

@ -27,7 +27,7 @@
</button>
</div>
</div>
<div *ngIf="hasLoadedListingItems && (hasListingItems || hasFilters)"
<div *ngIf="hasLoadedListingItems && (hasListingItems || hasFilters) && !isPublic"
class="filter-btn" [style.right]="dialog.getDialogById('filters') ? '446px' : '0px'" [style.width]="listingItems.length > 2 ? '57px' : '37px'" (click)="openFiltersDialog()">
<button mat-raised-button class="p-0" [matBadge]="filtersCount" [matBadgeHidden]="!hasFilters" matBadgePosition="before">
<mat-icon class="mr-4 filter-icon">filter_alt</mat-icon>

View File

@ -163,9 +163,11 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
this.onPageLoad({ offset: this.lookup.page.offset / this.lookup.page.size } as PageLoadEvent);
});
if (!this.isPublic){
this._loadUserTenants().pipe(takeUntil(this._destroyed)).subscribe( tenants => {
this.tenants = tenants;
});
}
this.formGroup.get('like').valueChanges
.pipe(takeUntil(this._destroyed), debounceTime(500))

View File

@ -7,7 +7,6 @@ const routes: Routes = [
{
path: '',
component: DescriptionListingComponent,
// canActivate: [AuthGuard],
data: {
breadcrumb: true
},

View File

@ -85,11 +85,9 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
} else if (this.description.status === DescriptionStatus.Draft) {
this.isDraft = true;
this.isDeleted = false;
this.setIsUserOwner();
} else {
this.isDraft = false;
this.isDeleted = false;
this.setIsUserOwner();
}
this.canDelete = (this.authService.hasPermission(AppPermission.DeleteDescription) ||
@ -106,14 +104,6 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
return this.tenants?.find(t => t?.id == id)?.name;
}
setIsUserOwner() {
if (this.description) {
const principalId: string = this.authService.userId()?.toString();
//TODO: add user to description objects
//if (principalId) this.isUserOwner = !!this.description.users.find(x => (x.role === Role.Owner) && (principalId === x.id));
}
}
isUserPlanRelated() {
const principalId: Guid = this.authService.userId();
return this.description.plan.planUsers?.some(x => (x.user.id === principalId));
@ -134,8 +124,6 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
openShareDialog() {
// TODO: This is a shared component. Put it in a seperate module.
const dialogRef = this.dialog.open(PlanInvitationDialogComponent, {
// height: '250px',
// width: '700px',
autoFocus: false,
restoreFocus: false,
data: {

View File

@ -43,17 +43,6 @@ export class LanguageComponent extends BaseComponent implements OnInit {
if (this.isAuthenticated()) {
const langMap = new Map<string, string>();
langMap.set('language', selectedLanguage.value);
//TODO: refactor - save language selection to user profile
// this.userService.updateUserSettings({ language: this.languages.find(lang => lang === selectedLanguage.value) })
// .pipe(takeUntil(this._destroyed))
// .subscribe((response) => {
// this.languageService.changeLanguage(selectedLanguage.value);
// this.authentication.refresh()
// .pipe(takeUntil(this._destroyed))
// .subscribe(innerResponse => { this.router.navigateByUrl(this.router.url); });
// },
// error => {
// });
this.languageService.changeLanguage(selectedLanguage.value);
this.router.navigateByUrl(this.router.url);
} else {

View File

@ -14,7 +14,7 @@
<div *ngIf="hasLoadedListingItems && (hasListingItems || hasFilters)" class="col-12">
<app-navigation-breadcrumb />
</div>
<div *ngIf="hasLoadedListingItems && (hasListingItems || hasFilters)" class="filter-btn" [style.right]="dialog.getDialogById('filters') ? '446px' : '0px'" [style.width]="listingItems.length > 2 ? '57px' : '37px'" (click)="openFiltersDialog()">
<div *ngIf="hasLoadedListingItems && (hasListingItems || hasFilters) && !isPublic" class="filter-btn" [style.right]="dialog.getDialogById('filters') ? '446px' : '0px'" [style.width]="listingItems.length > 2 ? '57px' : '37px'" (click)="openFiltersDialog()">
<button mat-raised-button class="p-0" [matBadge]="filtersCount" [matBadgeHidden]="!hasFilters" matBadgePosition="before">
<mat-icon class="mr-4 filter-icon">filter_alt</mat-icon>
</button>

View File

@ -152,9 +152,11 @@ export class PlanListingComponent extends BaseListingComponent<BasePlan, PlanLoo
this.onPageLoad({ offset: this.lookup.page.offset / this.lookup.page.size } as PageLoadEvent);
});
if (!this.isPublic){
this._loadUserTenants().pipe(takeUntil(this._destroyed)).subscribe( tenants => {
this.tenants = tenants;
});
}
this.formGroup.get('like').valueChanges
.pipe(takeUntil(this._destroyed), debounceTime(500))
@ -273,10 +275,6 @@ export class PlanListingComponent extends BaseListingComponent<BasePlan, PlanLoo
this.filterChanged(this.lookup, true);
}
openShareDialog(rowId: any, rowName: any) {
//TODO: add this
}
openFiltersDialog(): void {
let dialogRef = this.dialog.open(PlanFilterDialogComponent, {
width: '456px',

View File

@ -6,7 +6,6 @@ const routes: Routes = [
{
path: '',
component: PlanListingComponent,
// canActivate: [AuthGuard],
data: {
breadcrumb: true
},

View File

@ -116,7 +116,7 @@
<div class="row mb-4">
<ng-container *ngFor="let description of plan.descriptions">
<div class="col-12 col-lg-7 mt-1">
<a class="w-100 description" [routerLink]="isPublicView ? this.routerUtils.generateUrl(['/descriptions/overview/public/', description.id]) : this.routerUtils.generateUrl(['/descriptions/overview/' + description.id])" target="_blank">
<a class="w-100 description" [routerLink]="isPublicView ? this.routerUtils.generateUrl(['/explore-descriptions/overview/public/', description.id]) : this.routerUtils.generateUrl(['/descriptions/overview/' + description.id])" target="_blank">
<button class="w-100" [ngClass]="{'plan-btn': description.status === descriptionStatusEnum.Draft, 'plan-finalized-btn': description.status === descriptionStatusEnum.Finalized}">
<div matTooltip="{{ description.label }}" class="d-flex align-items-center justify-content-between">
<div class="description-btn-label">{{ description.label }}</div>

View File

@ -441,8 +441,6 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
openShareDialog(rowId: any, rowName: any) {
const dialogRef = this.dialog.open(PlanInvitationDialogComponent, {
// height: '250px',
// width: '700px',
autoFocus: false,
restoreFocus: false,
data: {

View File

@ -780,7 +780,7 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
//
//
public isDirty(): boolean {
return this.formGroup && this.formGroup.dirty; //&& this.hasChanges;
return this.formGroup && this.formGroup.dirty;
}
getLanguageInfos(): LanguageInfo[] {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -1627,6 +1627,13 @@
"LOCKED-DIALOG": {
"TITLE": "Plan Blueprint is locked",
"MESSAGE": "Somebody else is modifying the Plan Blueprint at this moment. You may view the Plan Blueprint but you cannot make any changes. If you would like to modify it please come back later."
},
"FORM-VALIDATION-DISPLAY-DIALOG": {
"TITLE-REQUIRED": "Title should be set.",
"DESCRIPTION-REQUIRED": "Description should be set.",
"LANGUAGE-REQUIRED": "Language should be set.",
"ACCESS-REQUIRED": "Access should be set.",
"DESCRIPTION-TEMPLATES-REQUIRED": "At least one section should have description templates."
}
},
"PLAN-EDITOR": {

View File

@ -16,14 +16,6 @@ export class StatusCodeInterceptor extends BaseInterceptor {
type: InterceptorType;
interceptRequest(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent <any>> {
return next.handle(req).pipe(tap(event => { }, err => {
// if (err.status === 480) {
// this.router.navigate(['confirmation']);
// }
// const error: HttpError = this.httpErrorHandlingService.getError(err);
// if (error.statusCode === 403 && error.errorCode === 103) {
// this.authService.selectedTenant('default');
// this.router.navigate(['/']);
// }
}));
}

View File

@ -55,7 +55,6 @@ export class ExpandableSearchFieldComponent extends BaseComponent implements OnI
protected a$ = this.subject$.asObservable().pipe(
debounceTime(200),
// delayWhen(x => interval( x ? 0: 3000).pipe(take(1))),
takeUntil(this._destroyed),
shareReplay(),
startWith(false)

View File

@ -7,10 +7,8 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<!-- <title>Data Management Plans Creator</title> -->
<base href="/">
<meta name="csrf-token" content="2c64def7de30197c40276fe1a7ea874ca8871f70be7d7dc3305465a4d5c565e4">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1"> -->
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script src="//connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript" src="//platform.linkedin.com/in.js"></script>

View File

@ -121,7 +121,5 @@ export class InAppNotificationEditorComponent extends BaseComponent implements O
}
onCallbackSuccess(data?: any): void {
// this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
// this.router.navigate(['/mine-notifications']);
}
}

View File

@ -1,13 +1,12 @@
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { HttpErrorResponse } from '@angular/common/http';
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Component, OnInit } from '@angular/core';
import { AuthService } from '@app/core/services/auth/auth.service';
import { LoggingService } from '@app/core/services/logging/logging-service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { BaseComponent } from '@common/base/base.component';
import { FormService } from '@common/forms/form-service';
import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
import { TranslateService } from '@ngx-translate/core';
import { NotificationContactType } from '@notification-service/core/enum/notification-contact-type';
import { NotificationTrackingProcess } from '@notification-service/core/enum/notification-tracking-process.enum';
@ -40,7 +39,6 @@ export class UserProfileNotifierListEditorComponent extends BaseComponent implem
private formService: FormService,
private logger: LoggingService,
public notificationServiceEnumUtils: NotificationServiceEnumUtils,
// private totpService: TotpService
) {
super();
}