add description status logic
This commit is contained in:
parent
99023ed159
commit
4dc0927140
|
@ -39,6 +39,10 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
|
|||
private DescriptionStatus status;
|
||||
public static final String _status = "status";
|
||||
|
||||
@Column(name = "status_id", nullable = true)
|
||||
private UUID statusId;
|
||||
public static final String _statusId = "statusId";
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
|
@ -187,5 +191,13 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
|
|||
public void setDescriptionTemplateId(UUID descriptionTemplateId) {
|
||||
this.descriptionTemplateId = descriptionTemplateId;
|
||||
}
|
||||
|
||||
public UUID getStatusId() {
|
||||
return statusId;
|
||||
}
|
||||
|
||||
public void setStatusId(UUID statusId) {
|
||||
this.statusId = statusId;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.opencdmp.model;
|
||||
|
||||
import org.opencdmp.commons.enums.DescriptionStatus;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
@ -15,7 +14,7 @@ public class PublicDescription {
|
|||
|
||||
public static final String _label = "label";
|
||||
|
||||
private DescriptionStatus status;
|
||||
private PublicDescriptionStatus status;
|
||||
|
||||
public static final String _status = "status";
|
||||
|
||||
|
@ -65,11 +64,11 @@ public class PublicDescription {
|
|||
}
|
||||
|
||||
|
||||
public DescriptionStatus getStatus() {
|
||||
public PublicDescriptionStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(DescriptionStatus status) {
|
||||
public void setStatus(PublicDescriptionStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package org.opencdmp.model;
|
||||
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PublicDescriptionStatus {
|
||||
|
||||
public final static String _id = "id";
|
||||
private UUID id;
|
||||
|
||||
public final static String _name = "name";
|
||||
private String name;
|
||||
|
||||
public final static String _internalStatus = "internalStatus";
|
||||
private org.opencdmp.commons.enums.DescriptionStatus internalStatus;
|
||||
|
||||
public UUID getId() { return this.id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public String getName() { return this.name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
|
||||
public org.opencdmp.commons.enums.DescriptionStatus getInternalStatus() { return this.internalStatus; }
|
||||
public void setInternalStatus(org.opencdmp.commons.enums.DescriptionStatus internalStatus) { this.internalStatus = internalStatus; }
|
||||
}
|
|
@ -10,10 +10,8 @@ import gr.cite.tools.logging.LoggerService;
|
|||
import org.opencdmp.authorization.AuthorizationFlags;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
import org.opencdmp.data.DescriptionEntity;
|
||||
import org.opencdmp.model.PublicDescription;
|
||||
import org.opencdmp.model.PublicDescriptionTemplate;
|
||||
import org.opencdmp.model.PublicPlan;
|
||||
import org.opencdmp.model.PublicPlanDescriptionTemplate;
|
||||
import org.opencdmp.model.*;
|
||||
import org.opencdmp.query.DescriptionStatusQuery;
|
||||
import org.opencdmp.query.DescriptionTemplateQuery;
|
||||
import org.opencdmp.query.PlanDescriptionTemplateQuery;
|
||||
import org.opencdmp.query.PlanQuery;
|
||||
|
@ -66,12 +64,15 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
|
|||
FieldSet planFields = fields.extractPrefixed(this.asPrefix(PublicDescription._plan));
|
||||
Map<UUID, PublicPlan> planItemsMap = this.collectPlans(planFields, data);
|
||||
|
||||
FieldSet descriptionStatusFields = fields.extractPrefixed(this.asPrefix(PublicDescription._status));
|
||||
Map<UUID, PublicDescriptionStatus> descriptionStatusItemsMap = this.collectDescriptionStatuses(descriptionStatusFields, data);
|
||||
|
||||
List<PublicDescription> models = new ArrayList<>();
|
||||
for (DescriptionEntity d : data) {
|
||||
PublicDescription m = new PublicDescription();
|
||||
if (fields.hasField(this.asIndexer(PublicDescription._id))) m.setId(d.getId());
|
||||
if (fields.hasField(this.asIndexer(PublicDescription._label))) m.setLabel(d.getLabel());
|
||||
if (fields.hasField(this.asIndexer(PublicDescription._status))) m.setStatus(d.getStatus());
|
||||
if (!descriptionStatusFields.isEmpty() && descriptionStatusItemsMap != null && descriptionStatusItemsMap.containsKey(d.getStatusId())) m.setStatus(descriptionStatusItemsMap.get(d.getStatusId()));
|
||||
if (fields.hasField(this.asIndexer(PublicDescription._description))) m.setDescription(d.getDescription());
|
||||
if (fields.hasField(this.asIndexer(PublicDescription._createdAt))) m.setCreatedAt(d.getCreatedAt());
|
||||
if (fields.hasField(this.asIndexer(PublicDescription._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
|
||||
|
@ -177,4 +178,34 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
|
|||
return itemMap;
|
||||
}
|
||||
|
||||
private Map<UUID, PublicDescriptionStatus> collectDescriptionStatuses(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
|
||||
if (fields.isEmpty() || data.isEmpty())
|
||||
return null;
|
||||
this.logger.debug("checking related - {}", PublicDescriptionStatus.class.getSimpleName());
|
||||
|
||||
Map<UUID, PublicDescriptionStatus> itemMap;
|
||||
if (!fields.hasOtherField(this.asIndexer(PublicDescriptionStatus._id))) {
|
||||
itemMap = this.asEmpty(
|
||||
data.stream().map(DescriptionEntity::getDescriptionTemplateId).distinct().collect(Collectors.toList()),
|
||||
x -> {
|
||||
PublicDescriptionStatus item = new PublicDescriptionStatus();
|
||||
item.setId(x);
|
||||
return item;
|
||||
},
|
||||
PublicDescriptionStatus::getId);
|
||||
} else {
|
||||
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(PublicDescriptionStatus._id);
|
||||
DescriptionStatusQuery q = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()));
|
||||
itemMap = this.builderFactory.builder(PublicDescriptionStatusBuilder.class).authorize(this.authorize).asForeignKey(q, clone, PublicDescriptionStatus::getId);
|
||||
}
|
||||
if (!fields.hasField(PublicDescriptionStatus._id)) {
|
||||
itemMap.forEach((id, item) -> {
|
||||
if (item != null)
|
||||
item.setId(null);
|
||||
});
|
||||
}
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
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.convention.ConventionService;
|
||||
|
||||
|
||||
import org.opencdmp.data.DescriptionStatusEntity;
|
||||
import org.opencdmp.model.PublicDescriptionStatus;
|
||||
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 PublicDescriptionStatusBuilder extends BaseBuilder<PublicDescriptionStatus, DescriptionStatusEntity> {
|
||||
|
||||
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||
@Autowired
|
||||
public PublicDescriptionStatusBuilder(
|
||||
ConventionService conventionService) {
|
||||
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicDescriptionStatusBuilder.class)));
|
||||
}
|
||||
|
||||
public PublicDescriptionStatusBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
||||
this.authorize = values;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PublicDescriptionStatus> build(FieldSet fields, List<DescriptionStatusEntity> 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<PublicDescriptionStatus> models = new ArrayList<>();
|
||||
for (DescriptionStatusEntity d : data) {
|
||||
PublicDescriptionStatus m = new PublicDescriptionStatus();
|
||||
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._id))) m.setId(d.getId());
|
||||
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._name))) m.setName(d.getName());
|
||||
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._internalStatus))) m.setInternalStatus(d.getInternalStatus());
|
||||
models.add(m);
|
||||
}
|
||||
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
|
||||
return models;
|
||||
}
|
||||
}
|
|
@ -26,10 +26,12 @@ import org.opencdmp.model.builder.DescriptionTagBuilder;
|
|||
import org.opencdmp.model.builder.PlanDescriptionTemplateBuilder;
|
||||
import org.opencdmp.model.builder.UserBuilder;
|
||||
import org.opencdmp.model.builder.descriptionreference.DescriptionReferenceBuilder;
|
||||
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
||||
import org.opencdmp.model.builder.descriptiontemplate.DescriptionTemplateBuilder;
|
||||
import org.opencdmp.model.builder.plan.PlanBuilder;
|
||||
import org.opencdmp.model.description.Description;
|
||||
import org.opencdmp.model.descriptionreference.DescriptionReference;
|
||||
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||
import org.opencdmp.model.descriptiontemplate.DescriptionTemplate;
|
||||
import org.opencdmp.model.plan.Plan;
|
||||
import org.opencdmp.model.user.User;
|
||||
|
@ -85,6 +87,9 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
|||
if (fields == null || data == null || fields.isEmpty())
|
||||
return new ArrayList<>();
|
||||
|
||||
FieldSet statusFields = fields.extractPrefixed(this.asPrefix(Description._status));
|
||||
Map<UUID, DescriptionStatus> statusItemsMap = this.collectDescriptionStatuses(statusFields, data);
|
||||
|
||||
FieldSet planDescriptionTemplateFields = fields.extractPrefixed(this.asPrefix(Description._planDescriptionTemplate));
|
||||
Map<UUID, PlanDescriptionTemplate> planDescriptionTemplateItemsMap = this.collectPlanDescriptionTemplates(planDescriptionTemplateFields, data);
|
||||
|
||||
|
@ -116,7 +121,7 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
|||
if (fields.hasField(this.asIndexer(Description._id))) m.setId(d.getId());
|
||||
if (fields.hasField(this.asIndexer(Description._tenantId))) m.setTenantId(d.getTenantId());
|
||||
if (fields.hasField(this.asIndexer(Description._label))) m.setLabel(d.getLabel());
|
||||
if (fields.hasField(this.asIndexer(Description._status))) m.setStatus(d.getStatus());
|
||||
if (!statusFields.isEmpty() && statusItemsMap != null && statusItemsMap.containsKey(d.getStatusId())) m.setStatus(statusItemsMap.get(d.getStatusId()));
|
||||
if (fields.hasField(this.asIndexer(Description._description))) m.setDescription(d.getDescription());
|
||||
if (fields.hasField(this.asIndexer(Description._createdAt))) m.setCreatedAt(d.getCreatedAt());
|
||||
if (fields.hasField(this.asIndexer(Description._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
|
||||
|
@ -143,6 +148,36 @@ public class DescriptionBuilder extends BaseBuilder<Description, DescriptionEnti
|
|||
return models;
|
||||
}
|
||||
|
||||
private Map<UUID, DescriptionStatus> collectDescriptionStatuses(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
|
||||
if (fields.isEmpty() || data.isEmpty())
|
||||
return null;
|
||||
this.logger.debug("checking related - {}", DescriptionStatus.class.getSimpleName());
|
||||
|
||||
Map<UUID, DescriptionStatus> itemMap;
|
||||
if (!fields.hasOtherField(this.asIndexer(DescriptionStatus._id))) {
|
||||
itemMap = this.asEmpty(
|
||||
data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()),
|
||||
x -> {
|
||||
DescriptionStatus item = new DescriptionStatus();
|
||||
item.setId(x);
|
||||
return item;
|
||||
},
|
||||
DescriptionStatus::getId);
|
||||
} else {
|
||||
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(DescriptionStatus._id);
|
||||
DescriptionStatusQuery q = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()));
|
||||
itemMap = this.builderFactory.builder(DescriptionStatusBuilder.class).authorize(this.authorize).asForeignKey(q, clone, DescriptionStatus::getId);
|
||||
}
|
||||
if (!fields.hasField(DescriptionStatus._id)) {
|
||||
itemMap.forEach((id, item) -> {
|
||||
if (item != null)
|
||||
item.setId(null);
|
||||
});
|
||||
}
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
private Map<UUID, User> collectUsers(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
|
||||
if (fields.isEmpty() || data.isEmpty())
|
||||
return null;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.opencdmp.model.description;
|
||||
|
||||
import org.opencdmp.commons.enums.DescriptionStatus;
|
||||
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||
import org.opencdmp.commons.enums.IsActive;
|
||||
import org.opencdmp.model.*;
|
||||
import org.opencdmp.model.descriptionreference.DescriptionReference;
|
||||
|
|
|
@ -30,7 +30,7 @@ public class DescriptionToPublicApiDatasetMapper {
|
|||
model.setDescription(description.getDescription());
|
||||
model.setReference("");
|
||||
model.setUri("");
|
||||
model.setStatus(description.getStatus());
|
||||
// TODO status model.setStatus(description.getStatus());
|
||||
|
||||
model.setDmp(dmp);
|
||||
model.setDatasetProfileDefinition(descriptionTemplateToPublicApiDatasetProfileMapper.toPublicModel(description.getDescriptionTemplate()));
|
||||
|
|
|
@ -46,9 +46,9 @@ public class DescriptionPersist {
|
|||
|
||||
public static final String _descriptionTemplateId = "descriptionTemplateId";
|
||||
|
||||
private DescriptionStatus status;
|
||||
private UUID statusId;
|
||||
|
||||
public static final String _status = "status";
|
||||
public static final String _statusId = "statusId";
|
||||
|
||||
private String description;
|
||||
|
||||
|
@ -97,12 +97,12 @@ public class DescriptionPersist {
|
|||
this.planDescriptionTemplateId = planDescriptionTemplateId;
|
||||
}
|
||||
|
||||
public DescriptionStatus getStatus() {
|
||||
return this.status;
|
||||
public UUID getStatusId() {
|
||||
return statusId;
|
||||
}
|
||||
|
||||
public void setStatus(DescriptionStatus status) {
|
||||
this.status = status;
|
||||
public void setStatusId(UUID statusId) {
|
||||
this.statusId = statusId;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
|
@ -178,16 +178,19 @@ public class DescriptionPersist {
|
|||
DescriptionTemplateEntity descriptionTemplate = null;
|
||||
PlanEntity planEntity = null;
|
||||
PlanBlueprintEntity planBlueprintEntity = null;
|
||||
DescriptionStatusEntity statusEntity = null;
|
||||
try {
|
||||
descriptionTemplate = this.isValidGuid(item.getDescriptionTemplateId()) ? this.entityManager.find(DescriptionTemplateEntity.class, item.getDescriptionTemplateId(), true) : null;
|
||||
planEntity = this.isValidGuid(item.getPlanId()) ? this.entityManager.find(PlanEntity.class, item.getPlanId(), true) : null;
|
||||
planBlueprintEntity = planEntity == null ? null : this.entityManager.find(PlanBlueprintEntity.class, planEntity.getBlueprintId());
|
||||
statusEntity = this.isValidGuid(item.getStatusId()) ? this.entityManager.find(DescriptionStatusEntity.class, item.getStatusId(), true) : null;
|
||||
|
||||
} catch (InvalidApplicationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
DefinitionEntity definition = descriptionTemplate == null ? null : this.xmlHandlingService.fromXmlSafe(DefinitionEntity.class, descriptionTemplate.getDefinition());
|
||||
PlanBlueprintEntity finalPlanBlueprintEntity = planBlueprintEntity;
|
||||
DescriptionStatusEntity finalStatusEntity = statusEntity;
|
||||
return Arrays.asList(
|
||||
this.spec()
|
||||
.iff(() -> this.isValidGuid(item.getId()))
|
||||
|
@ -214,21 +217,22 @@ public class DescriptionPersist {
|
|||
.must(() -> this.isValidGuid(item.getPlanDescriptionTemplateId()))
|
||||
.failOn(DescriptionPersist._planDescriptionTemplateId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._planDescriptionTemplateId}, LocaleContextHolder.getLocale())),
|
||||
this.spec()
|
||||
.must(() -> !this.isNull(item.getStatus()))
|
||||
.failOn(DescriptionPersist._status).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._status}, LocaleContextHolder.getLocale())),
|
||||
.iff(() -> this.isValidGuid(item.getId()))
|
||||
.must(() -> this.isValidGuid(item.getStatusId()))
|
||||
.failOn(DescriptionPersist._statusId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._statusId}, LocaleContextHolder.getLocale())),
|
||||
this.spec()
|
||||
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
|
||||
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == DescriptionStatus.Finalized)
|
||||
.must(() -> !this.isNull(item.getProperties()))
|
||||
.failOn(DescriptionPersist._properties).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionPersist._properties}, LocaleContextHolder.getLocale())),
|
||||
this.spec()
|
||||
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
|
||||
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == DescriptionStatus.Finalized)
|
||||
.must(() -> this.isDescriptionTemplateMaxMultiplicityValid(finalPlanBlueprintEntity, item.getPlanId(), item.getPlanDescriptionTemplateId(), this.isValidGuid(item.getId())))
|
||||
.failOn(DescriptionPersist._descriptionTemplateId).failWith(this.messageSource.getMessage("Validation.InvalidDescriptionTemplateMultiplicity", new Object[]{DescriptionPersist._descriptionTemplateId}, LocaleContextHolder.getLocale())),
|
||||
this.refSpec()
|
||||
.iff(() -> item.getStatus() == DescriptionStatus.Finalized)
|
||||
.iff(() -> finalStatusEntity != null && finalStatusEntity.getInternalStatus() != null && finalStatusEntity.getInternalStatus() == DescriptionStatus.Finalized)
|
||||
.on(DescriptionPersist._properties)
|
||||
.over(item.getProperties())
|
||||
.using(() -> this.validatorFactory.validator(PropertyDefinitionPersist.PropertyDefinitionPersistValidator.class).setStatus(item.getStatus()).withDefinition(definition).setVisibilityService(definition, item.getProperties()))
|
||||
.using(() -> this.validatorFactory.validator(PropertyDefinitionPersist.PropertyDefinitionPersistValidator.class).setStatus(finalStatusEntity.getInternalStatus()).withDefinition(definition).setVisibilityService(definition, item.getProperties()))
|
||||
// this.navSpec()
|
||||
// .iff(() -> !this.isNull(item.getTags()))
|
||||
// .on(DescriptionPersist._tags)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.opencdmp.model.persist;
|
||||
|
||||
import org.opencdmp.commons.enums.DescriptionStatus;
|
||||
import org.opencdmp.commons.validation.BaseValidator;
|
||||
import gr.cite.tools.validation.specification.Specification;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
|
@ -21,7 +20,7 @@ public class DescriptionStatusPersist {
|
|||
|
||||
public static final String _id = "id";
|
||||
|
||||
private DescriptionStatus status;
|
||||
private UUID statusId;
|
||||
|
||||
public static final String _status = "status";
|
||||
|
||||
|
@ -37,12 +36,12 @@ public class DescriptionStatusPersist {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
public DescriptionStatus getStatus() {
|
||||
return status;
|
||||
public UUID getStatusId() {
|
||||
return statusId;
|
||||
}
|
||||
|
||||
public void setStatus(DescriptionStatus status) {
|
||||
this.status = status;
|
||||
public void setStatusId(UUID statusId) {
|
||||
this.statusId = statusId;
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
|
@ -82,7 +81,7 @@ public class DescriptionStatusPersist {
|
|||
.must(() -> this.isValidHash(item.getHash()))
|
||||
.failOn(DescriptionStatusPersist._hash).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._hash}, LocaleContextHolder.getLocale())),
|
||||
this.spec()
|
||||
.must(() -> !this.isNull(item.getStatus()))
|
||||
.must(() -> this.isValidGuid(item.getStatusId()))
|
||||
.failOn(DescriptionStatusPersist._status).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionStatusPersist._status}, LocaleContextHolder.getLocale()))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -400,6 +400,8 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
|
|||
return DescriptionEntity._properties;
|
||||
else if (item.match(Description._status) || item.match(PublicDescription._status))
|
||||
return DescriptionEntity._status;
|
||||
else if (item.prefix(Description._status) || item.prefix(PublicDescription._status))
|
||||
return DescriptionEntity._statusId;
|
||||
else if (item.match(Description._description) || item.match(PublicDescription._description))
|
||||
return DescriptionEntity._description;
|
||||
else if (item.match(Description._createdBy))
|
||||
|
@ -444,6 +446,7 @@ public class DescriptionQuery extends QueryBase<DescriptionEntity> {
|
|||
item.setLabel(QueryBase.convertSafe(tuple, columns, DescriptionEntity._label, String.class));
|
||||
item.setProperties(QueryBase.convertSafe(tuple, columns, DescriptionEntity._properties, String.class));
|
||||
item.setStatus(QueryBase.convertSafe(tuple, columns, DescriptionEntity._status, DescriptionStatus.class));
|
||||
item.setStatusId(QueryBase.convertSafe(tuple, columns, DescriptionEntity._statusId, UUID.class));
|
||||
item.setDescription(QueryBase.convertSafe(tuple, columns, DescriptionEntity._description, String.class));
|
||||
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, DescriptionEntity._createdAt, Instant.class));
|
||||
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, DescriptionEntity._updatedAt, Instant.class));
|
||||
|
|
|
@ -77,9 +77,9 @@ public class DashboardServiceImpl implements DashboardService {
|
|||
descriptionLookup.getPage().setOffset(0);
|
||||
descriptionLookup.getPage().setSize(model.getPage().getSize()+model.getPage().getOffset());
|
||||
|
||||
QueryResult<Description> descriptions = this.elasticQueryHelperService.collect(descriptionLookup, AuthorizationFlags.AllExceptPublic, new BaseFieldSet().ensure(Description._id).ensure(Description._updatedAt).ensure(Description._status).ensure(Description._label));
|
||||
QueryResult<Description> descriptions = this.elasticQueryHelperService.collect(descriptionLookup, AuthorizationFlags.AllExceptPublic, new BaseFieldSet().ensure(Description._id).ensure(Description._updatedAt).ensure(String.join(".",Description._status, org.opencdmp.model.descriptionstatus.DescriptionStatus._internalStatus)).ensure(Description._label));
|
||||
if (!this.conventionService.isListNullOrEmpty(descriptions.getItems())) {
|
||||
for (Description description : descriptions.getItems()) recentActivityItemEntities.add(new RecentActivityItemEntity(RecentActivityItemType.Description, description.getId(), description.getUpdatedAt(), description.getLabel(), description.getStatus().getValue()));
|
||||
for (Description description : descriptions.getItems()) recentActivityItemEntities.add(new RecentActivityItemEntity(RecentActivityItemType.Description, description.getId(), description.getUpdatedAt(), description.getLabel(), description.getStatus().getInternalStatus().getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ import org.opencdmp.model.referencetype.ReferenceType;
|
|||
import org.opencdmp.query.*;
|
||||
import org.opencdmp.service.accounting.AccountingService;
|
||||
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
|
||||
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
|
||||
import org.opencdmp.service.elastic.ElasticService;
|
||||
import org.opencdmp.service.filetransformer.FileTransformerService;
|
||||
import org.opencdmp.service.responseutils.ResponseUtilsService;
|
||||
|
@ -141,6 +142,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
private final TagService tagService;
|
||||
private final UsageLimitService usageLimitService;
|
||||
private final AccountingService accountingService;
|
||||
private final DescriptionWorkflowService descriptionWorkflowService;
|
||||
|
||||
@Autowired
|
||||
public DescriptionServiceImpl(
|
||||
|
@ -155,7 +157,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
QueryFactory queryFactory,
|
||||
JsonHandlingService jsonHandlingService,
|
||||
UserScope userScope,
|
||||
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService, UsageLimitService usageLimitService, AccountingService accountingService) {
|
||||
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService) {
|
||||
this.entityManager = entityManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
@ -184,6 +186,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
this.tagService = tagService;
|
||||
this.usageLimitService = usageLimitService;
|
||||
this.accountingService = accountingService;
|
||||
this.descriptionWorkflowService = descriptionWorkflowService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -223,9 +226,17 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
data = this.entityManager.find(DescriptionEntity.class, model.getId());
|
||||
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
|
||||
if (data.getStatus().equals(DescriptionStatus.Finalized)) throw new MyValidationException(this.errors.getDescriptionIsFinalized().getCode(), this.errors.getDescriptionIsFinalized().getMessage());
|
||||
DescriptionStatusEntity oldDescriptionStatusEntity = this.entityManager.find(DescriptionStatusEntity.class, data.getStatusId(), true);
|
||||
if (oldDescriptionStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getStatusId(), org.opencdmp.model.descriptionstatus.DescriptionStatus.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
if (oldDescriptionStatusEntity.getInternalStatus() != null && oldDescriptionStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) throw new MyValidationException(this.errors.getDescriptionIsFinalized().getCode(), this.errors.getDescriptionIsFinalized().getMessage());
|
||||
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());
|
||||
if (model.getStatusId() != null && !model.getStatusId().equals(data.getStatusId())) {
|
||||
data.setStatusId(model.getStatusId());
|
||||
DescriptionStatusEntity newDescriptionStatusEntity = this.entityManager.find(DescriptionStatusEntity.class, model.getStatusId(), true);
|
||||
if (newDescriptionStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getStatusId(), org.opencdmp.model.descriptionstatus.DescriptionStatus.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
if (newDescriptionStatusEntity.getInternalStatus() != null && newDescriptionStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) data.setFinalizedAt(Instant.now());
|
||||
}
|
||||
} else {
|
||||
this.usageLimitService.checkIncrease(UsageLimitTargetMetric.DESCRIPTION_COUNT);
|
||||
|
||||
|
@ -244,6 +255,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
data.setCreatedById(this.userScope.getUserId());
|
||||
data.setPlanId(model.getPlanId());
|
||||
data.setPlanDescriptionTemplateId(model.getPlanDescriptionTemplateId());
|
||||
data.setStatus(DescriptionStatus.Draft);
|
||||
data.setStatusId(this.descriptionWorkflowService.getWorkFlowDefinition().getStartingStatusId());
|
||||
}
|
||||
|
||||
DescriptionTemplateEntity descriptionTemplateEntity = this.entityManager.find(DescriptionTemplateEntity.class, model.getDescriptionTemplateId(), true);
|
||||
|
@ -257,8 +270,6 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
if (plan.getStatus().equals(PlanStatus.Finalized) && isUpdate) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
|
||||
|
||||
data.setLabel(model.getLabel());
|
||||
data.setStatus(model.getStatus());
|
||||
if (model.getStatus() == DescriptionStatus.Finalized) data.setFinalizedAt(Instant.now());
|
||||
data.setDescription(model.getDescription());
|
||||
data.setDescriptionTemplateId(model.getDescriptionTemplateId());
|
||||
data.setUpdatedAt(Instant.now());
|
||||
|
@ -376,6 +387,10 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
}
|
||||
|
||||
private void sendNotification(DescriptionEntity description, Boolean isUpdate) throws InvalidApplicationException {
|
||||
DescriptionStatusEntity descriptionStatusEntity = this.entityManager.find(DescriptionStatusEntity.class, description.getStatusId(), true);
|
||||
if (descriptionStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{description, DescriptionStatus.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
if (descriptionStatusEntity.getInternalStatus() == null || descriptionStatusEntity.getInternalStatus().equals(DescriptionStatus.Canceled)) return;
|
||||
|
||||
List<PlanUserEntity> existingUsers = this.queryFactory.query(PlanUserQuery.class).disableTracking()
|
||||
.planIds(description.getPlanId())
|
||||
.isActives(IsActive.Active)
|
||||
|
@ -388,7 +403,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
if (!planUser.getUserId().equals(this.userScope.getUserIdSafe())){
|
||||
UserEntity user = this.queryFactory.query(UserQuery.class).disableTracking().ids(planUser.getUserId()).first();
|
||||
if (user == null || user.getIsActive().equals(IsActive.Inactive)) throw new MyValidationException(this.errors.getPlanInactiveUser().getCode(), this.errors.getPlanInactiveUser().getMessage());
|
||||
this.createDescriptionNotificationEvent(description, user, isUpdate);
|
||||
this.createDescriptionNotificationEvent(description, descriptionStatusEntity.getInternalStatus(), user, isUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -437,11 +452,11 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
return cleanData;
|
||||
}
|
||||
|
||||
private void createDescriptionNotificationEvent(DescriptionEntity description, UserEntity user, Boolean isUpdate) throws InvalidApplicationException {
|
||||
private void createDescriptionNotificationEvent(DescriptionEntity description, DescriptionStatus internalStatus, UserEntity user, Boolean isUpdate) throws InvalidApplicationException {
|
||||
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
|
||||
event.setUserId(user.getId());
|
||||
|
||||
this.applyNotificationType(description.getStatus(), event, isUpdate);
|
||||
this.applyNotificationType(internalStatus, event, isUpdate);
|
||||
NotificationFieldData data = new NotificationFieldData();
|
||||
List<FieldInfo> fieldInfoList = new ArrayList<>();
|
||||
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));
|
||||
|
@ -482,16 +497,20 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
DescriptionEntity data = this.entityManager.find(DescriptionEntity.class, model.getId());
|
||||
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getId(), Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
if (!this.conventionService.hashValue(data.getUpdatedAt()).equals(model.getHash())) throw new MyValidationException(this.errors.getHashConflict().getCode(), this.errors.getHashConflict().getMessage());
|
||||
if (!data.getStatus().equals(model.getStatus())){
|
||||
if (data.getStatus().equals(DescriptionStatus.Finalized)){
|
||||
if (!data.getStatusId().equals(model.getStatusId())){
|
||||
DescriptionStatusEntity oldStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().ids(data.getStatusId()).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id).ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._internalStatus));
|
||||
if (oldStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getStatusId(), DescriptionStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
if (oldStatusEntity.getInternalStatus() != null && oldStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)){
|
||||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.FinalizeDescription);
|
||||
PlanEntity planEntity = this.entityManager.find(PlanEntity.class, data.getPlanId(), true);
|
||||
if (planEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getPlanId(), PlanEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
if(!planEntity.getStatus().equals(PlanStatus.Draft)) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
|
||||
}
|
||||
|
||||
data.setStatus(model.getStatus());
|
||||
if (model.getStatus() == DescriptionStatus.Finalized) data.setFinalizedAt(Instant.now());
|
||||
data.setStatusId(model.getStatusId());
|
||||
DescriptionStatusEntity newStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().ids(model.getStatusId()).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id).ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._internalStatus));
|
||||
if (newStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getStatusId(), DescriptionStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
if (newStatusEntity.getInternalStatus() != null && newStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) data.setFinalizedAt(Instant.now());
|
||||
data.setUpdatedAt(Instant.now());
|
||||
this.entityManager.merge(data);
|
||||
|
||||
|
@ -501,7 +520,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
this.eventBroker.emit(new DescriptionTouchedEvent(data.getId()));
|
||||
|
||||
this.annotationEntityTouchedIntegrationEventHandler.handleDescription(data.getId());
|
||||
if (data.getStatus().equals(DescriptionStatus.Finalized)) this.sendNotification(data, true);
|
||||
if (newStatusEntity.getInternalStatus() != null && newStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) this.sendNotification(data, true);
|
||||
}
|
||||
return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(BaseFieldSet.build(fields, Description._id), data);
|
||||
}
|
||||
|
@ -1003,7 +1022,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
|
||||
persist.setId(data.getId());
|
||||
persist.setLabel(data.getLabel());
|
||||
persist.setStatus(DescriptionStatus.Finalized);
|
||||
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
|
||||
persist.setDescription(data.getDescription());
|
||||
persist.setDescriptionTemplateId(data.getDescriptionTemplateId());
|
||||
persist.setPlanId(data.getPlanId());
|
||||
|
@ -1382,7 +1402,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
DescriptionPersist persist = new DescriptionPersist();
|
||||
persist.setLabel(descriptionXml.getLabel());
|
||||
persist.setDescription(descriptionXml.getDescription());
|
||||
persist.setStatus(DescriptionStatus.Draft);
|
||||
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().isActive(IsActive.Active).internalStatuses(DescriptionStatus.Draft).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
|
||||
persist.setPlanId(planId);
|
||||
persist.setDescriptionTemplateId(this.xmlToDescriptionTemplatePersist(descriptionXml));
|
||||
persist.setPlanDescriptionTemplateId(this.xmlToPlanDescriptionTemplatePersist(descriptionXml, planId));
|
||||
|
@ -1598,7 +1619,8 @@ public class DescriptionServiceImpl implements DescriptionService {
|
|||
DescriptionPersist persist = new DescriptionPersist();
|
||||
persist.setLabel(model.getLabel());
|
||||
persist.setDescription(model.getDescription());
|
||||
persist.setStatus(DescriptionStatus.Draft);
|
||||
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().isActive(IsActive.Active).internalStatuses(DescriptionStatus.Draft).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
|
||||
persist.setPlanId(planId);
|
||||
persist.setDescriptionTemplateId(this.commonModelToDescriptionTemplatePersist(model));
|
||||
persist.setPlanDescriptionTemplateId(this.commonModelTToPlanDescriptionTemplatePersist(model, planId));
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
|||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
||||
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface DescriptionStatusService {
|
||||
|
@ -17,4 +18,6 @@ public interface DescriptionStatusService {
|
|||
DescriptionStatus persist(DescriptionStatusPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
|
||||
|
||||
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
|
||||
|
||||
List<DescriptionStatus> getAvailableTransitionStatuses(UUID descriptionId) throws InvalidApplicationException;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.opencdmp.service.descriptionstatus;
|
|||
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.data.query.QueryFactory;
|
||||
import gr.cite.tools.exception.MyApplicationException;
|
||||
import gr.cite.tools.exception.MyForbiddenException;
|
||||
import gr.cite.tools.exception.MyNotFoundException;
|
||||
|
@ -12,22 +13,29 @@ import gr.cite.tools.fieldset.FieldSet;
|
|||
import gr.cite.tools.logging.LoggerService;
|
||||
import gr.cite.tools.logging.MapLogEntry;
|
||||
import jakarta.xml.bind.JAXBException;
|
||||
import org.opencdmp.authorization.AuthorizationFlags;
|
||||
import org.opencdmp.authorization.Permission;
|
||||
import org.opencdmp.commons.XmlHandlingService;
|
||||
import org.opencdmp.commons.enums.IsActive;
|
||||
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionAuthorizationEntity;
|
||||
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionAuthorizationItemEntity;
|
||||
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
|
||||
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
|
||||
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionTransitionEntity;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
import org.opencdmp.data.DescriptionEntity;
|
||||
import org.opencdmp.data.DescriptionStatusEntity;
|
||||
import org.opencdmp.data.TenantEntityManager;
|
||||
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
||||
import org.opencdmp.model.deleter.DescriptionStatusDeleter;
|
||||
import org.opencdmp.model.description.Description;
|
||||
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionAuthorizationItemPersist;
|
||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionAuthorizationPersist;
|
||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusDefinitionPersist;
|
||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
||||
import org.opencdmp.query.DescriptionStatusQuery;
|
||||
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
|
@ -35,8 +43,10 @@ import org.springframework.stereotype.Service;
|
|||
|
||||
import javax.management.InvalidApplicationException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
||||
|
@ -51,8 +61,10 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
|||
private final ConventionService conventionService;
|
||||
private final MessageSource messageSource;
|
||||
private final XmlHandlingService xmlHandlingService;
|
||||
private final QueryFactory queryFactory;
|
||||
private final DescriptionWorkflowService descriptionWorkflowService;
|
||||
|
||||
public DescriptionStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authService, TenantEntityManager entityManager, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService) {
|
||||
public DescriptionStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authService, TenantEntityManager entityManager, ConventionService conventionService, MessageSource messageSource, XmlHandlingService xmlHandlingService, QueryFactory queryFactory, DescriptionWorkflowService descriptionWorkflowService) {
|
||||
this.builderFactory = builderFactory;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
||||
|
@ -61,6 +73,8 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
|||
this.conventionService = conventionService;
|
||||
this.messageSource = messageSource;
|
||||
this.xmlHandlingService = xmlHandlingService;
|
||||
this.queryFactory = queryFactory;
|
||||
this.descriptionWorkflowService = descriptionWorkflowService;
|
||||
}
|
||||
|
||||
|
||||
|
@ -141,4 +155,20 @@ public class DescriptionStatusServiceImpl implements DescriptionStatusService {
|
|||
|
||||
return data;
|
||||
}
|
||||
|
||||
public List<DescriptionStatus> getAvailableTransitionStatuses(UUID descriptionId) throws InvalidApplicationException {
|
||||
DescriptionWorkflowDefinitionEntity definition = this.descriptionWorkflowService.getWorkFlowDefinition();
|
||||
|
||||
DescriptionEntity description = this.entityManager.find(DescriptionEntity.class, descriptionId);
|
||||
if (description == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
List<DescriptionWorkflowDefinitionTransitionEntity> availableTransitions = definition.getStatusTransitions().stream().filter(x -> x.getFromStatusId().equals(description.getStatusId())).collect(Collectors.toList());
|
||||
if (!this.conventionService.isListNullOrEmpty(availableTransitions)){
|
||||
DescriptionStatusQuery query = this.queryFactory.query(DescriptionStatusQuery.class).authorize(AuthorizationFlags.AllExceptPublic).isActive(IsActive.Active).ids(availableTransitions.stream().map(DescriptionWorkflowDefinitionTransitionEntity::getToStatusId).distinct().toList());
|
||||
FieldSet fieldSet = new BaseFieldSet().ensure(DescriptionStatus._id).ensure(DescriptionStatus._name).ensure(DescriptionStatus._internalStatus);
|
||||
return this.builderFactory.builder(DescriptionStatusBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(fieldSet, query.collectAs(fieldSet));
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.opencdmp.service.descriptionworkflow;
|
||||
|
||||
import gr.cite.tools.fieldset.FieldSet;
|
||||
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
|
||||
import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
|
||||
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowPersist;
|
||||
|
||||
|
@ -11,4 +12,6 @@ public interface DescriptionWorkflowService {
|
|||
DescriptionWorkflow persist(DescriptionWorkflowPersist persist, FieldSet fields) throws InvalidApplicationException;
|
||||
|
||||
void deleteAndSave(UUID id) throws InvalidApplicationException;
|
||||
|
||||
DescriptionWorkflowDefinitionEntity getWorkFlowDefinition() throws InvalidApplicationException;
|
||||
}
|
||||
|
|
|
@ -3,15 +3,19 @@ package org.opencdmp.service.descriptionworkflow;
|
|||
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.data.query.QueryFactory;
|
||||
import gr.cite.tools.exception.MyApplicationException;
|
||||
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.XmlHandlingService;
|
||||
import org.opencdmp.commons.enums.IsActive;
|
||||
import org.opencdmp.commons.scope.tenant.TenantScope;
|
||||
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionEntity;
|
||||
import org.opencdmp.commons.types.descriptionworkflow.DescriptionWorkflowDefinitionTransitionEntity;
|
||||
import org.opencdmp.convention.ConventionService;
|
||||
|
@ -24,6 +28,7 @@ import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
|
|||
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowDefinitionPersist;
|
||||
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowDefinitionTransitionPersist;
|
||||
import org.opencdmp.model.persist.descriptionworkflow.DescriptionWorkflowPersist;
|
||||
import org.opencdmp.query.DescriptionWorkflowQuery;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
|
@ -48,8 +53,10 @@ public class DescriptionWorkflowServiceImpl implements DescriptionWorkflowServic
|
|||
private final TenantEntityManager entityManager;
|
||||
private final MessageSource messageSource;
|
||||
private final ErrorThesaurusProperties errors;
|
||||
private final TenantScope tenantScope;
|
||||
private final QueryFactory queryFactory;
|
||||
|
||||
public DescriptionWorkflowServiceImpl(AuthorizationService authService, ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory, DeleterFactory deleterFactory, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors) {
|
||||
public DescriptionWorkflowServiceImpl(AuthorizationService authService, ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory, DeleterFactory deleterFactory, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors, TenantScope tenantScope, QueryFactory queryFactory) {
|
||||
this.authService = authService;
|
||||
this.conventionService = conventionService;
|
||||
this.xmlHandlingService = xmlHandlingService;
|
||||
|
@ -58,6 +65,8 @@ public class DescriptionWorkflowServiceImpl implements DescriptionWorkflowServic
|
|||
this.entityManager = entityManager;
|
||||
this.messageSource = messageSource;
|
||||
this.errors = errors;
|
||||
this.tenantScope = tenantScope;
|
||||
this.queryFactory = queryFactory;
|
||||
}
|
||||
|
||||
|
||||
|
@ -132,4 +141,22 @@ public class DescriptionWorkflowServiceImpl implements DescriptionWorkflowServic
|
|||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DescriptionWorkflowDefinitionEntity getWorkFlowDefinition() throws InvalidApplicationException {
|
||||
DescriptionWorkflowQuery query = this.queryFactory.query(DescriptionWorkflowQuery.class).authorize(AuthorizationFlags.AllExceptPublic).isActives(IsActive.Active);
|
||||
|
||||
if (this.tenantScope.isDefaultTenant())
|
||||
query = query.defaultTenant(true);
|
||||
else
|
||||
query = query.tenantIds(this.tenantScope.getTenant());
|
||||
|
||||
DescriptionWorkflowEntity entity = query.first();
|
||||
if (entity == null) throw new MyApplicationException("Description workflow not found!");
|
||||
|
||||
DescriptionWorkflowDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(DescriptionWorkflowDefinitionEntity.class, entity.getDefinition());
|
||||
if (definition == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{entity.getId(), DescriptionWorkflowDefinitionEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ import org.opencdmp.service.accounting.AccountingService;
|
|||
import org.opencdmp.service.actionconfirmation.ActionConfirmationService;
|
||||
import org.opencdmp.service.description.DescriptionService;
|
||||
import org.opencdmp.service.descriptiontemplate.DescriptionTemplateService;
|
||||
import org.opencdmp.service.descriptionworkflow.DescriptionWorkflowService;
|
||||
import org.opencdmp.service.elastic.ElasticService;
|
||||
import org.opencdmp.service.filetransformer.FileTransformerService;
|
||||
import org.opencdmp.service.planblueprint.PlanBlueprintService;
|
||||
|
@ -183,6 +184,7 @@ public class PlanServiceImpl implements PlanService {
|
|||
private final PlanBlueprintService planBlueprintService;
|
||||
private final UsageLimitService usageLimitService;
|
||||
private final AccountingService accountingService;
|
||||
private final DescriptionWorkflowService descriptionWorkflowService;
|
||||
|
||||
@Autowired
|
||||
public PlanServiceImpl(
|
||||
|
@ -205,7 +207,7 @@ public class PlanServiceImpl implements PlanService {
|
|||
FileTransformerService fileTransformerService,
|
||||
ValidatorFactory validatorFactory,
|
||||
ElasticService elasticService, DescriptionTemplateService descriptionTemplateService,
|
||||
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService, UsageLimitService usageLimitService, AccountingService accountingService) {
|
||||
AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, AuthorizationContentResolver authorizationContentResolver, TenantScope tenantScope, ResponseUtilsService responseUtilsService, PlanBlueprintService planBlueprintService, UsageLimitService usageLimitService, AccountingService accountingService, DescriptionWorkflowService descriptionWorkflowService) {
|
||||
this.entityManager = entityManager;
|
||||
this.authorizationService = authorizationService;
|
||||
this.deleterFactory = deleterFactory;
|
||||
|
@ -234,6 +236,7 @@ public class PlanServiceImpl implements PlanService {
|
|||
this.planBlueprintService = planBlueprintService;
|
||||
this.usageLimitService = usageLimitService;
|
||||
this.accountingService = accountingService;
|
||||
this.descriptionWorkflowService = descriptionWorkflowService;
|
||||
}
|
||||
|
||||
public Plan persist(PlanPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, IOException {
|
||||
|
@ -620,6 +623,7 @@ public class PlanServiceImpl implements PlanService {
|
|||
newDescription.setLabel(existing.getLabel());
|
||||
newDescription.setDescription(existing.getDescription());
|
||||
newDescription.setStatus(DescriptionStatus.Draft);
|
||||
newDescription.setStatusId(this.descriptionWorkflowService.getWorkFlowDefinition().getStartingStatusId());
|
||||
newDescription.setProperties(existing.getProperties());
|
||||
newDescription.setPlanId(planId);
|
||||
if (newPlanDescriptionTemplateId == null && planDescriptionTemplateRemap != null) newDescription.setPlanDescriptionTemplateId(planDescriptionTemplateRemap.get(existing.getPlanDescriptionTemplateId()));
|
||||
|
@ -740,6 +744,7 @@ public class PlanServiceImpl implements PlanService {
|
|||
newDescription.setLabel(existing.getLabel());
|
||||
newDescription.setDescription(existing.getDescription());
|
||||
newDescription.setStatus(DescriptionStatus.Draft);
|
||||
newDescription.setStatusId(this.descriptionWorkflowService.getWorkFlowDefinition().getStartingStatusId());
|
||||
newDescription.setProperties(existing.getProperties());
|
||||
newDescription.setPlanId(planId);
|
||||
if (planDescriptionTemplateRemap != null) newDescription.setPlanDescriptionTemplateId(planDescriptionTemplateRemap.get(existing.getPlanDescriptionTemplateId()));
|
||||
|
@ -1593,23 +1598,34 @@ public class PlanServiceImpl implements PlanService {
|
|||
List<DescriptionEntity> descriptions = this.queryFactory.query(DescriptionQuery.class)
|
||||
.authorize(AuthorizationFlags.AllExceptPublic).planIds(id).isActive(IsActive.Active).collect();
|
||||
|
||||
for (DescriptionEntity description: descriptions) {
|
||||
if (descriptionIds.contains(description.getId())){
|
||||
// description to be finalized
|
||||
if (description.getStatus().equals(DescriptionStatus.Finalized)){
|
||||
throw new MyApplicationException("Description is already finalized");
|
||||
}
|
||||
if (this.descriptionService.validate(List.of(description.getId())).getFirst().getResult().equals(DescriptionValidationOutput.Invalid)){
|
||||
throw new MyApplicationException("Description is invalid");
|
||||
if (!this.conventionService.isListNullOrEmpty(descriptions)) {
|
||||
List<DescriptionStatusEntity> statusEntities = this.queryFactory.query(DescriptionStatusQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(descriptions.stream().map(DescriptionEntity::getStatusId).distinct().toList()).isActive(IsActive.Active).collect();
|
||||
|
||||
if (this.conventionService.isListNullOrEmpty(statusEntities)) throw new MyApplicationException("Not found description statuses");
|
||||
DescriptionStatusEntity finalizedStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||
if (finalizedStatusEntity == null) throw new MyApplicationException("finalized status not found");
|
||||
|
||||
DescriptionStatusEntity canceledStatusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Canceled).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
||||
if (canceledStatusEntity == null) throw new MyApplicationException("canceled status not found");
|
||||
for (DescriptionEntity description: descriptions) {
|
||||
DescriptionStatusEntity currentStatusEntity = statusEntities.stream().filter(x -> x.getId().equals(description.getStatusId())).findFirst().orElse(null);
|
||||
if (descriptionIds.contains(description.getId())){
|
||||
// description to be finalized
|
||||
if (currentStatusEntity != null && currentStatusEntity.getInternalStatus()!= null && currentStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)){
|
||||
throw new MyApplicationException("Description is already finalized");
|
||||
}
|
||||
if (this.descriptionService.validate(List.of(description.getId())).getFirst().getResult().equals(DescriptionValidationOutput.Invalid)){
|
||||
throw new MyApplicationException("Description is invalid");
|
||||
}
|
||||
if (finalizedStatusEntity != null) description.setStatusId(finalizedStatusEntity.getId());
|
||||
description.setUpdatedAt(Instant.now());
|
||||
description.setFinalizedAt(Instant.now());
|
||||
this.entityManager.merge(description);
|
||||
} else if (currentStatusEntity != null && currentStatusEntity.getInternalStatus()!= null && !currentStatusEntity.getInternalStatus().equals(DescriptionStatus.Finalized)) {
|
||||
// description to be canceled
|
||||
description.setStatusId(canceledStatusEntity.getId());
|
||||
this.deleterFactory.deleter(DescriptionDeleter.class).delete(List.of(description), true);
|
||||
}
|
||||
description.setStatus(DescriptionStatus.Finalized);
|
||||
description.setUpdatedAt(Instant.now());
|
||||
description.setFinalizedAt(Instant.now());
|
||||
this.entityManager.merge(description);
|
||||
} else if (description.getStatus().equals(DescriptionStatus.Draft)) {
|
||||
// description to be canceled
|
||||
description.setStatus(DescriptionStatus.Canceled);
|
||||
this.deleterFactory.deleter(DescriptionDeleter.class).delete(List.of(description), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|||
import jakarta.xml.bind.JAXBException;
|
||||
import org.opencdmp.audit.AuditableAction;
|
||||
import org.opencdmp.authorization.AuthorizationFlags;
|
||||
import org.opencdmp.commons.enums.IsActive;
|
||||
import org.opencdmp.controllers.swagger.SwaggerHelpers;
|
||||
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
|
||||
import org.opencdmp.controllers.swagger.annotation.Swagger400;
|
||||
|
@ -27,11 +28,15 @@ import org.opencdmp.controllers.swagger.annotation.Swagger404;
|
|||
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
|
||||
import org.opencdmp.data.DescriptionStatusEntity;
|
||||
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
||||
import org.opencdmp.model.builder.descriptionworkflow.DescriptionWorkflowBuilder;
|
||||
import org.opencdmp.model.censorship.descriptionstatus.DescriptionStatusCensor;
|
||||
import org.opencdmp.model.censorship.descriptionworkflow.DescriptionWorkflowCensor;
|
||||
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||
import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
|
||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
||||
import org.opencdmp.model.result.QueryResult;
|
||||
import org.opencdmp.query.DescriptionStatusQuery;
|
||||
import org.opencdmp.query.DescriptionWorkflowQuery;
|
||||
import org.opencdmp.query.lookup.DescriptionStatusLookup;
|
||||
import org.opencdmp.service.descriptionstatus.DescriptionStatusService;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -183,4 +188,23 @@ public class DescriptionStatusController {
|
|||
|
||||
this.auditService.track(AuditableAction.DescriptionStatus_Delete, "id", id);
|
||||
}
|
||||
|
||||
@GetMapping("available-transitions/{descriptionId}")
|
||||
@OperationWithTenantHeader(summary = "Get available status transitions for description", description = "",
|
||||
responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(
|
||||
schema = @Schema(
|
||||
implementation = DescriptionWorkflow.class
|
||||
))
|
||||
))
|
||||
@Swagger404
|
||||
public List<DescriptionStatus> GetAvailableTransitions(
|
||||
@Parameter(name = "descriptionId", description = "The id of description", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable UUID descriptionId
|
||||
) throws InvalidApplicationException {
|
||||
logger.debug(new MapLogEntry("retrieving available statuses" + DescriptionStatus.class.getSimpleName()));
|
||||
|
||||
List<DescriptionStatus> availableTransitionStatuses = this.descriptionStatusService.getAvailableTransitionStatuses(descriptionId);
|
||||
|
||||
this.auditService.track(AuditableAction.DescriptionStatus_Delete, "descriptionId", descriptionId);
|
||||
return availableTransitionStatuses;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@ import { Reference, ReferencePersist } from "../reference/reference";
|
|||
import { Tag, TagPersist } from "../tag/tag";
|
||||
import { User } from "../user/user";
|
||||
import { AppPermission } from "@app/core/common/enum/permission.enum";
|
||||
import { DescriptionStatus } from "../description-status/description-status";
|
||||
|
||||
export interface Description extends BaseDescription {
|
||||
label?: string;
|
||||
status?: DescriptionStatus;
|
||||
properties?: DescriptionPropertyDefinition;
|
||||
description?: string;
|
||||
createdBy?: User;
|
||||
|
@ -76,7 +78,7 @@ export interface DescriptionPersist extends BaseEntityPersist {
|
|||
planId: Guid;
|
||||
planDescriptionTemplateId: Guid;
|
||||
descriptionTemplateId: Guid;
|
||||
status: DescriptionStatusEnum;
|
||||
statusId: Guid;
|
||||
description: string;
|
||||
properties: DescriptionPropertyDefinitionPersist;
|
||||
tags: string[];
|
||||
|
@ -120,7 +122,7 @@ export interface DescriptionReferencePersist {
|
|||
|
||||
export interface DescriptionStatusPersist {
|
||||
id: Guid;
|
||||
status: DescriptionStatusEnum;
|
||||
statusId?: Guid;
|
||||
hash: string;
|
||||
}
|
||||
|
||||
|
@ -130,7 +132,7 @@ export interface DescriptionStatusPersist {
|
|||
|
||||
export interface PublicDescription extends BaseDescription {
|
||||
label?: string;
|
||||
status?: DescriptionStatusEnum;
|
||||
status?: PublicDescriptionStatus;
|
||||
description?: string;
|
||||
finalizedAt?: Date;
|
||||
descriptionTemplate?: PublicDescriptionTemplate;
|
||||
|
@ -148,6 +150,13 @@ export interface PublicDescriptionTemplate {
|
|||
label: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface PublicDescriptionStatus {
|
||||
id: Guid;
|
||||
name: string;
|
||||
internalStatus: DescriptionStatusEnum;
|
||||
}
|
||||
|
||||
export interface DescriptionSectionPermissionResolver {
|
||||
planId: Guid;
|
||||
sectionIds: Guid[];
|
||||
|
@ -161,5 +170,4 @@ export interface UpdateDescriptionTemplatePersist {
|
|||
|
||||
export interface BaseDescription extends BaseEntity {
|
||||
tenantId?: Guid;
|
||||
status?: DescriptionStatusEnum;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,15 @@ export class DescriptionStatusService {
|
|||
catchError((error: any) => throwError(() => error)));
|
||||
}
|
||||
|
||||
getAvailableTransitions(descriptionId: Guid, reqFields: string[] = []): Observable<Array<DescriptionStatus>> {
|
||||
const url = `${this.apiBase}/available-transitions/${descriptionId}`;
|
||||
const options = { params: { f: reqFields } };
|
||||
|
||||
return this.http
|
||||
.get<Array<DescriptionStatus>>(url, options).pipe(
|
||||
catchError((error: any) => throwError(() => error)));
|
||||
}
|
||||
|
||||
buildLookup(params: {
|
||||
like?: string,
|
||||
excludedIds?: Guid[],
|
||||
|
|
|
@ -28,6 +28,7 @@ import { BehaviorSubject } from 'rxjs';
|
|||
import { debounceTime, map, takeUntil } from 'rxjs/operators';
|
||||
import { nameof } from 'ts-simple-nameof';
|
||||
import { ActivityListingType } from '../dashboard.component';
|
||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recent-edited-activity',
|
||||
|
@ -232,16 +233,16 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
|
|||
if (item.plan){
|
||||
if (item.plan.descriptions) {
|
||||
if (item.plan.status == PlanStatusEnum.Finalized) {
|
||||
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatusEnum.Finalized);
|
||||
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus === DescriptionStatusEnum.Finalized);
|
||||
} else {
|
||||
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status != DescriptionStatusEnum.Canceled);
|
||||
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus != DescriptionStatusEnum.Canceled);
|
||||
}
|
||||
}
|
||||
item.plan.planUsers = item.plan.planUsers.filter(x=> x.isActive === IsActive.Active);
|
||||
this.listingItems.push(item);
|
||||
}
|
||||
if (item.description){
|
||||
if (item.description.status != DescriptionStatusEnum.Canceled) this.listingItems.push(item);
|
||||
if (item.description?.status?.internalStatus != DescriptionStatusEnum.Canceled) this.listingItems.push(item);
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -288,7 +289,9 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
|
|||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.authorizationFlags), AppPermission.EditPlan].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.label)].join('.'),
|
||||
|
@ -318,7 +321,9 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
|
|||
return [
|
||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.id)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.label)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.status)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.updatedAt)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.isActive)].join('.'),
|
||||
[nameof<RecentActivityItem>(x => x.description), nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
|
||||
|
|
|
@ -46,7 +46,7 @@ export class DescriptionBaseFieldsEditorComponent extends BaseComponent {
|
|||
if (this.description?.descriptionTemplate != null) {
|
||||
const isPreviousVersion: boolean = this.description.descriptionTemplate.versionStatus === DescriptionTemplateVersionStatus.Previous;
|
||||
if (isPreviousVersion === true) {
|
||||
if (this.description.status === DescriptionStatusEnum.Draft) {
|
||||
if (this.description.status?.internalStatus === DescriptionStatusEnum.Draft) {
|
||||
this.openDeprecatedDescriptionTemplateDialog();
|
||||
} else {
|
||||
this.availableDescriptionTemplates.push(this.description.descriptionTemplate);
|
||||
|
|
|
@ -67,9 +67,12 @@
|
|||
<button [disabled]="saving" mat-menu-item (click)="saveAndClose()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.SAVE-AND-CLOSE' | translate }}</button>
|
||||
<button [disabled]="saving" mat-menu-item (click)="saveAndContinue()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.SAVE-AND-CONTINUE' | translate }}</button>
|
||||
</mat-menu>
|
||||
<button [disabled]="saving" *ngIf="canEdit && !isLocked && !viewOnly && hasReversableStatus() == false && canEdit" mat-button class="rounded-btn neutral mr-2" type="button" (click)="finalize()">{{ 'DESCRIPTION-EDITOR.ACTIONS.FINALIZE' | translate }}</button>
|
||||
<ng-container *ngIf="availableStatusesTransitions && availableStatusesTransitions.length > 0 && !isLocked && item.id">
|
||||
<button *ngFor='let status of availableStatusesTransitions' [disabled]="saving" mat-button class="rounded-btn neutral mr-2" type="button" (click)="persistStatus(status)">{{ status.name }}</button>
|
||||
</ng-container>
|
||||
<!-- <button [disabled]="saving" *ngIf="canEdit && !isLocked && !viewOnly && hasReversableStatus() == false && canEdit" mat-button class="rounded-btn neutral mr-2" type="button" (click)="finalize()">{{ 'DESCRIPTION-EDITOR.ACTIONS.FINALIZE' | translate }}</button> -->
|
||||
<button [disabled]="saving" *ngIf="isLocked" mat-button disabled class="rounded-btn neutral cursor-default" type="button">{{ 'PLAN-OVERVIEW.LOCKED' | translate}}</button>
|
||||
<button [disabled]="saving" *ngIf="hasReversableStatus() && !isLocked && canEdit" mat-button class="rounded-btn neutral mr-2" (click)="reverse()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.REVERSE' | translate }}</button>
|
||||
<!-- <button [disabled]="saving" *ngIf="hasReversableStatus() && !isLocked && canEdit" mat-button class="rounded-btn neutral mr-2" (click)="reverse()" type="button">{{ 'DESCRIPTION-EDITOR.ACTIONS.REVERSE' | translate }}</button> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -45,6 +45,8 @@ import { DescriptionEditorEntityResolver } from './resolvers/description-editor-
|
|||
import { ToCEntry } from './table-of-contents/models/toc-entry';
|
||||
import { TableOfContentsService } from './table-of-contents/services/table-of-contents-service';
|
||||
import { TableOfContentsComponent } from './table-of-contents/table-of-contents.component';
|
||||
import { DescriptionStatusService } from '@app/core/services/description-status/description-status.service';
|
||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||
|
||||
@Component({
|
||||
selector: 'app-description-editor-component',
|
||||
|
@ -82,6 +84,9 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
private initialTemplateId: string = Guid.EMPTY;
|
||||
private permissionPerSection: Map<Guid, string[]>;
|
||||
|
||||
availableStatusesTransitions: DescriptionStatus[];
|
||||
oldStatusId: Guid;
|
||||
|
||||
constructor(
|
||||
// BaseFormEditor injected dependencies
|
||||
public routerUtils: RouterUtilsService,
|
||||
|
@ -111,6 +116,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
private tableOfContentsService: TableOfContentsService,
|
||||
private descriptionFormService: DescriptionFormService,
|
||||
private formAnnotationService: FormAnnotationService,
|
||||
private descriptionStatusService: DescriptionStatusService
|
||||
) {
|
||||
const descriptionLabel: string = route.snapshot.data['entity']?.label;
|
||||
if (descriptionLabel) {
|
||||
|
@ -190,7 +196,8 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
}
|
||||
if (this.route.snapshot.url[1] && this.route.snapshot.url[1].path == 'finalize' && !this.lockStatus && !this.viewOnly) {
|
||||
setTimeout(() => {
|
||||
this.finalize();
|
||||
const finalizedStatus = this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Finalized) || null;
|
||||
if (finalizedStatus) this.finalize(finalizedStatus.id);
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
|
@ -215,6 +222,10 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
prepareForm(data: Description) {
|
||||
try {
|
||||
this.editorModel = data ? new DescriptionEditorModel().fromModel(data, data.descriptionTemplate) : new DescriptionEditorModel();
|
||||
if (data) {
|
||||
if (data.id) this.getAvailableStatuses(data.id);
|
||||
if (data.status?.id) this.oldStatusId = data.status.id
|
||||
}
|
||||
if (data && data?.plan?.planUsers) data.plan.planUsers = data.plan.planUsers.filter(x => x.isActive === IsActive.Active);
|
||||
this.item = data;
|
||||
this.initialTemplateId = data?.descriptionTemplate?.id?.toString();
|
||||
|
@ -227,6 +238,13 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
}
|
||||
this.isDeleted = data ? data.isActive === IsActive.Inactive : false;
|
||||
this.buildForm();
|
||||
if (data?.status?.internalStatus == DescriptionStatusEnum.Finalized || this.isDeleted || !this.canEdit) {
|
||||
this.viewOnly = true;
|
||||
this.isFinalized = true;
|
||||
this.formGroup.disable();
|
||||
} else {
|
||||
this.viewOnly = false;
|
||||
}
|
||||
if (this.isDeleted || (this.formGroup && this.editorModel.belongsToCurrentTenant == false)) {
|
||||
this.formGroup.disable();
|
||||
this.canEdit = false;
|
||||
|
@ -245,17 +263,19 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
|
||||
// this.selectedSystemFields = this.selectedSystemFieldDisabled();
|
||||
this.descriptionEditorService.setValidationErrorModel(this.editorModel.validationErrorModel);
|
||||
if (this.editorModel.status == DescriptionStatusEnum.Finalized || this.isDeleted || !this.canEdit) {
|
||||
this.viewOnly = true;
|
||||
this.isFinalized = this.editorModel.status == DescriptionStatusEnum.Finalized;
|
||||
this.formGroup.disable();
|
||||
} else {
|
||||
this.viewOnly = false;
|
||||
}
|
||||
|
||||
this.registerFormListeners();
|
||||
}
|
||||
|
||||
getAvailableStatuses(id: Guid){
|
||||
this.descriptionStatusService.getAvailableTransitions(id).pipe(takeUntil(this._destroyed))
|
||||
.subscribe(
|
||||
(statuses) => {
|
||||
this.availableStatusesTransitions = statuses;
|
||||
},
|
||||
(error) => this.httpErrorHandlingService.handleBackedRequestError(error)
|
||||
); }
|
||||
|
||||
calculateMultiplicityRejectedPlanDescriptionTemplates(section: PlanBlueprintDefinitionSection, descriptions: Description[]): PlanDescriptionTemplate[] {
|
||||
if (section.descriptionTemplates?.length > 0) {
|
||||
descriptions = descriptions?.filter(x => x?.planDescriptionTemplate?.sectionId === section.id) || [];
|
||||
|
@ -302,17 +322,18 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
|
||||
persistEntity(onSuccess?: (response) => void): void {
|
||||
const formData = this.formService.getValue(this.formGroup.value) as DescriptionPersist;
|
||||
const finalizedStatus = this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Finalized) || null;
|
||||
|
||||
this.descriptionService.persist(formData)
|
||||
.pipe(takeUntil(this._destroyed)).subscribe(
|
||||
complete => {
|
||||
onSuccess ? onSuccess(complete) : this.onCallbackSuccess(complete);
|
||||
this.descriptionIsOnceSaved = true;
|
||||
if (this.formGroup.get('status').value == DescriptionStatusEnum.Finalized) this.isFinalized = true;
|
||||
if (finalizedStatus && this.formGroup.get('statusId').value == finalizedStatus.id) this.isFinalized = true;
|
||||
},
|
||||
error => {
|
||||
if (this.formGroup.get('status').value == DescriptionStatusEnum.Finalized) {
|
||||
this.formGroup.get('status').setValue(DescriptionStatusEnum.Draft);
|
||||
if (finalizedStatus && this.formGroup.get('statusId').value == finalizedStatus.id) {
|
||||
this.formGroup.get('statusId').setValue(this.oldStatusId);
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-FINALIZE'), SnackBarNotificationLevel.Error);
|
||||
} else {
|
||||
this.onCallbackError(error);
|
||||
|
@ -324,7 +345,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
formSubmit(onSuccess?: (response) => void): void {
|
||||
this.formService.removeAllBackEndErrors(this.formGroup);
|
||||
if (this.formGroup.get('label').valid && this.formGroup.get('planId').valid && this.formGroup.get('planDescriptionTemplateId').valid
|
||||
&& this.formGroup.get('descriptionTemplateId').valid && this.formGroup.get('status').valid) {
|
||||
&& this.formGroup.get('descriptionTemplateId').valid) {// && this.formGroup.get('statusId').valid) {
|
||||
this.persistEntity(onSuccess);
|
||||
} else {
|
||||
const errorMessages = this._buildSemiFormErrorMessages();
|
||||
|
@ -698,7 +719,19 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
return [];
|
||||
}
|
||||
|
||||
finalize() {
|
||||
persistStatus(status: DescriptionStatus) {
|
||||
if (status.internalStatus != null && status.internalStatus === DescriptionStatusEnum.Finalized) {
|
||||
this.finalize(status.id);
|
||||
} else if (status.internalStatus != null && this.item.status.internalStatus === DescriptionStatusEnum.Finalized){
|
||||
this.reverse(status.id);
|
||||
} else {
|
||||
// other statuses
|
||||
this.formGroup.get('statusId').setValue(status.id);
|
||||
this.persistEntity();
|
||||
}
|
||||
}
|
||||
|
||||
finalize(statusId: Guid) {
|
||||
this.formService.removeAllBackEndErrors(this.formGroup);
|
||||
this.formService.touchAllFormFields(this.formGroup);
|
||||
this.formService.validateAllFormFields(this.formGroup);
|
||||
|
@ -727,13 +760,13 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
});
|
||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||
if (result) {
|
||||
this.formGroup.get('status').setValue(DescriptionStatusEnum.Finalized);
|
||||
this.formGroup.get('statusId').setValue(statusId);
|
||||
this.persistEntity();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reverse() {
|
||||
reverse(statusId: Guid) {
|
||||
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||
restoreFocus: false,
|
||||
data: {
|
||||
|
@ -747,7 +780,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
|||
if (result) {
|
||||
const planUserRemovePersist: DescriptionStatusPersist = {
|
||||
id: this.formGroup.get('id').value,
|
||||
status: DescriptionStatusEnum.Draft,
|
||||
statusId: statusId,
|
||||
hash: this.formGroup.get('hash').value
|
||||
};
|
||||
this.descriptionService.persistStatus(planUserRemovePersist, DescriptionEditorEntityResolver.lookupFields()).pipe(takeUntil(this._destroyed))
|
||||
|
|
|
@ -18,7 +18,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti
|
|||
planId: Guid;
|
||||
planDescriptionTemplateId: Guid;
|
||||
descriptionTemplateId: Guid;
|
||||
status: DescriptionStatusEnum;
|
||||
statusId: Guid;
|
||||
description: string;
|
||||
properties: DescriptionPropertyDefinitionEditorModel = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel);
|
||||
tags: string[] = [];
|
||||
|
@ -36,7 +36,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti
|
|||
this.planId = item.plan?.id;
|
||||
this.planDescriptionTemplateId = item.planDescriptionTemplate?.id;
|
||||
this.descriptionTemplateId = item.descriptionTemplate?.id;
|
||||
this.status = item.status ?? DescriptionStatusEnum.Draft;
|
||||
this.statusId = item.status?.id;
|
||||
this.description = item.description;
|
||||
this.tags = item.descriptionTags?.filter(x => x.isActive === IsActive.Active).map(x => x.tag?.label);
|
||||
this.properties = new DescriptionPropertyDefinitionEditorModel(this.validationErrorModel).fromModel(item.properties, descriptionTemplate, item.descriptionReferences);
|
||||
|
@ -53,7 +53,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti
|
|||
planId: [{ value: this.planId, disabled: disabled }, context.getValidation('planId').validators],
|
||||
planDescriptionTemplateId: [{ value: this.planDescriptionTemplateId, disabled: disabled }, context.getValidation('planDescriptionTemplateId').validators],
|
||||
descriptionTemplateId: [{ value: this.descriptionTemplateId, disabled: disabled }, context.getValidation('descriptionTemplateId').validators],
|
||||
status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators],
|
||||
statusId: [{ value: this.statusId, disabled: disabled }, context.getValidation('statusId').validators],
|
||||
description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators],
|
||||
tags: [{ value: this.tags, disabled: disabled }, context.getValidation('tags').validators],
|
||||
properties: this.buildProperties(visibilityRulesService),
|
||||
|
@ -76,7 +76,7 @@ export class DescriptionEditorModel extends BaseEditorModel implements Descripti
|
|||
baseValidationArray.push({ key: 'planId', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'planId')] });
|
||||
baseValidationArray.push({ key: 'planDescriptionTemplateId', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'planDescriptionTemplateId')] });
|
||||
baseValidationArray.push({ key: 'descriptionTemplateId', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'descriptionTemplateId')] });
|
||||
baseValidationArray.push({ key: 'status', validators: [CustomValidators.required(), BackendErrorValidator(this.validationErrorModel, 'status')] });
|
||||
baseValidationArray.push({ key: 'statusId', validators: [BackendErrorValidator(this.validationErrorModel, 'statusId')] });
|
||||
baseValidationArray.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] });
|
||||
baseValidationArray.push({ key: 'tags', validators: [BackendErrorValidator(this.validationErrorModel, 'tags')] });
|
||||
baseValidationArray.push({ key: 'hash', validators: [] });
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { DescriptionStatusEnum } from '@app/core/common/enum/description-status';
|
||||
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
||||
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||
import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
|
||||
import { Description, DescriptionExternalIdentifier, DescriptionField, DescriptionPropertyDefinition, DescriptionPropertyDefinitionFieldSet, DescriptionPropertyDefinitionFieldSetItem, DescriptionReference, DescriptionReferenceData, DescriptionTag } from '@app/core/model/description/description';
|
||||
import { DescriptionTemplatesInSection, PlanBlueprint, PlanBlueprintDefinition, PlanBlueprintDefinitionSection } from '@app/core/model/plan-blueprint/plan-blueprint';
|
||||
|
@ -52,9 +52,10 @@ export class DescriptionEditorEntityResolver extends BaseEditorResolver {
|
|||
...BaseEditorResolver.lookupFields(),
|
||||
nameof<Description>(x => x.id),
|
||||
nameof<Description>(x => x.label),
|
||||
nameof<Description>(x => x.status),
|
||||
nameof<Description>(x => x.description),
|
||||
nameof<Description>(x => x.status),
|
||||
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||
|
||||
[nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
|
||||
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),
|
||||
|
@ -203,7 +204,7 @@ export class DescriptionEditorEntityResolver extends BaseEditorResolver {
|
|||
description.hash = null;
|
||||
description.isActive = IsActive.Active;
|
||||
description.belongsToCurrentTenant = true;
|
||||
description.status = DescriptionStatusEnum.Draft;
|
||||
description.status = null;
|
||||
description.plan = plan;
|
||||
description.planDescriptionTemplate = {
|
||||
id: plan.planDescriptionTemplates.filter(x => x.sectionId == Guid.parse(planSectionId) && x.descriptionTemplateGroupId == description.descriptionTemplate.groupId)[0].id,
|
||||
|
|
|
@ -43,6 +43,7 @@ import { InterceptorType } from '@common/http/interceptors/interceptor-type';
|
|||
import { PrincipalService } from '@app/core/services/http/principal.service';
|
||||
import { DescriptionListingFilters } from './filtering/description-filter.component';
|
||||
import { MatSelectChange } from '@angular/material/select';
|
||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||
|
||||
@Component({
|
||||
selector: 'app-description-listing-component',
|
||||
|
@ -490,7 +491,9 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
|
|||
nameof<Description>(x => x.id),
|
||||
nameof<Description>(x => x.tenantId),
|
||||
nameof<Description>(x => x.label),
|
||||
nameof<Description>(x => x.status),
|
||||
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||
nameof<Description>(x => x.updatedAt),
|
||||
nameof<Description>(x => x.belongsToCurrentTenant),
|
||||
nameof<Description>(x => x.finalizedAt),
|
||||
|
|
|
@ -13,15 +13,18 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="description.status === descriptionStatusEnum.Finalized" class="col-auto description-title">{{description.label}}</div>
|
||||
<div *ngIf="description.status === descriptionStatusEnum.Draft" class="col-auto description-title-draft">{{description.label}}</div>
|
||||
<div *ngIf="description.status.internalStatus === descriptionStatusEnum.Finalized" class="col-auto description-title">{{description.label}}</div>
|
||||
<div *ngIf="description.status.internalStatus === descriptionStatusEnum.Draft" class="col-auto description-title-draft">{{description.label}}</div>
|
||||
<div *ngIf="description.status.internalStatus === descriptionStatusEnum.Canceled" class="col-auto description-title-draft">{{description.label}}</div>
|
||||
<div *ngIf="description.status.internalStatus === null" class="col-auto description-title-draft">{{description.label}}</div>
|
||||
<div class="description-subtitle">
|
||||
<span *ngIf="isUserPlanRelated()" class="col-auto">{{ enumUtils.toPlanUserRolesString(planService.getCurrentUserRolesInPlan(description?.plan?.planUsers)) }}</span>
|
||||
<span *ngIf="isUserPlanRelated()">.</span>
|
||||
<span class="col-auto" *ngIf="description.status === descriptionStatusEnum.Finalized && description.plan.accessType === planAccessTypeEnum.Public"><span class="material-icons icon-align">public</span>{{'DESCRIPTION-LISTING.STATES.PUBLIC' | translate}}</span>
|
||||
<span *ngIf="description.status === descriptionStatusEnum.Finalized && description.plan.accessType != planAccessTypeEnum.Public; else draft" class="col-auto"><span class="material-icons icon-align">done</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span>
|
||||
<ng-template #draft><span *ngIf="description.status === descriptionStatusEnum.Draft && canEditDescription(); else preview" class=" col-auto draft"><span class="material-icons icon-align">create</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span></ng-template>
|
||||
<ng-template #preview><span *ngIf="description.status === descriptionStatusEnum.Draft && !canEditDescription()" class=" col-auto draft"><span class="material-icons-outlined mr-1 icon-align">visibility</span>{{ enumUtils.toDescriptionStatusString(description.status) }}</span></ng-template>
|
||||
<span class="col-auto" *ngIf="description.status.internalStatus === descriptionStatusEnum.Finalized && description.plan.accessType === planAccessTypeEnum.Public"><span class="material-icons icon-align">public</span>{{'DESCRIPTION-LISTING.STATES.PUBLIC' | translate}}</span>
|
||||
<span *ngIf="description.status.internalStatus === descriptionStatusEnum.Finalized && description.plan.accessType != planAccessTypeEnum.Public; else draft" class="col-auto"><span class="material-icons icon-align">done</span>{{ description.status.name }}</span>
|
||||
<ng-template #draft><span *ngIf="description.status.internalStatus === descriptionStatusEnum.Draft && canEditDescription(); else preview" class=" col-auto draft"><span class="material-icons icon-align">create</span>{{ description.status.name }}</span></ng-template>
|
||||
<ng-template #preview><span *ngIf="description.status.internalStatus === descriptionStatusEnum.Draft && !canEditDescription(); else otherStatus" class=" col-auto draft"><span class="material-icons-outlined mr-1 icon-align">visibility</span>{{ description.status.name }}</span></ng-template>
|
||||
<ng-template #otherStatus><span class=" col-auto draft">{{ description.status.name }}</span></ng-template>
|
||||
<span>.</span>
|
||||
<span class="col">{{'DESCRIPTION-LISTING.GRANT' | translate}}: {{referenceService.getReferencesForTypesFirstSafe(description?.plan?.planReferences, [this.referenceTypeService.getGrantReferenceType()])?.reference?.label}}</span>
|
||||
</div>
|
||||
|
|
|
@ -82,7 +82,7 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
|
|||
this.analyticsService.trackPageView(AnalyticsService.DescriptionListingItem);
|
||||
if (this.description.isActive === IsActive.Inactive) {
|
||||
this.isDeleted = true;
|
||||
} else if (this.description.status === DescriptionStatusEnum.Draft) {
|
||||
} else if (this.description?.status?.internalStatus === DescriptionStatusEnum.Draft) {
|
||||
this.isDraft = true;
|
||||
this.isDeleted = false;
|
||||
} else {
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
</div>
|
||||
<div class="row mb-4 pb-3">
|
||||
<div class="col-auto pr-0">
|
||||
@if(isActive && (canEdit || canAnnotate) && isDraftDescription(description) && !isLocked){
|
||||
@if(isActive && (canEdit || canAnnotate) && isNotFinalizedDescription(description) && !isLocked){
|
||||
<button (click)="editClicked(description)" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.EDIT' | translate}}" matTooltipPosition="above">
|
||||
<mat-icon class="mat-mini-fab-icon">create</mat-icon>
|
||||
</button>
|
||||
|
@ -134,32 +134,25 @@
|
|||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="frame mb-3 pt-4 pl-4 pr-5 pb-3">
|
||||
<ng-container *ngIf="canFinalize && isDraftDescription(description) && !isLocked">
|
||||
<div class="row align-items-center" (click)="finalize(description)">
|
||||
<div class="col-auto pr-0">
|
||||
<button mat-mini-fab class="finalize-btn">
|
||||
<mat-icon class="mat-mini-fab-icon check-icon">check</mat-icon>
|
||||
</button>
|
||||
<ng-container *ngIf="availableStatusesTransitions && availableStatusesTransitions.length > 0 && !isLocked">
|
||||
<div *ngFor='let status of availableStatusesTransitions'>
|
||||
<div class="row align-items-center" (click)="persistStatus(status, description)">
|
||||
<div class="col-auto pr-0">
|
||||
<button *ngIf="status.internalStatus === descriptionStatusEnum.Finalized && description.status?.internalStatus != descriptionStatusEnum.Finalized" mat-mini-fab class="finalize-btn">
|
||||
<mat-icon class="mat-mini-fab-icon check-icon">check</mat-icon>
|
||||
</button>
|
||||
<button *ngIf="description.status?.internalStatus === descriptionStatusEnum.Finalized" mat-mini-fab class="frame-btn">
|
||||
<mat-icon class="mat-mini-fab-icon">unarchive</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-auto pl-0">
|
||||
<p class="mb-0 pl-2 frame-txt">{{ status.name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto pl-0">
|
||||
<p class="mb-0 pl-2 frame-txt">{{ 'DESCRIPTION-OVERVIEW.ACTIONS.FINALIZE' | translate }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-center">
|
||||
<div class="col-12">
|
||||
<hr class="hr-line">
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="hasReversableStatus(description)">
|
||||
<div class="row mb-3 align-items-center" (click)="reverseFinalization(description)">
|
||||
<div class="col-auto pr-0">
|
||||
<button mat-mini-fab class="frame-btn">
|
||||
<mat-icon class="mat-mini-fab-icon">unarchive</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-auto pl-0">
|
||||
<p class="mb-0 mr-0 pl-2 frame-txt">{{ 'DESCRIPTION-OVERVIEW.ACTIONS.REVERSE' | translate }}</p>
|
||||
<div class="row align-items-center">
|
||||
<div class="col-12">
|
||||
<hr class="hr-line">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
|
|
@ -44,6 +44,8 @@ import { map, takeUntil } from 'rxjs/operators';
|
|||
import { nameof } from 'ts-simple-nameof';
|
||||
import { DescriptionCopyDialogComponent } from '../description-copy-dialog/description-copy-dialog.component';
|
||||
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||
import { DescriptionStatusService } from '@app/core/services/description-status/description-status.service';
|
||||
|
||||
|
||||
@Component({
|
||||
|
@ -73,6 +75,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
canFinalize = false;
|
||||
canAnnotate = false;
|
||||
canInvitePlanUsers = false;
|
||||
availableStatusesTransitions: DescriptionStatus[];
|
||||
canAssignPlanUsers(): boolean {
|
||||
const authorizationFlags = !this.isPublicView ? (this.description?.plan as Plan)?.authorizationFlags : [];
|
||||
return (authorizationFlags?.some(x => x === AppPermission.AssignPlanUsers) || this.authentication.hasPermission(AppPermission.AssignPlanUsers)) &&
|
||||
|
@ -106,6 +109,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
private breadcrumbService: BreadcrumbService,
|
||||
private httpErrorHandlingService: HttpErrorHandlingService,
|
||||
private userService: UserService,
|
||||
private descriptionStatusService: DescriptionStatusService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
@ -135,6 +139,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
this.breadcrumbService.addIdResolvedValue(data.id.toString(), data.label);
|
||||
|
||||
this.description = data;
|
||||
this.getAvailableStatuses(this.description.id);
|
||||
this.description.plan.planUsers = this.isActive ? data.plan.planUsers.filter(x => x.isActive === IsActive.Active) : data.plan.planUsers;
|
||||
this.researchers = this.referenceService.getReferencesForTypes(this.description?.plan?.planReferences, [this.referenceTypeService.getResearcherReferenceType()]);
|
||||
this.checkLockStatus(this.description.id);
|
||||
|
@ -216,6 +221,19 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
return this.language.instant('DESCRIPTION-OVERVIEW.INFOS.UNAUTHORIZED-ORCID');
|
||||
}
|
||||
|
||||
getAvailableStatuses(id: Guid){
|
||||
this.descriptionStatusService.getAvailableTransitions(id).pipe(takeUntil(this._destroyed))
|
||||
.subscribe(
|
||||
(statuses) => {
|
||||
this.availableStatusesTransitions = statuses;
|
||||
},
|
||||
(error) => this.httpErrorHandlingService.handleBackedRequestError(error)
|
||||
); }
|
||||
|
||||
hasAvailableFinalizeStatus() {
|
||||
return this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Finalized) != null;
|
||||
}
|
||||
|
||||
checkLockStatus(id: Guid) {
|
||||
this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed))
|
||||
.subscribe({
|
||||
|
@ -290,8 +308,8 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
return this.authentication.currentAccountIsAuthenticated();
|
||||
}
|
||||
|
||||
isDraftDescription(description: Description) {
|
||||
return description.status == DescriptionStatusEnum.Draft;
|
||||
isNotFinalizedDescription(description: Description) {
|
||||
return description?.status?.internalStatus != DescriptionStatusEnum.Finalized;
|
||||
}
|
||||
|
||||
editClicked(description: Description) {
|
||||
|
@ -426,7 +444,30 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
});
|
||||
}
|
||||
|
||||
finalize(description: Description) {
|
||||
persistStatus(status: DescriptionStatus, description: Description) {
|
||||
if (status.internalStatus != null && status.internalStatus === DescriptionStatusEnum.Finalized) {
|
||||
this.finalize(description, status.id);
|
||||
} else if (status.internalStatus != null && description.status.internalStatus === DescriptionStatusEnum.Finalized){
|
||||
this.reverseFinalization(description, status.id);
|
||||
} else {
|
||||
// other statuses
|
||||
const descriptionStatusPersist: DescriptionStatusPersist = {
|
||||
id: description.id,
|
||||
statusId: status.id,
|
||||
hash: description.hash
|
||||
};
|
||||
this.descriptionService.persistStatus(descriptionStatusPersist).pipe(takeUntil(this._destroyed))
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.reloadPage();
|
||||
this.onUpdateCallbackSuccess()
|
||||
},
|
||||
error: (error: any) => this.onUpdateCallbackError(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
finalize(description: Description, statusId: Guid) {
|
||||
|
||||
this.descriptionService.validate([description.id]).pipe(takeUntil(this._destroyed))
|
||||
.subscribe({
|
||||
|
@ -448,7 +489,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
if (result) {
|
||||
const descriptionStatusPersist: DescriptionStatusPersist = {
|
||||
id: description.id,
|
||||
status: DescriptionStatusEnum.Finalized,
|
||||
statusId: statusId,
|
||||
hash: description.hash
|
||||
};
|
||||
this.descriptionService.persistStatus(descriptionStatusPersist).pipe(takeUntil(this._destroyed))
|
||||
|
@ -472,10 +513,10 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
}
|
||||
|
||||
hasReversableStatus(description: Description): boolean {
|
||||
return description.plan.status == PlanStatusEnum.Draft && description.status == DescriptionStatusEnum.Finalized && this.canFinalize
|
||||
return description.plan.status == PlanStatusEnum.Draft && description?.status?.internalStatus == DescriptionStatusEnum.Finalized && this.canFinalize && this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Draft) != null
|
||||
}
|
||||
|
||||
reverseFinalization(description: Description) {
|
||||
reverseFinalization(description: Description, statusId: Guid) {
|
||||
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||
restoreFocus: false,
|
||||
data: {
|
||||
|
@ -489,7 +530,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
if (result) {
|
||||
const planUserRemovePersist: DescriptionStatusPersist = {
|
||||
id: description.id,
|
||||
status: DescriptionStatusEnum.Draft,
|
||||
statusId: statusId,
|
||||
hash: description.hash
|
||||
};
|
||||
this.descriptionService.persistStatus(planUserRemovePersist).pipe(takeUntil(this._destroyed))
|
||||
|
@ -512,7 +553,9 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
|||
nameof<Description>(x => x.id),
|
||||
nameof<Description>(x => x.label),
|
||||
nameof<Description>(x => x.description),
|
||||
nameof<Description>(x => x.status),
|
||||
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||
nameof<Description>(x => x.updatedAt),
|
||||
nameof<Description>(x => x.belongsToCurrentTenant),
|
||||
nameof<Description>(x => x.hash),
|
||||
|
|
|
@ -44,6 +44,7 @@ import { PlanFilterDialogComponent } from './filtering/plan-filter-dialog/plan-f
|
|||
import { PlanListingFilters } from './filtering/plan-filter.component';
|
||||
import { Lookup } from '@common/model/lookup';
|
||||
import { MatSelectChange } from '@angular/material/select';
|
||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||
|
||||
@Component({
|
||||
selector: 'app-plan-listing-component',
|
||||
|
@ -513,10 +514,11 @@ export class PlanListingComponent extends BaseListingComponent<BasePlan, PlanLoo
|
|||
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.sectionId)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'), [nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.sectionId)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
||||
|
||||
[nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
||||
[nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.label)].join('.'),
|
||||
|
|
|
@ -50,6 +50,7 @@ import { PlanFinalizeDialogComponent, PlanFinalizeDialogOutput } from '../plan-f
|
|||
import { PlanInvitationDialogComponent } from '../invitation/dialog/plan-invitation-dialog.component';
|
||||
import { NewVersionPlanDialogComponent } from '../new-version-dialog/plan-new-version-dialog.component';
|
||||
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||
|
||||
@Component({
|
||||
selector: 'app-plan-overview',
|
||||
|
@ -133,9 +134,9 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
|||
this.plan.otherPlanVersions = data.otherPlanVersions?.filter(x => x.isActive === IsActive.Active) || null;
|
||||
if (this.plan.descriptions) {
|
||||
if (this.plan.status == PlanStatusEnum.Finalized) {
|
||||
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatusEnum.Finalized);
|
||||
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus === DescriptionStatusEnum.Finalized);
|
||||
} else {
|
||||
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status !== DescriptionStatusEnum.Canceled);
|
||||
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus !== DescriptionStatusEnum.Canceled);
|
||||
}
|
||||
}
|
||||
if (data.entityDois && data.entityDois.length > 0) this.plan.entityDois = data.entityDois.filter(x => x.isActive === IsActive.Active);
|
||||
|
@ -660,7 +661,9 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
|||
[nameof<Plan>(x => x.entityDois), nameof<EntityDoi>(x => x.isActive)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
||||
[nameof<Plan>(x => x.planUsers), nameof<PlanUser>(x => x.id)].join('.'),
|
||||
[nameof<Plan>(x => x.planUsers), nameof<PlanUser>(x => x.sectionId)].join('.'),
|
||||
|
|
|
@ -263,9 +263,9 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
|||
if (data) {
|
||||
if (data.descriptions) {
|
||||
if (data.status == PlanStatusEnum.Finalized) {
|
||||
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatusEnum.Finalized);
|
||||
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status.internalStatus === DescriptionStatusEnum.Finalized);
|
||||
} else {
|
||||
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status !== DescriptionStatusEnum.Canceled);
|
||||
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status.internalStatus !== DescriptionStatusEnum.Canceled);
|
||||
}
|
||||
}
|
||||
if (data.planDescriptionTemplates) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import { Guid } from '@common/types/guid';
|
|||
import { takeUntil, tap } from 'rxjs/operators';
|
||||
import { nameof } from 'ts-simple-nameof';
|
||||
import { EntityDoi } from '@app/core/model/entity-doi/entity-doi';
|
||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||
|
||||
@Injectable()
|
||||
export class PlanEditorEntityResolver extends BaseEditorResolver {
|
||||
|
@ -56,7 +57,9 @@ export class PlanEditorEntityResolver extends BaseEditorResolver {
|
|||
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.id)].join('.'),
|
||||
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.sectionId)].join('.'),
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
</mat-expansion-panel-header>
|
||||
<div *ngIf="plan.descriptions && plan.descriptions.length > 0">
|
||||
<div *ngFor="let description of plan.descriptions" class="row pl-3 descriptions">
|
||||
<mat-icon *ngIf="description.status == descriptionStatusEnum.Draft" class="col-1 draft-bookmark">bookmark</mat-icon>
|
||||
<mat-icon *ngIf="description.status == descriptionStatusEnum.Finalized" class="col-1 finalized-bookmark">bookmark</mat-icon>
|
||||
<h4 *ngIf="description.status == descriptionStatusEnum.Draft" class="col-11 ml-auto mt-1 mb-4">
|
||||
<span>{{ 'TYPES.DESCRIPTION-STATUS.DRAFT' | translate }}
|
||||
<mat-icon *ngIf="description?.status?.internalStatus == descriptionStatusEnum.Draft" class="col-1 draft-bookmark">bookmark</mat-icon>
|
||||
<mat-icon *ngIf="description?.status?.internalStatus == descriptionStatusEnum.Finalized" class="col-1 finalized-bookmark">bookmark</mat-icon>
|
||||
<h4 *ngIf="description.status?.internalStatus == descriptionStatusEnum.Draft" class="col-11 ml-auto mt-1 mb-4">
|
||||
<span>{{ description?.status?.name}}
|
||||
<ng-container *ngIf="!isDescriptionValid(description.id)">
|
||||
({{'PLAN-FINALISE-DIALOG.INVALID' | translate}})
|
||||
</ng-container>
|
||||
|
@ -41,7 +41,7 @@
|
|||
{{ description.label }}
|
||||
<i *ngIf="(descriptionValidationOutputMap.get(description.id) != descriptionValidationOutputEnum.Invalid) && (descriptionValidationOutputMap.get(description.id) != descriptionValidationOutputEnum.Valid)" class="fa fa-spinner fa-spin" ></i>
|
||||
</h4>
|
||||
<h4 *ngIf="description.status == descriptionStatusEnum.Finalized" class="col-11 ml-auto mt-1 mb-4">{{ description.label }}</h4>
|
||||
<h4 *ngIf="description.status.internalStatus == descriptionStatusEnum.Finalized" class="col-11 ml-auto mt-1 mb-4">{{ description.label }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!plan.descriptions" class="emptyList">{{ 'PLAN-FINALISE-DIALOG.EMPTY' | translate }} </div>
|
||||
|
|
|
@ -74,7 +74,7 @@ export class PlanFinalizeDialogComponent extends BaseComponent implements OnInit
|
|||
|
||||
getFinalizedDescriptions() {
|
||||
if (!this.plan.descriptions) return [];
|
||||
const finalizedDescriptions = this.plan.descriptions.filter(x => x.status === DescriptionStatusEnum.Finalized);
|
||||
const finalizedDescriptions = this.plan.descriptions.filter(x => x.status.internalStatus === DescriptionStatusEnum.Finalized);
|
||||
if (finalizedDescriptions?.length > 0){
|
||||
finalizedDescriptions.forEach(finalize => {
|
||||
this.descriptionValidationOutputMap.set(finalize.id, DescriptionValidationOutput.Valid);
|
||||
|
@ -88,16 +88,16 @@ export class PlanFinalizeDialogComponent extends BaseComponent implements OnInit
|
|||
}
|
||||
|
||||
validateDescriptions(plan: Plan) {
|
||||
if (!plan.descriptions?.some(x => x.status == DescriptionStatusEnum.Draft)) return;
|
||||
if (!plan.descriptions?.some(x => x.status.internalStatus == DescriptionStatusEnum.Draft)) return;
|
||||
|
||||
const draftDescriptions = this.plan.descriptions.filter(x => x.status == DescriptionStatusEnum.Draft) || [];
|
||||
const draftDescriptions = this.plan.descriptions.filter(x => x.status.internalStatus == DescriptionStatusEnum.Draft) || [];
|
||||
if ( draftDescriptions.length > 0){
|
||||
draftDescriptions.forEach(draft => {
|
||||
this.descriptionValidationOutputMap.set(draft.id, DescriptionValidationOutput.Pending);
|
||||
});
|
||||
}
|
||||
|
||||
this.descriptionService.validate(plan.descriptions.filter(x => x.status == DescriptionStatusEnum.Draft).map(x => x.id)).pipe(takeUntil(this._destroyed),)
|
||||
this.descriptionService.validate(plan.descriptions.filter(x => x.status.internalStatus == DescriptionStatusEnum.Draft).map(x => x.id)).pipe(takeUntil(this._destroyed),)
|
||||
.subscribe(result => {
|
||||
this.validationResults = result;
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue