implement plan status logic (in progress)
This commit is contained in:
parent
a7a223d2c6
commit
21fd258181
|
@ -50,6 +50,7 @@ public class AuditableAction {
|
||||||
public static final EventId Plan_GetPublicXml = new EventId(5017, "Plan_GetPublicXml");
|
public static final EventId Plan_GetPublicXml = new EventId(5017, "Plan_GetPublicXml");
|
||||||
public static final EventId Plan_ExportPublic = new EventId(5018, "Plan_ExportPublic");
|
public static final EventId Plan_ExportPublic = new EventId(5018, "Plan_ExportPublic");
|
||||||
public static final EventId Plan_PublicClone = new EventId(5019, "Plan_PublicClone");
|
public static final EventId Plan_PublicClone = new EventId(5019, "Plan_PublicClone");
|
||||||
|
public static final EventId Plan_SetStatus = new EventId(5020, "Plan_SetStatus");
|
||||||
|
|
||||||
|
|
||||||
public static final EventId Description_Query = new EventId(6000, "Description_Query");
|
public static final EventId Description_Query = new EventId(6000, "Description_Query");
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.opencdmp.model;
|
package org.opencdmp.model;
|
||||||
|
|
||||||
import org.opencdmp.commons.enums.PlanAccessType;
|
import org.opencdmp.commons.enums.PlanAccessType;
|
||||||
import org.opencdmp.commons.enums.PlanStatus;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -36,7 +35,7 @@ public class PublicPlan {
|
||||||
|
|
||||||
public static final String _publishedAt = "publishedAt";
|
public static final String _publishedAt = "publishedAt";
|
||||||
|
|
||||||
private PlanStatus status;
|
private PublicPlanStatus status;
|
||||||
public static final String _status = "status";
|
public static final String _status = "status";
|
||||||
|
|
||||||
private UUID groupId;
|
private UUID groupId;
|
||||||
|
@ -118,11 +117,11 @@ public class PublicPlan {
|
||||||
this.publishedAt = publishedAt;
|
this.publishedAt = publishedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlanStatus getStatus() {
|
public PublicPlanStatus getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(PlanStatus status) {
|
public void setStatus(PublicPlanStatus status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package org.opencdmp.model;
|
||||||
|
|
||||||
|
|
||||||
|
import org.opencdmp.commons.enums.PlanStatus;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PublicPlanStatus {
|
||||||
|
|
||||||
|
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 PlanStatus 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 PlanStatus getInternalStatus() {
|
||||||
|
return internalStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInternalStatus(PlanStatus internalStatus) {
|
||||||
|
this.internalStatus = internalStatus;
|
||||||
|
}
|
||||||
|
}
|
|
@ -186,7 +186,7 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
|
||||||
Map<UUID, PublicDescriptionStatus> itemMap;
|
Map<UUID, PublicDescriptionStatus> itemMap;
|
||||||
if (!fields.hasOtherField(this.asIndexer(PublicDescriptionStatus._id))) {
|
if (!fields.hasOtherField(this.asIndexer(PublicDescriptionStatus._id))) {
|
||||||
itemMap = this.asEmpty(
|
itemMap = this.asEmpty(
|
||||||
data.stream().map(DescriptionEntity::getDescriptionTemplateId).distinct().collect(Collectors.toList()),
|
data.stream().map(DescriptionEntity::getStatusId).distinct().collect(Collectors.toList()),
|
||||||
x -> {
|
x -> {
|
||||||
PublicDescriptionStatus item = new PublicDescriptionStatus();
|
PublicDescriptionStatus item = new PublicDescriptionStatus();
|
||||||
item.setId(x);
|
item.setId(x);
|
||||||
|
|
|
@ -71,6 +71,9 @@ public class PublicPlanBuilder extends BaseBuilder<PublicPlan, PlanEntity> {
|
||||||
FieldSet otherPlanVersionsFields = fields.extractPrefixed(this.asPrefix(PublicPlan._otherPlanVersions));
|
FieldSet otherPlanVersionsFields = fields.extractPrefixed(this.asPrefix(PublicPlan._otherPlanVersions));
|
||||||
Map<UUID, List<PublicPlan>> otherPlanVersionsMap = this.collectOtherPlanVersions(otherPlanVersionsFields, data);
|
Map<UUID, List<PublicPlan>> otherPlanVersionsMap = this.collectOtherPlanVersions(otherPlanVersionsFields, data);
|
||||||
|
|
||||||
|
FieldSet planStatusFields = fields.extractPrefixed(this.asPrefix(PublicPlan._status));
|
||||||
|
Map<UUID, PublicPlanStatus> planStatusItemsMap = this.collectPlanStatuses(planStatusFields, data);
|
||||||
|
|
||||||
for (PlanEntity d : data) {
|
for (PlanEntity d : data) {
|
||||||
PublicPlan m = new PublicPlan();
|
PublicPlan m = new PublicPlan();
|
||||||
if (fields.hasField(this.asIndexer(PublicPlan._id))) m.setId(d.getId());
|
if (fields.hasField(this.asIndexer(PublicPlan._id))) m.setId(d.getId());
|
||||||
|
@ -80,7 +83,7 @@ public class PublicPlanBuilder extends BaseBuilder<PublicPlan, PlanEntity> {
|
||||||
if (fields.hasField(this.asIndexer(PublicPlan._finalizedAt))) m.setFinalizedAt(d.getFinalizedAt());
|
if (fields.hasField(this.asIndexer(PublicPlan._finalizedAt))) m.setFinalizedAt(d.getFinalizedAt());
|
||||||
if (fields.hasField(this.asIndexer(PublicPlan._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
|
if (fields.hasField(this.asIndexer(PublicPlan._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
|
||||||
if (fields.hasField(this.asIndexer(PublicPlan._accessType))) m.setAccessType(d.getAccessType());
|
if (fields.hasField(this.asIndexer(PublicPlan._accessType))) m.setAccessType(d.getAccessType());
|
||||||
if (fields.hasField(this.asIndexer(PublicPlan._status))) m.setStatus(d.getStatus());
|
if (!planStatusFields.isEmpty() && planStatusItemsMap != null && planStatusItemsMap.containsKey(d.getStatusId())) m.setStatus(planStatusItemsMap.get(d.getStatusId()));
|
||||||
if (fields.hasField(this.asIndexer(PublicPlan._groupId))) m.setGroupId(d.getGroupId());
|
if (fields.hasField(this.asIndexer(PublicPlan._groupId))) m.setGroupId(d.getGroupId());
|
||||||
if (fields.hasField(this.asIndexer(PublicPlan._accessType))) m.setAccessType(d.getAccessType());
|
if (fields.hasField(this.asIndexer(PublicPlan._accessType))) m.setAccessType(d.getAccessType());
|
||||||
|
|
||||||
|
@ -190,4 +193,34 @@ public class PublicPlanBuilder extends BaseBuilder<PublicPlan, PlanEntity> {
|
||||||
return itemMap;
|
return itemMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<UUID, PublicPlanStatus> collectPlanStatuses(FieldSet fields, List<PlanEntity> data) throws MyApplicationException {
|
||||||
|
if (fields.isEmpty() || data.isEmpty())
|
||||||
|
return null;
|
||||||
|
this.logger.debug("checking related - {}", PublicPlanStatus.class.getSimpleName());
|
||||||
|
|
||||||
|
Map<UUID, PublicPlanStatus> itemMap;
|
||||||
|
if (!fields.hasOtherField(this.asIndexer(PublicPlanStatus._id))) {
|
||||||
|
itemMap = this.asEmpty(
|
||||||
|
data.stream().map(PlanEntity::getStatusId).distinct().collect(Collectors.toList()),
|
||||||
|
x -> {
|
||||||
|
PublicPlanStatus item = new PublicPlanStatus();
|
||||||
|
item.setId(x);
|
||||||
|
return item;
|
||||||
|
},
|
||||||
|
PublicPlanStatus::getId);
|
||||||
|
} else {
|
||||||
|
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(PublicPlanStatus._id);
|
||||||
|
PlanStatusQuery q = this.queryFactory.query(PlanStatusQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(PlanEntity::getStatusId).distinct().collect(Collectors.toList()));
|
||||||
|
itemMap = this.builderFactory.builder(PublicPlanStatusBuilder.class).authorize(this.authorize).asForeignKey(q, clone, PublicPlanStatus::getId);
|
||||||
|
}
|
||||||
|
if (!fields.hasField(PublicPlanStatus._id)) {
|
||||||
|
itemMap.forEach((id, item) -> {
|
||||||
|
if (item != null)
|
||||||
|
item.setId(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemMap;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
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.PlanStatusEntity;
|
||||||
|
import org.opencdmp.model.PublicPlanStatus;
|
||||||
|
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 PublicPlanStatusBuilder extends BaseBuilder<PublicPlanStatus, PlanStatusEntity> {
|
||||||
|
|
||||||
|
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
|
||||||
|
@Autowired
|
||||||
|
public PublicPlanStatusBuilder(
|
||||||
|
ConventionService conventionService) {
|
||||||
|
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicPlanStatusBuilder.class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PublicPlanStatusBuilder authorize(EnumSet<AuthorizationFlags> values) {
|
||||||
|
this.authorize = values;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PublicPlanStatus> build(FieldSet fields, List<PlanStatusEntity> 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<PublicPlanStatus> models = new ArrayList<>();
|
||||||
|
for (PlanStatusEntity d : data) {
|
||||||
|
PublicPlanStatus m = new PublicPlanStatus();
|
||||||
|
if (fields.hasField(this.asIndexer(PublicPlanStatus._id))) m.setId(d.getId());
|
||||||
|
if (fields.hasField(this.asIndexer(PublicPlanStatus._name))) m.setName(d.getName());
|
||||||
|
if (fields.hasField(this.asIndexer(PublicPlanStatus._internalStatus))) m.setInternalStatus(d.getInternalStatus());
|
||||||
|
models.add(m);
|
||||||
|
}
|
||||||
|
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
}
|
|
@ -87,7 +87,7 @@ public class PlanBuilder extends BaseBuilder<Plan, PlanEntity> {
|
||||||
|
|
||||||
List<Plan> models = new ArrayList<>();
|
List<Plan> models = new ArrayList<>();
|
||||||
|
|
||||||
FieldSet statusFields = fields.extractPrefixed(this.asPrefix(Description._status));
|
FieldSet statusFields = fields.extractPrefixed(this.asPrefix(Plan._status));
|
||||||
Map<UUID, PlanStatus> statusItemsMap = this.collectPlanStatuses(statusFields, data);
|
Map<UUID, PlanStatus> statusItemsMap = this.collectPlanStatuses(statusFields, data);
|
||||||
|
|
||||||
FieldSet entityDoisFields = fields.extractPrefixed(this.asPrefix(Plan._entityDois));
|
FieldSet entityDoisFields = fields.extractPrefixed(this.asPrefix(Plan._entityDois));
|
||||||
|
|
|
@ -243,7 +243,7 @@ public class PlanPersist {
|
||||||
.must(() -> this.isDescriptionTemplateMultiplicityValid(finalPlanBlueprintEntity, item.getId()))
|
.must(() -> this.isDescriptionTemplateMultiplicityValid(finalPlanBlueprintEntity, item.getId()))
|
||||||
.failOn(PlanPersist._descriptionTemplates).failWith(this.messageSource.getMessage("Validation.InvalidDescriptionTemplateMultiplicityOnPlan", new Object[]{PlanPersist._descriptionTemplates}, LocaleContextHolder.getLocale())),
|
.failOn(PlanPersist._descriptionTemplates).failWith(this.messageSource.getMessage("Validation.InvalidDescriptionTemplateMultiplicityOnPlan", new Object[]{PlanPersist._descriptionTemplates}, LocaleContextHolder.getLocale())),
|
||||||
this.refSpec()
|
this.refSpec()
|
||||||
.iff(() -> !this.isNull(item.getProperties()))
|
.iff(() -> !this.isNull(item.getProperties()) && finalStatusEntity != null)
|
||||||
.on(PlanPersist._properties)
|
.on(PlanPersist._properties)
|
||||||
.over(item.getProperties())
|
.over(item.getProperties())
|
||||||
.using(() -> this.validatorFactory.validator(PlanPropertiesPersist.PlanPropertiesPersistValidator.class).setStatus(finalStatusEntity.getInternalStatus()).withDefinition(definition)),
|
.using(() -> this.validatorFactory.validator(PlanPropertiesPersist.PlanPropertiesPersistValidator.class).setStatus(finalStatusEntity.getInternalStatus()).withDefinition(definition)),
|
||||||
|
|
|
@ -97,6 +97,8 @@ public class Plan {
|
||||||
private List<Plan> otherPlanVersions;
|
private List<Plan> otherPlanVersions;
|
||||||
public static final String _otherPlanVersions = "otherPlanVersions";
|
public static final String _otherPlanVersions = "otherPlanVersions";
|
||||||
|
|
||||||
|
private List<PlanStatus> availableTransitions;
|
||||||
|
public static final String _availableTransitions = "availableTransitions";
|
||||||
|
|
||||||
private Boolean belongsToCurrentTenant;
|
private Boolean belongsToCurrentTenant;
|
||||||
public static final String _belongsToCurrentTenant = "belongsToCurrentTenant";
|
public static final String _belongsToCurrentTenant = "belongsToCurrentTenant";
|
||||||
|
@ -318,4 +320,12 @@ public class Plan {
|
||||||
public void setOtherPlanVersions(List<Plan> otherPlanVersions) {
|
public void setOtherPlanVersions(List<Plan> otherPlanVersions) {
|
||||||
this.otherPlanVersions = otherPlanVersions;
|
this.otherPlanVersions = otherPlanVersions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<PlanStatus> getAvailableTransitions() {
|
||||||
|
return availableTransitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvailableTransitions(List<PlanStatus> availableTransitions) {
|
||||||
|
this.availableTransitions = availableTransitions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -425,6 +425,8 @@ public class PlanQuery extends QueryBase<PlanEntity> {
|
||||||
return PlanEntity._version;
|
return PlanEntity._version;
|
||||||
else if (item.match(Plan._status))
|
else if (item.match(Plan._status))
|
||||||
return PlanEntity._status;
|
return PlanEntity._status;
|
||||||
|
else if (item.prefix(Plan._status))
|
||||||
|
return PlanEntity._statusId;
|
||||||
else if (item.match(Plan._properties))
|
else if (item.match(Plan._properties))
|
||||||
return PlanEntity._properties;
|
return PlanEntity._properties;
|
||||||
else if (item.prefix(Plan._properties))
|
else if (item.prefix(Plan._properties))
|
||||||
|
@ -475,6 +477,7 @@ public class PlanQuery extends QueryBase<PlanEntity> {
|
||||||
item.setLabel(QueryBase.convertSafe(tuple, columns, PlanEntity._label, String.class));
|
item.setLabel(QueryBase.convertSafe(tuple, columns, PlanEntity._label, String.class));
|
||||||
item.setVersion(QueryBase.convertSafe(tuple, columns, PlanEntity._version, Short.class));
|
item.setVersion(QueryBase.convertSafe(tuple, columns, PlanEntity._version, Short.class));
|
||||||
item.setStatus(QueryBase.convertSafe(tuple, columns, PlanEntity._status, PlanStatus.class));
|
item.setStatus(QueryBase.convertSafe(tuple, columns, PlanEntity._status, PlanStatus.class));
|
||||||
|
item.setStatusId(QueryBase.convertSafe(tuple, columns, PlanEntity._statusId, UUID.class));
|
||||||
item.setVersionStatus(QueryBase.convertSafe(tuple, columns, PlanEntity._versionStatus, PlanVersionStatus.class));
|
item.setVersionStatus(QueryBase.convertSafe(tuple, columns, PlanEntity._versionStatus, PlanVersionStatus.class));
|
||||||
item.setProperties(QueryBase.convertSafe(tuple, columns, PlanEntity._properties, String.class));
|
item.setProperties(QueryBase.convertSafe(tuple, columns, PlanEntity._properties, String.class));
|
||||||
item.setGroupId(QueryBase.convertSafe(tuple, columns, PlanEntity._groupId, UUID.class));
|
item.setGroupId(QueryBase.convertSafe(tuple, columns, PlanEntity._groupId, UUID.class));
|
||||||
|
|
|
@ -266,8 +266,10 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
|
|
||||||
PlanEntity plan = this.entityManager.find(PlanEntity.class, data.getPlanId(), true);
|
PlanEntity plan = this.entityManager.find(PlanEntity.class, data.getPlanId(), true);
|
||||||
if (plan == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getPlanId(), Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (plan == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{data.getPlanId(), Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
PlanStatusEntity planStatusEntity = this.entityManager.find(PlanStatusEntity.class, plan.getStatusId(), true);
|
||||||
|
if (planStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{plan.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
if (plan.getStatus().equals(PlanStatus.Finalized) && isUpdate) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
|
if (planStatusEntity.getInternalStatus() != null && planStatusEntity.getInternalStatus().equals(PlanStatus.Finalized) && isUpdate) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
|
||||||
|
|
||||||
data.setLabel(model.getLabel());
|
data.setLabel(model.getLabel());
|
||||||
data.setDescription(model.getDescription());
|
data.setDescription(model.getDescription());
|
||||||
|
@ -504,7 +506,9 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.FinalizeDescription);
|
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.FinalizeDescription);
|
||||||
PlanEntity planEntity = this.entityManager.find(PlanEntity.class, data.getPlanId(), true);
|
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 == 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());
|
PlanStatusEntity planStatusEntity = this.entityManager.find(PlanStatusEntity.class, planEntity.getStatusId(), true);
|
||||||
|
if (planStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{planEntity.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
if (planStatusEntity.getInternalStatus() != null && planStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) throw new MyValidationException(this.errors.getPlanIsFinalized().getCode(), this.errors.getPlanIsFinalized().getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
data.setStatusId(model.getStatusId());
|
data.setStatusId(model.getStatusId());
|
||||||
|
@ -533,11 +537,14 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) throw new MyApplicationException("finalized status not found");
|
||||||
|
|
||||||
for (DescriptionEntity description: descriptions) {
|
for (DescriptionEntity description: descriptions) {
|
||||||
DescriptionValidationResult descriptionValidationResult = new DescriptionValidationResult(description.getId(), DescriptionValidationOutput.Invalid);
|
DescriptionValidationResult descriptionValidationResult = new DescriptionValidationResult(description.getId(), DescriptionValidationOutput.Invalid);
|
||||||
|
|
||||||
DescriptionPersist.DescriptionPersistValidator validator = this.validatorFactory.validator(DescriptionPersist.DescriptionPersistValidator.class);
|
DescriptionPersist.DescriptionPersistValidator validator = this.validatorFactory.validator(DescriptionPersist.DescriptionPersistValidator.class);
|
||||||
validator.validate(this.buildDescriptionPersist(description));
|
validator.validate(this.buildDescriptionPersist(description, statusEntity.getId()));
|
||||||
if (validator.result().isValid()) descriptionValidationResult.setResult(DescriptionValidationOutput.Valid);
|
if (validator.result().isValid()) descriptionValidationResult.setResult(DescriptionValidationOutput.Valid);
|
||||||
|
|
||||||
descriptionValidationResults.add(descriptionValidationResult);
|
descriptionValidationResults.add(descriptionValidationResult);
|
||||||
|
@ -1013,7 +1020,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
|
|
||||||
//region build persist
|
//region build persist
|
||||||
|
|
||||||
private @NotNull DescriptionPersist buildDescriptionPersist(DescriptionEntity data) throws InvalidApplicationException {
|
private @NotNull DescriptionPersist buildDescriptionPersist(DescriptionEntity data, UUID statusId) throws InvalidApplicationException {
|
||||||
DescriptionPersist persist = new DescriptionPersist();
|
DescriptionPersist persist = new DescriptionPersist();
|
||||||
if (data == null) return persist;
|
if (data == null) return persist;
|
||||||
|
|
||||||
|
@ -1022,8 +1029,7 @@ public class DescriptionServiceImpl implements DescriptionService {
|
||||||
|
|
||||||
persist.setId(data.getId());
|
persist.setId(data.getId());
|
||||||
persist.setLabel(data.getLabel());
|
persist.setLabel(data.getLabel());
|
||||||
DescriptionStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
persist.setStatusId(statusId);
|
||||||
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
|
|
||||||
persist.setDescription(data.getDescription());
|
persist.setDescription(data.getDescription());
|
||||||
persist.setDescriptionTemplateId(data.getDescriptionTemplateId());
|
persist.setDescriptionTemplateId(data.getDescriptionTemplateId());
|
||||||
persist.setPlanId(data.getPlanId());
|
persist.setPlanId(data.getPlanId());
|
||||||
|
|
|
@ -34,9 +34,7 @@ public interface PlanService {
|
||||||
|
|
||||||
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException;
|
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException;
|
||||||
|
|
||||||
void finalize(UUID id, List<UUID> descriptionIds) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException;
|
void setStatus(UUID id, UUID newStatusId, List<UUID> descriptionIds) throws InvalidApplicationException, IOException;
|
||||||
|
|
||||||
void undoFinalize(UUID id, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException;
|
|
||||||
|
|
||||||
PlanValidationResult validate(UUID id) throws InvalidApplicationException;
|
PlanValidationResult validate(UUID id) throws InvalidApplicationException;
|
||||||
|
|
||||||
|
|
|
@ -386,7 +386,10 @@ public class PlanServiceImpl implements PlanService {
|
||||||
planQuery.setOrder(new Ordering().addDescending(Plan._version));
|
planQuery.setOrder(new Ordering().addDescending(Plan._version));
|
||||||
previousPlan = planQuery.count() > 0 ? planQuery.collect().getFirst() : null;
|
previousPlan = planQuery.count() > 0 ? planQuery.collect().getFirst() : null;
|
||||||
if (previousPlan != null){
|
if (previousPlan != null){
|
||||||
if (previousPlan.getStatus().equals(PlanStatus.Finalized)) previousPlan.setVersionStatus(PlanVersionStatus.Current);
|
PlanStatusEntity previousPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, previousPlan.getStatusId(), true);
|
||||||
|
if (previousPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{previousPlan.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
if (previousPlanStatusEntity.getInternalStatus() != null && previousPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) previousPlan.setVersionStatus(PlanVersionStatus.Current);
|
||||||
else previousPlan.setVersionStatus(PlanVersionStatus.NotFinalized);
|
else previousPlan.setVersionStatus(PlanVersionStatus.NotFinalized);
|
||||||
this.entityManager.merge(previousPlan);
|
this.entityManager.merge(previousPlan);
|
||||||
}
|
}
|
||||||
|
@ -428,6 +431,9 @@ public class PlanServiceImpl implements PlanService {
|
||||||
.count();
|
.count();
|
||||||
if (notFinalizedCount > 0) throw new MyValidationException(this.errors.getPlanNewVersionAlreadyCreatedDraft().getCode(), this.errors.getPlanNewVersionAlreadyCreatedDraft().getMessage());
|
if (notFinalizedCount > 0) throw new MyValidationException(this.errors.getPlanNewVersionAlreadyCreatedDraft().getCode(), this.errors.getPlanNewVersionAlreadyCreatedDraft().getMessage());
|
||||||
|
|
||||||
|
PlanStatusEntity startingPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, this.planWorkflowService.getWorkFlowDefinition().getStartingStatusId(), true);
|
||||||
|
if (startingPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{this.planWorkflowService.getWorkFlowDefinition().getStartingStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
PlanEntity newPlan = new PlanEntity();
|
PlanEntity newPlan = new PlanEntity();
|
||||||
newPlan.setId(UUID.randomUUID());
|
newPlan.setId(UUID.randomUUID());
|
||||||
newPlan.setIsActive(IsActive.Active);
|
newPlan.setIsActive(IsActive.Active);
|
||||||
|
@ -440,6 +446,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
newPlan.setLabel(model.getLabel());
|
newPlan.setLabel(model.getLabel());
|
||||||
newPlan.setLanguage(oldPlanEntity.getLanguage());
|
newPlan.setLanguage(oldPlanEntity.getLanguage());
|
||||||
newPlan.setStatus(PlanStatus.Draft);
|
newPlan.setStatus(PlanStatus.Draft);
|
||||||
|
newPlan.setStatusId(startingPlanStatusEntity.getId());
|
||||||
newPlan.setProperties(oldPlanEntity.getProperties());
|
newPlan.setProperties(oldPlanEntity.getProperties());
|
||||||
newPlan.setBlueprintId(model.getBlueprintId());
|
newPlan.setBlueprintId(model.getBlueprintId());
|
||||||
newPlan.setAccessType(oldPlanEntity.getAccessType());
|
newPlan.setAccessType(oldPlanEntity.getAccessType());
|
||||||
|
@ -591,7 +598,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
|
|
||||||
this.entityManager.flush();
|
this.entityManager.flush();
|
||||||
|
|
||||||
this.updateVersionStatusAndSave(newPlan, PlanStatus.Draft, newPlan.getStatus());
|
this.updateVersionStatusAndSave(newPlan, PlanStatus.Draft, startingPlanStatusEntity.getInternalStatus());
|
||||||
|
|
||||||
this.entityManager.flush();
|
this.entityManager.flush();
|
||||||
|
|
||||||
|
@ -855,9 +862,11 @@ public class PlanServiceImpl implements PlanService {
|
||||||
|
|
||||||
|
|
||||||
private void updateVersionStatusAndSave(PlanEntity data, PlanStatus previousStatus, PlanStatus newStatus) throws InvalidApplicationException {
|
private void updateVersionStatusAndSave(PlanEntity data, PlanStatus previousStatus, PlanStatus newStatus) throws InvalidApplicationException {
|
||||||
if (previousStatus.equals(newStatus))
|
if (previousStatus == null && newStatus == null)
|
||||||
return;
|
return;
|
||||||
if (previousStatus.equals(PlanStatus.Finalized) && newStatus.equals(PlanStatus.Draft)){
|
if (previousStatus != null && previousStatus.equals(newStatus))
|
||||||
|
return;
|
||||||
|
if (previousStatus != null && previousStatus.equals(PlanStatus.Finalized) && (newStatus == null || newStatus.equals(PlanStatus.Draft))){
|
||||||
boolean alreadyCreatedNewVersion = this.queryFactory.query(PlanQuery.class).disableTracking()
|
boolean alreadyCreatedNewVersion = this.queryFactory.query(PlanQuery.class).disableTracking()
|
||||||
.versionStatuses(PlanVersionStatus.NotFinalized, PlanVersionStatus.Current)
|
.versionStatuses(PlanVersionStatus.NotFinalized, PlanVersionStatus.Current)
|
||||||
.excludedIds(data.getId())
|
.excludedIds(data.getId())
|
||||||
|
@ -870,7 +879,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
this.entityManager.merge(data);
|
this.entityManager.merge(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newStatus.equals(PlanStatus.Finalized)) {
|
if (newStatus != null && newStatus.equals(PlanStatus.Finalized)) {
|
||||||
List<PlanEntity> latestVersionPlans = this.queryFactory.query(PlanQuery.class)
|
List<PlanEntity> latestVersionPlans = this.queryFactory.query(PlanQuery.class)
|
||||||
.versionStatuses(PlanVersionStatus.Current).excludedIds(data.getId())
|
.versionStatuses(PlanVersionStatus.Current).excludedIds(data.getId())
|
||||||
.isActive(IsActive.Active).groupIds(data.getGroupId()).collect();
|
.isActive(IsActive.Active).groupIds(data.getGroupId()).collect();
|
||||||
|
@ -915,6 +924,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
newPlan.setLabel(model.getLabel());
|
newPlan.setLabel(model.getLabel());
|
||||||
newPlan.setLanguage(existingPlanEntity.getLanguage());
|
newPlan.setLanguage(existingPlanEntity.getLanguage());
|
||||||
newPlan.setStatus(PlanStatus.Draft);
|
newPlan.setStatus(PlanStatus.Draft);
|
||||||
|
newPlan.setStatusId(this.planWorkflowService.getWorkFlowDefinition().getStartingStatusId());
|
||||||
newPlan.setProperties(existingPlanEntity.getProperties());
|
newPlan.setProperties(existingPlanEntity.getProperties());
|
||||||
newPlan.setBlueprintId(existingPlanEntity.getBlueprintId());
|
newPlan.setBlueprintId(existingPlanEntity.getBlueprintId());
|
||||||
newPlan.setAccessType(existingPlanEntity.getAccessType());
|
newPlan.setAccessType(existingPlanEntity.getAccessType());
|
||||||
|
@ -1103,6 +1113,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
newPlan.setLabel(model.getLabel());
|
newPlan.setLabel(model.getLabel());
|
||||||
newPlan.setLanguage(existingPlanEntity.getLanguage());
|
newPlan.setLanguage(existingPlanEntity.getLanguage());
|
||||||
newPlan.setStatus(PlanStatus.Draft);
|
newPlan.setStatus(PlanStatus.Draft);
|
||||||
|
newPlan.setStatusId(this.planWorkflowService.getWorkFlowDefinition().getStartingStatusId());
|
||||||
newPlan.setProperties(existingPlanEntity.getProperties());
|
newPlan.setProperties(existingPlanEntity.getProperties());
|
||||||
newPlan.setBlueprintId(blueprintEntityByTenant.getId());
|
newPlan.setBlueprintId(blueprintEntityByTenant.getId());
|
||||||
newPlan.setAccessType(existingPlanEntity.getAccessType());
|
newPlan.setAccessType(existingPlanEntity.getAccessType());
|
||||||
|
@ -1339,7 +1350,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
data.setIsActive(IsActive.Active);
|
data.setIsActive(IsActive.Active);
|
||||||
data.setCreatedAt(Instant.now());
|
data.setCreatedAt(Instant.now());
|
||||||
}
|
}
|
||||||
PlanStatus previousStatus = data.getStatus();
|
// PlanStatus previousStatus = data.getStatus();
|
||||||
|
|
||||||
PlanBlueprintEntity planBlueprintEntity = this.entityManager.find(PlanBlueprintEntity.class, model.getBlueprint(), true);
|
PlanBlueprintEntity planBlueprintEntity = this.entityManager.find(PlanBlueprintEntity.class, model.getBlueprint(), true);
|
||||||
if (planBlueprintEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getBlueprint(), PlanBlueprint.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (planBlueprintEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{model.getBlueprint(), PlanBlueprint.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
@ -1361,7 +1372,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
|
|
||||||
this.entityManager.flush();
|
this.entityManager.flush();
|
||||||
|
|
||||||
this.updateVersionStatusAndSave(data, previousStatus, data.getStatus());
|
// this.updateVersionStatusAndSave(data, previousStatus, data.getStatus());
|
||||||
|
|
||||||
this.entityManager.flush();
|
this.entityManager.flush();
|
||||||
|
|
||||||
|
@ -1587,31 +1598,50 @@ public class PlanServiceImpl implements PlanService {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finalize(UUID id, List<UUID> descriptionIds) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
|
public void setStatus(UUID id, UUID newStatusId, List<UUID> descriptionIds) throws InvalidApplicationException, IOException {
|
||||||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(id)), Permission.FinalizePlan);
|
|
||||||
PlanEntity plan = this.queryFactory.query(PlanQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(id).isActive(IsActive.Active).first();
|
PlanEntity plan = this.queryFactory.query(PlanQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(id).isActive(IsActive.Active).first();
|
||||||
|
if (plan == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
if (plan.getStatusId().equals(newStatusId)) throw new MyApplicationException("Old status equals with new");
|
||||||
|
|
||||||
if (plan == null){
|
PlanStatusEntity oldPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, plan.getStatusId(), true);
|
||||||
throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (oldPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{plan.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
PlanStatusEntity newPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, newStatusId, true);
|
||||||
|
if (newPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{newStatusId, PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
if (oldPlanStatusEntity.getInternalStatus() != null && oldPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) {
|
||||||
|
this.undoFinalize(plan, oldPlanStatusEntity, newPlanStatusEntity);
|
||||||
|
} else if (newPlanStatusEntity.getInternalStatus() != null && newPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) {
|
||||||
|
this.finalize(plan, descriptionIds ,oldPlanStatusEntity, newPlanStatusEntity);
|
||||||
|
} else {
|
||||||
|
plan.setStatusId(newPlanStatusEntity.getId());
|
||||||
|
plan.setUpdatedAt(Instant.now());
|
||||||
|
|
||||||
|
this.entityManager.merge(plan);
|
||||||
|
this.entityManager.flush();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (plan.getStatus().equals(PlanStatus.Finalized)){
|
private void finalize(PlanEntity plan, List<UUID> descriptionIds, PlanStatusEntity oldPlanStatusEntity, PlanStatusEntity newPlanStatusEntity) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
|
||||||
|
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(plan.getId())), Permission.FinalizePlan);
|
||||||
|
|
||||||
|
if (oldPlanStatusEntity.getInternalStatus() != null && oldPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)){
|
||||||
throw new MyApplicationException("Plan is already finalized");
|
throw new MyApplicationException("Plan is already finalized");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.validate(id).getResult().equals(PlanValidationOutput.Invalid)){
|
if (this.validate(plan.getId()).getResult().equals(PlanValidationOutput.Invalid)){
|
||||||
throw new MyApplicationException("Plan is invalid");
|
throw new MyApplicationException("Plan is invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DescriptionEntity> descriptions = this.queryFactory.query(DescriptionQuery.class)
|
List<DescriptionEntity> descriptions = this.queryFactory.query(DescriptionQuery.class)
|
||||||
.authorize(AuthorizationFlags.AllExceptPublic).planIds(id).isActive(IsActive.Active).collect();
|
.authorize(AuthorizationFlags.AllExceptPublic).planIds(plan.getId()).isActive(IsActive.Active).collect();
|
||||||
|
|
||||||
if (!this.conventionService.isListNullOrEmpty(descriptions)) {
|
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();
|
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");
|
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));
|
DescriptionStatusEntity descriptionFinalizedStatusEntity = 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");
|
if (descriptionFinalizedStatusEntity == 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));
|
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");
|
if (canceledStatusEntity == null) throw new MyApplicationException("canceled status not found");
|
||||||
|
@ -1625,7 +1655,7 @@ public class PlanServiceImpl implements PlanService {
|
||||||
if (this.descriptionService.validate(List.of(description.getId())).getFirst().getResult().equals(DescriptionValidationOutput.Invalid)){
|
if (this.descriptionService.validate(List.of(description.getId())).getFirst().getResult().equals(DescriptionValidationOutput.Invalid)){
|
||||||
throw new MyApplicationException("Description is invalid");
|
throw new MyApplicationException("Description is invalid");
|
||||||
}
|
}
|
||||||
if (finalizedStatusEntity != null) description.setStatusId(finalizedStatusEntity.getId());
|
description.setStatusId(descriptionFinalizedStatusEntity.getId());
|
||||||
description.setUpdatedAt(Instant.now());
|
description.setUpdatedAt(Instant.now());
|
||||||
description.setFinalizedAt(Instant.now());
|
description.setFinalizedAt(Instant.now());
|
||||||
this.entityManager.merge(description);
|
this.entityManager.merge(description);
|
||||||
|
@ -1636,13 +1666,12 @@ public class PlanServiceImpl implements PlanService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlanStatus previousStatus = plan.getStatus();
|
plan.setStatusId(newPlanStatusEntity.getId());
|
||||||
plan.setStatus(PlanStatus.Finalized);
|
|
||||||
plan.setUpdatedAt(Instant.now());
|
plan.setUpdatedAt(Instant.now());
|
||||||
plan.setFinalizedAt(Instant.now());
|
plan.setFinalizedAt(Instant.now());
|
||||||
|
|
||||||
this.updateVersionStatusAndSave(plan, previousStatus, plan.getStatus());
|
this.updateVersionStatusAndSave(plan, oldPlanStatusEntity.getInternalStatus(), newPlanStatusEntity.getInternalStatus());
|
||||||
plan.setVersionStatus(PlanVersionStatus.Current);
|
plan.setVersionStatus(PlanVersionStatus.Current);
|
||||||
|
|
||||||
this.entityManager.merge(plan);
|
this.entityManager.merge(plan);
|
||||||
|
@ -1654,24 +1683,21 @@ public class PlanServiceImpl implements PlanService {
|
||||||
this.sendNotification(plan);
|
this.sendNotification(plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undoFinalize(UUID id, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
|
private void undoFinalize(PlanEntity plan, PlanStatusEntity oldPlanStatusEntity, PlanStatusEntity newPlanStatusEntity) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException {
|
||||||
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(id)), Permission.UndoFinalizePlan);
|
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.planAffiliation(plan.getId())), Permission.UndoFinalizePlan);
|
||||||
PlanEntity plan = this.queryFactory.query(PlanQuery.class).authorize(AuthorizationFlags.AllExceptPublic).ids(id).isActive(IsActive.Active).firstAs(fields);
|
|
||||||
|
|
||||||
if (plan == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
if (oldPlanStatusEntity.getInternalStatus() == null && !oldPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) throw new MyApplicationException("Plan is already non finalized");
|
||||||
|
|
||||||
if (!plan.getStatus().equals(PlanStatus.Finalized)) throw new MyApplicationException("Plan is already drafted");
|
|
||||||
|
|
||||||
EntityDoiQuery entityDoiQuery = this.queryFactory.query(EntityDoiQuery.class).types(EntityType.Plan).entityIds(plan.getId()).isActive(IsActive.Active);
|
EntityDoiQuery entityDoiQuery = this.queryFactory.query(EntityDoiQuery.class).types(EntityType.Plan).entityIds(plan.getId()).isActive(IsActive.Active);
|
||||||
if (entityDoiQuery.count() > 0) throw new MyApplicationException("Plan is deposited");
|
if (entityDoiQuery.count() > 0) throw new MyApplicationException("Plan is deposited");
|
||||||
|
|
||||||
plan.setStatus(PlanStatus.Draft);
|
plan.setStatusId(newPlanStatusEntity.getId());
|
||||||
plan.setUpdatedAt(Instant.now());
|
plan.setUpdatedAt(Instant.now());
|
||||||
|
|
||||||
this.entityManager.merge(plan);
|
this.entityManager.merge(plan);
|
||||||
this.entityManager.flush();
|
this.entityManager.flush();
|
||||||
|
|
||||||
this.updateVersionStatusAndSave(plan, PlanStatus.Finalized, plan.getStatus());
|
this.updateVersionStatusAndSave(plan, PlanStatus.Finalized, newPlanStatusEntity.getInternalStatus());
|
||||||
this.entityManager.flush();
|
this.entityManager.flush();
|
||||||
|
|
||||||
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking()
|
PlanQuery planQuery = this.queryFactory.query(PlanQuery.class).disableTracking()
|
||||||
|
@ -1683,7 +1709,10 @@ public class PlanServiceImpl implements PlanService {
|
||||||
planQuery.setOrder(new Ordering().addDescending(Plan._version));
|
planQuery.setOrder(new Ordering().addDescending(Plan._version));
|
||||||
PlanEntity previousPlan = planQuery.count() > 0 ? planQuery.collect().getFirst() : null;
|
PlanEntity previousPlan = planQuery.count() > 0 ? planQuery.collect().getFirst() : null;
|
||||||
if (previousPlan != null){
|
if (previousPlan != null){
|
||||||
if (previousPlan.getStatus().equals(PlanStatus.Finalized)) previousPlan.setVersionStatus(PlanVersionStatus.Current);
|
PlanStatusEntity previousPlanStatusEntity = this.entityManager.find(PlanStatusEntity.class, previousPlan.getStatusId(), true);
|
||||||
|
if (previousPlanStatusEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{previousPlan.getStatusId(), PlanStatusEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
if (previousPlanStatusEntity.getInternalStatus() != null && previousPlanStatusEntity.getInternalStatus().equals(PlanStatus.Finalized)) previousPlan.setVersionStatus(PlanVersionStatus.Current);
|
||||||
else previousPlan.setVersionStatus(PlanVersionStatus.NotFinalized);
|
else previousPlan.setVersionStatus(PlanVersionStatus.NotFinalized);
|
||||||
this.entityManager.merge(previousPlan);
|
this.entityManager.merge(previousPlan);
|
||||||
}
|
}
|
||||||
|
@ -1721,8 +1750,8 @@ public class PlanServiceImpl implements PlanService {
|
||||||
persist.setId(data.getId());
|
persist.setId(data.getId());
|
||||||
persist.setHash(data.getId().toString());
|
persist.setHash(data.getId().toString());
|
||||||
persist.setLabel(data.getLabel());
|
persist.setLabel(data.getLabel());
|
||||||
//TODO status PlanStatusEntity statusEntity = this.queryFactory.query(DescriptionStatusQuery.class).disableTracking().internalStatuses(DescriptionStatus.Finalized).isActive(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.descriptionstatus.DescriptionStatus._id));
|
PlanStatusEntity statusEntity = this.queryFactory.query(PlanStatusQuery.class).disableTracking().internalStatuses(PlanStatus.Finalized).isActives(IsActive.Active).firstAs(new BaseFieldSet().ensure(org.opencdmp.model.planstatus.PlanStatus._id));
|
||||||
// persist.setStatus(PlanStatus.Finalized);
|
if (statusEntity != null) persist.setStatusId(statusEntity.getId());
|
||||||
persist.setDescription(data.getDescription());
|
persist.setDescription(data.getDescription());
|
||||||
persist.setBlueprint(data.getBlueprintId());
|
persist.setBlueprint(data.getBlueprintId());
|
||||||
persist.setAccessType(data.getAccessType());
|
persist.setAccessType(data.getAccessType());
|
||||||
|
@ -2316,7 +2345,6 @@ public class PlanServiceImpl implements PlanService {
|
||||||
|
|
||||||
PlanPersist persist = new PlanPersist();
|
PlanPersist persist = new PlanPersist();
|
||||||
persist.setLabel(label);
|
persist.setLabel(label);
|
||||||
//TODO status persist.setStatus(PlanStatus.Draft);
|
|
||||||
persist.setDescription(planXml.getDescription());
|
persist.setDescription(planXml.getDescription());
|
||||||
persist.setAccessType(planXml.getAccess());
|
persist.setAccessType(planXml.getAccess());
|
||||||
persist.setLanguage(planXml.getLanguage());
|
persist.setLanguage(planXml.getLanguage());
|
||||||
|
@ -2618,7 +2646,6 @@ public class PlanServiceImpl implements PlanService {
|
||||||
PlanPersist persist = new PlanPersist();
|
PlanPersist persist = new PlanPersist();
|
||||||
|
|
||||||
persist.setLabel(planCommonModelConfig.getLabel());
|
persist.setLabel(planCommonModelConfig.getLabel());
|
||||||
// TODO status persist.setStatus(PlanStatus.Draft);
|
|
||||||
persist.setDescription(model.getDescription());
|
persist.setDescription(model.getDescription());
|
||||||
switch (model.getAccessType()) {
|
switch (model.getAccessType()) {
|
||||||
case Public -> persist.setAccessType(PlanAccessType.Public);
|
case Public -> persist.setAccessType(PlanAccessType.Public);
|
||||||
|
|
|
@ -10,10 +10,13 @@ import org.opencdmp.model.persist.planstatus.PlanStatusPersist;
|
||||||
import org.opencdmp.model.planstatus.PlanStatus;
|
import org.opencdmp.model.planstatus.PlanStatus;
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
import javax.management.InvalidApplicationException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface PlanStatusService {
|
public interface PlanStatusService {
|
||||||
PlanStatus persist(PlanStatusPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
|
PlanStatus persist(PlanStatusPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException;
|
||||||
|
|
||||||
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
|
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
|
||||||
|
|
||||||
|
List<PlanStatus> getAvailableTransitionStatuses(UUID planId) throws InvalidApplicationException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.opencdmp.service.planstatus;
|
||||||
import gr.cite.commons.web.authz.service.AuthorizationService;
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
||||||
import gr.cite.tools.data.builder.BuilderFactory;
|
import gr.cite.tools.data.builder.BuilderFactory;
|
||||||
import gr.cite.tools.data.deleter.DeleterFactory;
|
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.MyApplicationException;
|
||||||
import gr.cite.tools.exception.MyForbiddenException;
|
import gr.cite.tools.exception.MyForbiddenException;
|
||||||
import gr.cite.tools.exception.MyNotFoundException;
|
import gr.cite.tools.exception.MyNotFoundException;
|
||||||
|
@ -13,24 +14,31 @@ import gr.cite.tools.logging.LoggerService;
|
||||||
import gr.cite.tools.logging.MapLogEntry;
|
import gr.cite.tools.logging.MapLogEntry;
|
||||||
import jakarta.xml.bind.JAXBException;
|
import jakarta.xml.bind.JAXBException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.opencdmp.authorization.AuthorizationFlags;
|
||||||
import org.opencdmp.authorization.Permission;
|
import org.opencdmp.authorization.Permission;
|
||||||
import org.opencdmp.commons.XmlHandlingService;
|
import org.opencdmp.commons.XmlHandlingService;
|
||||||
import org.opencdmp.commons.enums.IsActive;
|
import org.opencdmp.commons.enums.IsActive;
|
||||||
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionAuthorizationEntity;
|
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionAuthorizationEntity;
|
||||||
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionAuthorizationItemEntity;
|
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionAuthorizationItemEntity;
|
||||||
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
|
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
|
||||||
|
import org.opencdmp.commons.types.planworkflow.PlanWorkflowDefinitionEntity;
|
||||||
|
import org.opencdmp.commons.types.planworkflow.PlanWorkflowDefinitionTransitionEntity;
|
||||||
import org.opencdmp.convention.ConventionService;
|
import org.opencdmp.convention.ConventionService;
|
||||||
|
import org.opencdmp.data.PlanEntity;
|
||||||
import org.opencdmp.data.PlanStatusEntity;
|
import org.opencdmp.data.PlanStatusEntity;
|
||||||
import org.opencdmp.data.TenantEntityManager;
|
import org.opencdmp.data.TenantEntityManager;
|
||||||
import org.opencdmp.errorcode.ErrorThesaurusProperties;
|
import org.opencdmp.errorcode.ErrorThesaurusProperties;
|
||||||
import org.opencdmp.event.EventBroker;
|
import org.opencdmp.event.EventBroker;
|
||||||
import org.opencdmp.model.builder.planstatus.PlanStatusBuilder;
|
import org.opencdmp.model.builder.planstatus.PlanStatusBuilder;
|
||||||
import org.opencdmp.model.deleter.PlanStatusDeleter;
|
import org.opencdmp.model.deleter.PlanStatusDeleter;
|
||||||
|
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||||
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionAuthorizationItemPersist;
|
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionAuthorizationItemPersist;
|
||||||
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionAuthorizationPersist;
|
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionAuthorizationPersist;
|
||||||
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionPersist;
|
import org.opencdmp.model.persist.planstatus.PlanStatusDefinitionPersist;
|
||||||
import org.opencdmp.model.persist.planstatus.PlanStatusPersist;
|
import org.opencdmp.model.persist.planstatus.PlanStatusPersist;
|
||||||
import org.opencdmp.model.planstatus.PlanStatus;
|
import org.opencdmp.model.planstatus.PlanStatus;
|
||||||
|
import org.opencdmp.query.PlanStatusQuery;
|
||||||
|
import org.opencdmp.service.planworkflow.PlanWorkflowService;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
@ -38,8 +46,10 @@ import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.management.InvalidApplicationException;
|
import javax.management.InvalidApplicationException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PlanStatusServiceImpl implements PlanStatusService {
|
public class PlanStatusServiceImpl implements PlanStatusService {
|
||||||
|
@ -55,8 +65,10 @@ public class PlanStatusServiceImpl implements PlanStatusService {
|
||||||
private final TenantEntityManager entityManager;
|
private final TenantEntityManager entityManager;
|
||||||
private final MessageSource messageSource;
|
private final MessageSource messageSource;
|
||||||
private final ErrorThesaurusProperties errors;
|
private final ErrorThesaurusProperties errors;
|
||||||
|
private final QueryFactory queryFactory;
|
||||||
|
private final PlanWorkflowService planWorkflowService;
|
||||||
|
|
||||||
public PlanStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authorizationService, ConventionService conventionService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors, EventBroker eventBroker) {
|
public PlanStatusServiceImpl(BuilderFactory builderFactory, DeleterFactory deleterFactory, AuthorizationService authorizationService, ConventionService conventionService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager, MessageSource messageSource, ErrorThesaurusProperties errors, EventBroker eventBroker, QueryFactory queryFactory, PlanWorkflowService planWorkflowService) {
|
||||||
this.builderFactory = builderFactory;
|
this.builderFactory = builderFactory;
|
||||||
this.deleterFactory = deleterFactory;
|
this.deleterFactory = deleterFactory;
|
||||||
|
|
||||||
|
@ -66,6 +78,8 @@ public class PlanStatusServiceImpl implements PlanStatusService {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.messageSource = messageSource;
|
this.messageSource = messageSource;
|
||||||
this.errors = errors;
|
this.errors = errors;
|
||||||
|
this.queryFactory = queryFactory;
|
||||||
|
this.planWorkflowService = planWorkflowService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -149,4 +163,20 @@ public class PlanStatusServiceImpl implements PlanStatusService {
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<PlanStatus> getAvailableTransitionStatuses(UUID planId) throws InvalidApplicationException {
|
||||||
|
PlanWorkflowDefinitionEntity definition = this.planWorkflowService.getWorkFlowDefinition();
|
||||||
|
|
||||||
|
PlanEntity plan = this.entityManager.find(PlanEntity.class, planId);
|
||||||
|
if (plan == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{planId, PlanEntity.class.getSimpleName()}, LocaleContextHolder.getLocale()));
|
||||||
|
|
||||||
|
List<PlanWorkflowDefinitionTransitionEntity> availableTransitions = definition.getStatusTransitions().stream().filter(x -> x.getFromStatusId().equals(plan.getStatusId())).collect(Collectors.toList());
|
||||||
|
if (!this.conventionService.isListNullOrEmpty(availableTransitions)){
|
||||||
|
PlanStatusQuery query = this.queryFactory.query(PlanStatusQuery.class).authorize(AuthorizationFlags.AllExceptPublic).isActives(IsActive.Active).ids(availableTransitions.stream().map(PlanWorkflowDefinitionTransitionEntity::getToStatusId).distinct().toList());
|
||||||
|
FieldSet fieldSet = new BaseFieldSet().ensure(DescriptionStatus._id).ensure(DescriptionStatus._name).ensure(DescriptionStatus._internalStatus);
|
||||||
|
return this.builderFactory.builder(PlanStatusBuilder.class).authorize(AuthorizationFlags.AllExceptPublic).build(fieldSet, query.collectAs(fieldSet));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import jakarta.xml.bind.JAXBException;
|
import jakarta.xml.bind.JAXBException;
|
||||||
import org.opencdmp.audit.AuditableAction;
|
import org.opencdmp.audit.AuditableAction;
|
||||||
import org.opencdmp.authorization.AuthorizationFlags;
|
import org.opencdmp.authorization.AuthorizationFlags;
|
||||||
import org.opencdmp.commons.enums.IsActive;
|
|
||||||
import org.opencdmp.controllers.swagger.SwaggerHelpers;
|
import org.opencdmp.controllers.swagger.SwaggerHelpers;
|
||||||
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
|
import org.opencdmp.controllers.swagger.annotation.OperationWithTenantHeader;
|
||||||
import org.opencdmp.controllers.swagger.annotation.Swagger400;
|
import org.opencdmp.controllers.swagger.annotation.Swagger400;
|
||||||
|
@ -28,15 +27,11 @@ import org.opencdmp.controllers.swagger.annotation.Swagger404;
|
||||||
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
|
import org.opencdmp.controllers.swagger.annotation.SwaggerCommonErrorResponses;
|
||||||
import org.opencdmp.data.DescriptionStatusEntity;
|
import org.opencdmp.data.DescriptionStatusEntity;
|
||||||
import org.opencdmp.model.builder.descriptionstatus.DescriptionStatusBuilder;
|
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.descriptionstatus.DescriptionStatusCensor;
|
||||||
import org.opencdmp.model.censorship.descriptionworkflow.DescriptionWorkflowCensor;
|
|
||||||
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
import org.opencdmp.model.descriptionstatus.DescriptionStatus;
|
||||||
import org.opencdmp.model.descriptionworkflow.DescriptionWorkflow;
|
|
||||||
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
import org.opencdmp.model.persist.descriptionstatus.DescriptionStatusPersist;
|
||||||
import org.opencdmp.model.result.QueryResult;
|
import org.opencdmp.model.result.QueryResult;
|
||||||
import org.opencdmp.query.DescriptionStatusQuery;
|
import org.opencdmp.query.DescriptionStatusQuery;
|
||||||
import org.opencdmp.query.DescriptionWorkflowQuery;
|
|
||||||
import org.opencdmp.query.lookup.DescriptionStatusLookup;
|
import org.opencdmp.query.lookup.DescriptionStatusLookup;
|
||||||
import org.opencdmp.service.descriptionstatus.DescriptionStatusService;
|
import org.opencdmp.service.descriptionstatus.DescriptionStatusService;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -191,11 +186,7 @@ public class DescriptionStatusController {
|
||||||
|
|
||||||
@GetMapping("available-transitions/{descriptionId}")
|
@GetMapping("available-transitions/{descriptionId}")
|
||||||
@OperationWithTenantHeader(summary = "Get available status transitions for description", description = "",
|
@OperationWithTenantHeader(summary = "Get available status transitions for description", description = "",
|
||||||
responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(
|
responses = @ApiResponse(description = "OK", responseCode = "200"))
|
||||||
schema = @Schema(
|
|
||||||
implementation = DescriptionWorkflow.class
|
|
||||||
))
|
|
||||||
))
|
|
||||||
@Swagger404
|
@Swagger404
|
||||||
public List<DescriptionStatus> GetAvailableTransitions(
|
public List<DescriptionStatus> GetAvailableTransitions(
|
||||||
@Parameter(name = "descriptionId", description = "The id of description", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable UUID descriptionId
|
@Parameter(name = "descriptionId", description = "The id of description", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable UUID descriptionId
|
||||||
|
|
|
@ -245,49 +245,29 @@ public class PlanController {
|
||||||
this.auditService.track(AuditableAction.Plan_Delete, "id", id);
|
this.auditService.track(AuditableAction.Plan_Delete, "id", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("finalize/{id}")
|
@PostMapping("set-status/{id}/{newStatusId}")
|
||||||
@OperationWithTenantHeader(summary = "Finalize a plan by id", description = "",
|
@OperationWithTenantHeader(summary = "set status for a plan", description = "",
|
||||||
responses = @ApiResponse(description = "OK", responseCode = "200"))
|
responses = @ApiResponse(description = "OK", responseCode = "200"))
|
||||||
@Swagger404
|
@Swagger404
|
||||||
@Transactional
|
@Transactional
|
||||||
public boolean finalize(
|
public boolean SetStatus(
|
||||||
@Parameter(name = "id", description = "The id of a plan to finalize", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id,
|
@Parameter(name = "id", description = "The id of a plan", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id,
|
||||||
|
@Parameter(name = "newStatusId", description = "The new status of a plan", example = "f1a3da63-0bff-438f-8b46-1a81ca176115", required = true) @PathVariable("newStatusId") UUID newStatusId,
|
||||||
@RequestBody DescriptionsToBeFinalized descriptions
|
@RequestBody DescriptionsToBeFinalized descriptions
|
||||||
) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException {
|
) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException {
|
||||||
logger.debug(new MapLogEntry("finalizing" + Plan.class.getSimpleName()).And("id", id).And("descriptionIds", descriptions.getDescriptionIds()));
|
logger.debug(new MapLogEntry("set status" + Plan.class.getSimpleName()).And("id", id).And("newStatusId", newStatusId).And("descriptionIds", descriptions.getDescriptionIds()));
|
||||||
|
|
||||||
this.planService.finalize(id, descriptions.getDescriptionIds());
|
this.planService.setStatus(id, newStatusId, descriptions.getDescriptionIds());
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Plan_Finalize, Map.ofEntries(
|
this.auditService.track(AuditableAction.Plan_SetStatus, Map.ofEntries(
|
||||||
new AbstractMap.SimpleEntry<String, Object>("id", id),
|
new AbstractMap.SimpleEntry<String, Object>("id", id),
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("newStatusId", newStatusId),
|
||||||
new AbstractMap.SimpleEntry<String, Object>("descriptionIds", descriptions.getDescriptionIds())
|
new AbstractMap.SimpleEntry<String, Object>("descriptionIds", descriptions.getDescriptionIds())
|
||||||
));
|
));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("undo-finalize/{id}")
|
|
||||||
@OperationWithTenantHeader(summary = "Undo the finalization of a plan by id (only possible if it is not already deposited)", description = "",
|
|
||||||
responses = @ApiResponse(description = "OK", responseCode = "200"))
|
|
||||||
@Swagger404
|
|
||||||
@Transactional
|
|
||||||
public boolean undoFinalize(
|
|
||||||
@Parameter(name = "id", description = "The id of a plan to revert the finalization", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id,
|
|
||||||
@Parameter(name = "fieldSet", description = SwaggerHelpers.Commons.fieldset_description, required = true) FieldSet fieldSet
|
|
||||||
) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException, JAXBException {
|
|
||||||
logger.debug(new MapLogEntry("undo-finalizing" + Plan.class.getSimpleName()).And("id", id));
|
|
||||||
|
|
||||||
this.censorFactory.censor(PlanCensor.class).censor(fieldSet, null);
|
|
||||||
|
|
||||||
this.planService.undoFinalize(id, fieldSet);
|
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Plan_Undo_Finalize, Map.ofEntries(
|
|
||||||
new AbstractMap.SimpleEntry<String, Object>("id", id)
|
|
||||||
));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("validate/{id}")
|
@GetMapping("validate/{id}")
|
||||||
@OperationWithTenantHeader(summary = "Validate if a plan is ready for finalization by id")
|
@OperationWithTenantHeader(summary = "Validate if a plan is ready for finalization by id")
|
||||||
@Hidden
|
@Hidden
|
||||||
|
|
|
@ -184,4 +184,19 @@ public class PlanStatusController {
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.PlanStatus_Delete, "id", id);
|
this.auditService.track(AuditableAction.PlanStatus_Delete, "id", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("available-transitions/{planId}")
|
||||||
|
@OperationWithTenantHeader(summary = "Get available status transitions for plan", description = "",
|
||||||
|
responses = @ApiResponse(description = "OK", responseCode = "200"))
|
||||||
|
@Swagger404
|
||||||
|
public List<PlanStatus> GetAvailableTransitions(
|
||||||
|
@Parameter(name = "planId", description = "The id of plan", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable UUID planId
|
||||||
|
) throws InvalidApplicationException {
|
||||||
|
logger.debug(new MapLogEntry("retrieving available statuses" + PlanStatus.class.getSimpleName()));
|
||||||
|
|
||||||
|
List<PlanStatus> availableTransitionStatuses = this.planStatusService.getAvailableTransitionStatuses(planId);
|
||||||
|
|
||||||
|
this.auditService.track(AuditableAction.PlanStatus_Delete, "planId", planId);
|
||||||
|
return availableTransitionStatuses;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { PlanReference } from './plan-reference';
|
||||||
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
||||||
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
import { AppPermission } from '@app/core/common/enum/permission.enum';
|
||||||
import { EntityType } from '@app/core/common/enum/entity-type';
|
import { EntityType } from '@app/core/common/enum/entity-type';
|
||||||
|
import { PlanStatus } from '../plan-status/plan-status';
|
||||||
|
|
||||||
export interface BasePlan extends BaseEntity {
|
export interface BasePlan extends BaseEntity {
|
||||||
label?: string;
|
label?: string;
|
||||||
|
@ -26,7 +27,7 @@ export interface BasePlan extends BaseEntity {
|
||||||
planReferences?: PlanReference[];
|
planReferences?: PlanReference[];
|
||||||
entityDois?: EntityDoi[];
|
entityDois?: EntityDoi[];
|
||||||
tenantId?: Guid;
|
tenantId?: Guid;
|
||||||
status?: PlanStatusEnum;
|
status?: PlanStatus;
|
||||||
descriptions?: BaseDescription[];
|
descriptions?: BaseDescription[];
|
||||||
}
|
}
|
||||||
export interface Plan extends BasePlan {
|
export interface Plan extends BasePlan {
|
||||||
|
@ -96,7 +97,7 @@ export interface PlanDescriptionTemplate extends BaseEntity {
|
||||||
//
|
//
|
||||||
export interface PlanPersist extends BaseEntityPersist {
|
export interface PlanPersist extends BaseEntityPersist {
|
||||||
label: string;
|
label: string;
|
||||||
status: PlanStatusEnum;
|
statusId: Guid;
|
||||||
properties: PlanPropertiesPersist;
|
properties: PlanPropertiesPersist;
|
||||||
description: String;
|
description: String;
|
||||||
language: String;
|
language: String;
|
||||||
|
|
|
@ -57,6 +57,15 @@ export class PlanStatusService {
|
||||||
catchError((error: any) => throwError(() => error)));
|
catchError((error: any) => throwError(() => error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAvailableTransitions(planId: Guid, reqFields: string[] = []): Observable<Array<PlanStatus>> {
|
||||||
|
const url = `${this.apiBase}/available-transitions/${planId}`;
|
||||||
|
const options = { params: { f: reqFields } };
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get<Array<PlanStatus>>(url, options).pipe(
|
||||||
|
catchError((error: any) => throwError(() => error)));
|
||||||
|
}
|
||||||
|
|
||||||
buildLookup(params: {
|
buildLookup(params: {
|
||||||
like?: string,
|
like?: string,
|
||||||
excludedIds?: Guid[],
|
excludedIds?: Guid[],
|
||||||
|
|
|
@ -94,24 +94,14 @@ export class PlanService {
|
||||||
catchError((error: any) => throwError(error)));
|
catchError((error: any) => throwError(error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize(id: Guid, descriptionIds: Guid[] = []): Observable<Boolean> {
|
setStatus(id: Guid, newStatusId: Guid, descriptionIds: Guid[] = []): Observable<Boolean> {
|
||||||
const url = `${this.apiBase}/finalize/${id}`;
|
const url = `${this.apiBase}/set-status/${id}/${newStatusId}`;
|
||||||
|
|
||||||
return this.http
|
return this.http
|
||||||
.post<Boolean>(url, {descriptionIds: descriptionIds}).pipe(
|
.post<Boolean>(url, {descriptionIds: descriptionIds}).pipe(
|
||||||
catchError((error: any) => throwError(error)));
|
catchError((error: any) => throwError(error)));
|
||||||
}
|
}
|
||||||
|
|
||||||
undoFinalize(id: Guid, reqFields: string[] = []): Observable<Boolean> {
|
|
||||||
const url = `${this.apiBase}/undo-finalize/${id}`;
|
|
||||||
|
|
||||||
const options = { params: { f: reqFields } };
|
|
||||||
|
|
||||||
return this.http
|
|
||||||
.get<Boolean>(url, options).pipe(
|
|
||||||
catchError((error: any) => throwError(error)));
|
|
||||||
}
|
|
||||||
|
|
||||||
validate(id: Guid): Observable<PlanValidationResult> {
|
validate(id: Guid): Observable<PlanValidationResult> {
|
||||||
const url = `${this.apiBase}/validate/${id}`;
|
const url = `${this.apiBase}/validate/${id}`;
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { debounceTime, map, takeUntil } from 'rxjs/operators';
|
||||||
import { nameof } from 'ts-simple-nameof';
|
import { nameof } from 'ts-simple-nameof';
|
||||||
import { ActivityListingType } from '../dashboard.component';
|
import { ActivityListingType } from '../dashboard.component';
|
||||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-recent-edited-activity',
|
selector: 'app-recent-edited-activity',
|
||||||
|
@ -232,7 +233,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
|
||||||
response.forEach(item => {
|
response.forEach(item => {
|
||||||
if (item.plan){
|
if (item.plan){
|
||||||
if (item.plan.descriptions) {
|
if (item.plan.descriptions) {
|
||||||
if (item.plan.status == PlanStatusEnum.Finalized) {
|
if (item.plan.status.internalStatus == PlanStatusEnum.Finalized) {
|
||||||
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus === DescriptionStatusEnum.Finalized);
|
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus === DescriptionStatusEnum.Finalized);
|
||||||
} else {
|
} else {
|
||||||
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus != DescriptionStatusEnum.Canceled);
|
item.plan.descriptions = item.plan.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus != DescriptionStatusEnum.Canceled);
|
||||||
|
@ -271,7 +272,9 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.id)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.id)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.label)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.label)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.description)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.description)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.status)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.internalStatus)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.accessType)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.accessType)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.version)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.version)].join('.'),
|
||||||
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.versionStatus)].join('.'),
|
[nameof<RecentActivityItem>(x => x.plan), nameof<Plan>(x => x.versionStatus)].join('.'),
|
||||||
|
|
|
@ -70,9 +70,7 @@
|
||||||
<ng-container *ngIf="availableStatusesTransitions && availableStatusesTransitions.length > 0 && !isLocked && item.id">
|
<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>
|
<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>
|
</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="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> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -572,7 +572,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
|
||||||
|
|
||||||
hasReversableStatus(): boolean {
|
hasReversableStatus(): boolean {
|
||||||
if (this.item?.plan) {
|
if (this.item?.plan) {
|
||||||
return (this.item.plan.status == PlanStatusEnum.Draft && this.isFinalized);
|
return (this.item.plan.status?.internalStatus == PlanStatusEnum.Draft && this.isFinalized);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { DescriptionStatus } from '@app/core/model/description-status/descriptio
|
||||||
import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
|
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 { 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';
|
import { DescriptionTemplatesInSection, PlanBlueprint, PlanBlueprintDefinition, PlanBlueprintDefinitionSection } from '@app/core/model/plan-blueprint/plan-blueprint';
|
||||||
|
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
|
||||||
import { Plan, PlanDescriptionTemplate, PlanUser } from '@app/core/model/plan/plan';
|
import { Plan, PlanDescriptionTemplate, PlanUser } from '@app/core/model/plan/plan';
|
||||||
import { PrefillingSource } from '@app/core/model/prefilling-source/prefilling-source';
|
import { PrefillingSource } from '@app/core/model/prefilling-source/prefilling-source';
|
||||||
import { ReferenceType } from '@app/core/model/reference-type/reference-type';
|
import { ReferenceType } from '@app/core/model/reference-type/reference-type';
|
||||||
|
@ -121,7 +122,11 @@ export class DescriptionEditorEntityResolver extends BaseEditorResolver {
|
||||||
return [
|
return [
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.id)].join('.'),
|
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.id)].join('.'),
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.label)].join('.'),
|
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.label)].join('.'),
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.status)].join('.'),
|
|
||||||
|
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.id)].join('.'),
|
||||||
|
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.name)].join('.'),
|
||||||
|
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.internalStatus)].join('.'),
|
||||||
|
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.isActive)].join('.'),
|
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.isActive)].join('.'),
|
||||||
|
|
||||||
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.authorizationFlags), AppPermission.EditPlan].join('.'),
|
(prefix ? prefix + '.' : '') + [nameof<Plan>(x => x.authorizationFlags), AppPermission.EditPlan].join('.'),
|
||||||
|
|
|
@ -44,6 +44,7 @@ import { PrincipalService } from '@app/core/services/http/principal.service';
|
||||||
import { DescriptionListingFilters } from './filtering/description-filter.component';
|
import { DescriptionListingFilters } from './filtering/description-filter.component';
|
||||||
import { MatSelectChange } from '@angular/material/select';
|
import { MatSelectChange } from '@angular/material/select';
|
||||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-description-listing-component',
|
selector: 'app-description-listing-component',
|
||||||
|
@ -507,7 +508,9 @@ export class DescriptionListingComponent extends BaseListingComponent<BaseDescri
|
||||||
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.id)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.id)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.label)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.label)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.status)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.internalStatus)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.accessType)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.accessType)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.finalizedAt)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.finalizedAt)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
||||||
|
|
|
@ -46,6 +46,7 @@ import { DescriptionCopyDialogComponent } from '../description-copy-dialog/descr
|
||||||
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
||||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
import { DescriptionStatusService } from '@app/core/services/description-status/description-status.service';
|
import { DescriptionStatusService } from '@app/core/services/description-status/description-status.service';
|
||||||
|
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -79,7 +80,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
canAssignPlanUsers(): boolean {
|
canAssignPlanUsers(): boolean {
|
||||||
const authorizationFlags = !this.isPublicView ? (this.description?.plan as Plan)?.authorizationFlags : [];
|
const authorizationFlags = !this.isPublicView ? (this.description?.plan as Plan)?.authorizationFlags : [];
|
||||||
return (authorizationFlags?.some(x => x === AppPermission.AssignPlanUsers) || this.authentication.hasPermission(AppPermission.AssignPlanUsers)) &&
|
return (authorizationFlags?.some(x => x === AppPermission.AssignPlanUsers) || this.authentication.hasPermission(AppPermission.AssignPlanUsers)) &&
|
||||||
!this.isPublicView && this.description?.belongsToCurrentTenant && this.description?.plan?.status === PlanStatusEnum.Draft;
|
!this.isPublicView && this.description?.belongsToCurrentTenant && this.description?.plan?.status?.internalStatus != PlanStatusEnum.Finalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
authorFocus: string;
|
authorFocus: string;
|
||||||
|
@ -513,7 +514,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
}
|
}
|
||||||
|
|
||||||
hasReversableStatus(description: Description): boolean {
|
hasReversableStatus(description: Description): boolean {
|
||||||
return description.plan.status == PlanStatusEnum.Draft && description?.status?.internalStatus == DescriptionStatusEnum.Finalized && this.canFinalize && this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Draft) != null
|
return description.plan.status.internalStatus == PlanStatusEnum.Draft && description?.status?.internalStatus == DescriptionStatusEnum.Finalized && this.canFinalize && this.availableStatusesTransitions?.find(x => x.internalStatus === DescriptionStatusEnum.Draft) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseFinalization(description: Description, statusId: Guid) {
|
reverseFinalization(description: Description, statusId: Guid) {
|
||||||
|
@ -575,7 +576,9 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.id)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.id)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.label)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.label)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.accessType)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.accessType)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.status)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.internalStatus)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.authorizationFlags), AppPermission.InvitePlanUsers].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.authorizationFlags), AppPermission.InvitePlanUsers].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
|
||||||
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.label)].join('.'),
|
[nameof<Description>(x => x.plan), nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.label)].join('.'),
|
||||||
|
|
|
@ -17,13 +17,16 @@
|
||||||
<div class="plan-subtitle">
|
<div class="plan-subtitle">
|
||||||
<span *ngIf="isUserPlanRelated()" class="col-auto">{{ enumUtils.toPlanUserRolesString(planService.getCurrentUserRolesInPlan(plan?.planUsers)) }}</span>
|
<span *ngIf="isUserPlanRelated()" class="col-auto">{{ enumUtils.toPlanUserRolesString(planService.getCurrentUserRolesInPlan(plan?.planUsers)) }}</span>
|
||||||
<span *ngIf="isUserPlanRelated()">.</span>
|
<span *ngIf="isUserPlanRelated()">.</span>
|
||||||
<span class="col-auto" *ngIf="plan.status === planStatusEnum.Finalized && isPublic"><span class="material-icons icon-align">public</span>{{'TYPES.PLAN-VISIBILITY.PUBLIC' | translate}}</span>
|
<span class="col-auto" *ngIf="plan.status.internalStatus === planStatusEnum.Finalized && isPublic"><span class="material-icons icon-align">public</span>{{'TYPES.PLAN-VISIBILITY.PUBLIC' | translate}}</span>
|
||||||
<span *ngIf="plan.status === planStatusEnum.Finalized && !isPublic; else draft" class="col-auto"><span class="material-icons icon-align">done</span>{{ enumUtils.toPlanStatusString(plan.status) }}</span>
|
<span *ngIf="plan.status.internalStatus === planStatusEnum.Finalized && !isPublic; else draft" class="col-auto"><span class="material-icons icon-align">done</span>{{ plan.status.name }}</span>
|
||||||
<ng-template #draft>
|
<ng-template #draft>
|
||||||
<span *ngIf="plan.status === planStatusEnum.Draft && canEditPlan; else preview" class=" col-auto draft"><span class="material-icons icon-align">create</span>{{ enumUtils.toPlanStatusString(plan.status) }}</span>
|
<span *ngIf="plan.status.internalStatus === planStatusEnum.Draft && canEditPlan; else preview" class=" col-auto draft"><span class="material-icons icon-align">create</span>{{ plan.status.name }}</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #preview>
|
<ng-template #preview>
|
||||||
<span *ngIf="plan.status === planStatusEnum.Draft && !canEditPlan" class=" col-auto draft"><span class="material-icons-outlined mr-1 icon-align">visibility</span>{{ enumUtils.toPlanStatusString(plan.status) }}</span>
|
<span *ngIf="plan.status.internalStatus === planStatusEnum.Draft && !canEditPlan; else otherStatus" class=" col-auto draft"><span class="material-icons-outlined mr-1 icon-align">visibility</span>{{ plan.status.name }}</span>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template #otherStatus>
|
||||||
|
<span *ngIf="!isPublic" class=" col-auto draft">{{ plan.status.name }}</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<span>.</span>
|
<span>.</span>
|
||||||
<span class="col-auto">{{'PLAN-LISTING.VERSION' | translate}} {{plan.version}}</span>
|
<span class="col-auto">{{'PLAN-LISTING.VERSION' | translate}} {{plan.version}}</span>
|
||||||
|
|
|
@ -87,7 +87,7 @@ export class PlanListingItemComponent extends BaseComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
get isDraftPlan(): boolean {
|
get isDraftPlan(): boolean {
|
||||||
return this.plan.status == PlanStatusEnum.Draft;
|
return this.plan.status?.internalStatus == PlanStatusEnum.Draft;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -112,16 +112,16 @@ export class PlanListingItemComponent extends BaseComponent implements OnInit {
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.analyticsService.trackPageView(AnalyticsService.PlanListingItem);
|
this.analyticsService.trackPageView(AnalyticsService.PlanListingItem);
|
||||||
if (this.plan.status == PlanStatusEnum.Draft) {
|
if (this.plan.status?.internalStatus == PlanStatusEnum.Draft) {
|
||||||
this.isDraft = true;
|
this.isDraft = true;
|
||||||
this.isFinalized = false;
|
this.isFinalized = false;
|
||||||
this.isPublished = false;
|
this.isPublished = false;
|
||||||
}
|
}
|
||||||
else if (this.plan.status == PlanStatusEnum.Finalized) {
|
else if (this.plan.status?.internalStatus == PlanStatusEnum.Finalized) {
|
||||||
this.isDraft = false;
|
this.isDraft = false;
|
||||||
this.isFinalized = true;
|
this.isFinalized = true;
|
||||||
this.isPublished = false;
|
this.isPublished = false;
|
||||||
if (this.plan.status === PlanStatusEnum.Finalized && this.plan.accessType === PlanAccessType.Public) { this.isPublished = true }
|
if (this.plan.status.internalStatus === PlanStatusEnum.Finalized && this.plan.accessType === PlanAccessType.Public) { this.isPublished = true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ export class PlanListingItemComponent extends BaseComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
viewVersions(plan: Plan) {
|
viewVersions(plan: Plan) {
|
||||||
if (plan.accessType == PlanAccessType.Public && plan.status == PlanStatusEnum.Finalized && !this.plan.authorizationFlags?.some(x => x === AppPermission.EditPlan)) {
|
if (plan.accessType == PlanAccessType.Public && plan.status?.internalStatus == PlanStatusEnum.Finalized && !this.plan.authorizationFlags?.some(x => x === AppPermission.EditPlan)) {
|
||||||
let url = this.router.createUrlTree(['/explore-plans/versions/', plan.groupId]);
|
let url = this.router.createUrlTree(['/explore-plans/versions/', plan.groupId]);
|
||||||
window.open(url.toString(), '_blank');
|
window.open(url.toString(), '_blank');
|
||||||
} else {
|
} else {
|
||||||
|
@ -157,7 +157,7 @@ export class PlanListingItemComponent extends BaseComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
viewVersionsUrl(plan: Plan): string {
|
viewVersionsUrl(plan: Plan): string {
|
||||||
if (plan.accessType == PlanAccessType.Public && plan.status == PlanStatusEnum.Finalized && !this.plan.authorizationFlags?.some(x => x === AppPermission.EditPlan)) {
|
if (plan.accessType == PlanAccessType.Public && plan.status?.internalStatus == PlanStatusEnum.Finalized && !this.plan.authorizationFlags?.some(x => x === AppPermission.EditPlan)) {
|
||||||
let url = this.router.createUrlTree(['/explore-plans/versions/', plan.groupId]);
|
let url = this.router.createUrlTree(['/explore-plans/versions/', plan.groupId]);
|
||||||
return url.toString();
|
return url.toString();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -45,6 +45,7 @@ import { PlanListingFilters } from './filtering/plan-filter.component';
|
||||||
import { Lookup } from '@common/model/lookup';
|
import { Lookup } from '@common/model/lookup';
|
||||||
import { MatSelectChange } from '@angular/material/select';
|
import { MatSelectChange } from '@angular/material/select';
|
||||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-plan-listing-component',
|
selector: 'app-plan-listing-component',
|
||||||
|
@ -493,7 +494,11 @@ export class PlanListingComponent extends BaseListingComponent<BasePlan, PlanLoo
|
||||||
nameof<Plan>(x => x.id),
|
nameof<Plan>(x => x.id),
|
||||||
nameof<Plan>(x => x.label),
|
nameof<Plan>(x => x.label),
|
||||||
nameof<Plan>(x => x.description),
|
nameof<Plan>(x => x.description),
|
||||||
nameof<Plan>(x => x.status),
|
|
||||||
|
[nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.internalStatus)].join('.'),
|
||||||
|
|
||||||
nameof<Plan>(x => x.accessType),
|
nameof<Plan>(x => x.accessType),
|
||||||
nameof<Plan>(x => x.version),
|
nameof<Plan>(x => x.version),
|
||||||
nameof<Plan>(x => x.versionStatus),
|
nameof<Plan>(x => x.versionStatus),
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
{{plan.updatedAt | dateTimeFormatter: "d MMMM y"}}
|
{{plan.updatedAt | dateTimeFormatter: "d MMMM y"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto d-flex">
|
<div class="col-auto d-flex">
|
||||||
<div *ngIf="plan.status== planStatusEnum.Finalized" class="d-flex flex-row uppercase">
|
<div *ngIf="plan.status.internalStatus== planStatusEnum.Finalized" class="d-flex flex-row uppercase">
|
||||||
<mat-icon class="status-icon">check</mat-icon>
|
<mat-icon class="status-icon">check</mat-icon>
|
||||||
{{'PLAN-OVERVIEW.FINALISED' | translate}}
|
{{'PLAN-OVERVIEW.FINALISED' | translate}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
<ng-container *ngFor="let description of plan.descriptions">
|
<ng-container *ngFor="let description of plan.descriptions">
|
||||||
<div class="col-12 col-lg-7 mt-1">
|
<div class="col-12 col-lg-7 mt-1">
|
||||||
<a class="w-100 description" [routerLink]="isPublicView ? this.routerUtils.generateUrl(['/explore-descriptions/overview/public/', description.id]) : this.routerUtils.generateUrl(['/descriptions/overview/' + description.id])" target="_blank">
|
<a class="w-100 description" [routerLink]="isPublicView ? this.routerUtils.generateUrl(['/explore-descriptions/overview/public/', description.id]) : this.routerUtils.generateUrl(['/descriptions/overview/' + description.id])" target="_blank">
|
||||||
<button class="w-100" [ngClass]="{'plan-btn': description.status === descriptionStatusEnum.Draft, 'plan-finalized-btn': description.status === descriptionStatusEnum.Finalized}">
|
<button class="w-100" [ngClass]="{'plan-btn': description.status.internalStatus === descriptionStatusEnum.Draft, 'plan-finalized-btn': description.status.internalStatus === descriptionStatusEnum.Finalized}">
|
||||||
<div matTooltip="{{ description.label }}" class="d-flex align-items-center justify-content-between">
|
<div matTooltip="{{ description.label }}" class="d-flex align-items-center justify-content-between">
|
||||||
<div class="description-btn-label">{{ description.label }}</div>
|
<div class="description-btn-label">{{ description.label }}</div>
|
||||||
<mat-icon>launch</mat-icon>
|
<mat-icon>launch</mat-icon>
|
||||||
|
@ -181,7 +181,29 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="frame mb-3 pt-4 pl-4 pr-5 pb-3">
|
<div class="frame mb-3 pt-4 pl-4 pr-5 pb-3">
|
||||||
<ng-container *ngIf="isDraftPlan() && canFinalizePlan() && !isLocked">
|
<ng-container *ngIf="availableStatusesTransitions && availableStatusesTransitions.length > 0 && !isLocked && hasDoi(plan) && plan.belongsToCurrentTenant != false">
|
||||||
|
<div *ngFor='let status of availableStatusesTransitions'>
|
||||||
|
<div class="row align-items-center" (click)="persistStatus(status)">
|
||||||
|
<div class="col-auto pr-0">
|
||||||
|
<button *ngIf="status.internalStatus === descriptionStatusEnum.Finalized && plan.status?.internalStatus != planStatusEnum.Finalized" mat-mini-fab class="finalize-btn">
|
||||||
|
<mat-icon class="mat-mini-fab-icon check-icon">check</mat-icon>
|
||||||
|
</button>
|
||||||
|
<button *ngIf="plan.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="row align-items-center">
|
||||||
|
<div class="col-12">
|
||||||
|
<hr class="hr-line">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
<!-- <ng-container *ngIf="isDraftPlan() && canFinalizePlan() && !isLocked">
|
||||||
<div class="row align-items-center" (click)="finalize(plan)">
|
<div class="row align-items-center" (click)="finalize(plan)">
|
||||||
<div class="col-auto pr-0">
|
<div class="col-auto pr-0">
|
||||||
<button mat-mini-fab class="finalize-btn">
|
<button mat-mini-fab class="finalize-btn">
|
||||||
|
@ -192,14 +214,14 @@
|
||||||
<p class="mb-0 pl-2 finalize-txt">{{ 'PLAN-OVERVIEW.ACTIONS.FINALIZE' | translate }}</p>
|
<p class="mb-0 pl-2 finalize-txt">{{ 'PLAN-OVERVIEW.ACTIONS.FINALIZE' | translate }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">0
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<hr class="hr-line">
|
<hr class="hr-line">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container> -->
|
||||||
<app-plan-deposit-dropdown *ngIf="(hasDoi(plan) || moreDeposit()) && isFinalizedPlan(plan) && !this.isPublicView && canDepositPlan(plan) && inputRepos.length > 0" [inputRepos]="inputRepos" [plan]="plan" (outputReposEmitter)="afterDeposit($event)"></app-plan-deposit-dropdown>
|
<app-plan-deposit-dropdown *ngIf="(hasDoi(plan) || moreDeposit()) && isFinalizedPlan(plan) && !this.isPublicView && canDepositPlan(plan) && inputRepos.length > 0" [inputRepos]="inputRepos" [plan]="plan" (outputReposEmitter)="afterDeposit($event)"></app-plan-deposit-dropdown>
|
||||||
<ng-container *ngIf="isFinalizedPlan(plan) && hasDoi(plan) && !isPublishedPlan(plan) && canFinalizePlan(plan)">
|
<!-- <ng-container *ngIf="isFinalizedPlan(plan) && hasDoi(plan) && !isPublishedPlan(plan) && canFinalizePlan(plan)">
|
||||||
<div (click)="reverseFinalization()" class="row mb-3 align-items-center">
|
<div (click)="reverseFinalization()" class="row mb-3 align-items-center">
|
||||||
<div class="col-auto pr-0">
|
<div class="col-auto pr-0">
|
||||||
<button mat-mini-fab class="frame-btn">
|
<button mat-mini-fab class="frame-btn">
|
||||||
|
@ -210,7 +232,7 @@
|
||||||
<p class="mb-0 pl-2 frame-txt">{{ 'PLAN-OVERVIEW.ACTIONS.REVERSE' | translate }}</p>
|
<p class="mb-0 pl-2 frame-txt">{{ 'PLAN-OVERVIEW.ACTIONS.REVERSE' | translate }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container> -->
|
||||||
<ng-container *ngIf="canExportPlan() && fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Plan).length > 0">
|
<ng-container *ngIf="canExportPlan() && fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Plan).length > 0">
|
||||||
<div class="row mb-3 align-items-center">
|
<div class="row mb-3 align-items-center">
|
||||||
<div class="col-auto pr-0">
|
<div class="col-auto pr-0">
|
||||||
|
@ -254,7 +276,7 @@
|
||||||
<app-plan-authors
|
<app-plan-authors
|
||||||
[planUsers]="plan.planUsers"
|
[planUsers]="plan.planUsers"
|
||||||
[username]="userName"
|
[username]="userName"
|
||||||
[removeUser]="canAssignPlanUsers(plan) && plan.status === planStatusEnum.Draft"
|
[removeUser]="canAssignPlanUsers(plan) && (plan.status.internalStatus == null || plan.status.internalStatus === planStatusEnum.Finalized)"
|
||||||
(deleteAuthor)="removeUserFromPlan($event)"
|
(deleteAuthor)="removeUserFromPlan($event)"
|
||||||
/>
|
/>
|
||||||
<div *ngIf="canInvitePlanUsers()" class="col-12 d-flex align-items-center justify-content-center mt-2">
|
<div *ngIf="canInvitePlanUsers()" class="col-12 d-flex align-items-center justify-content-center mt-2">
|
||||||
|
|
|
@ -51,6 +51,8 @@ import { PlanInvitationDialogComponent } from '../invitation/dialog/plan-invitat
|
||||||
import { NewVersionPlanDialogComponent } from '../new-version-dialog/plan-new-version-dialog.component';
|
import { NewVersionPlanDialogComponent } from '../new-version-dialog/plan-new-version-dialog.component';
|
||||||
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
|
||||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
|
||||||
|
import { PlanStatusService } from '@app/core/services/plan/plan-status.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-plan-overview',
|
selector: 'app-plan-overview',
|
||||||
|
@ -83,6 +85,7 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
|
|
||||||
authorFocus: string;
|
authorFocus: string;
|
||||||
userName: string;
|
userName: string;
|
||||||
|
availableStatusesTransitions: PlanStatus[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public routerUtils: RouterUtilsService,
|
public routerUtils: RouterUtilsService,
|
||||||
|
@ -108,6 +111,7 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
private breadcrumbService: BreadcrumbService,
|
private breadcrumbService: BreadcrumbService,
|
||||||
private httpErrorHandlingService: HttpErrorHandlingService,
|
private httpErrorHandlingService: HttpErrorHandlingService,
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
|
private pLanStatusService: PlanStatusService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
@ -130,10 +134,11 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
this.breadcrumbService.addIdResolvedValue(data.id?.toString(), data.label);
|
this.breadcrumbService.addIdResolvedValue(data.id?.toString(), data.label);
|
||||||
|
|
||||||
this.plan = data;
|
this.plan = data;
|
||||||
|
this.getAvailableStatuses(this.plan.id);
|
||||||
this.plan.planUsers = this.isActive ? data?.planUsers?.filter((x) => x.isActive === IsActive.Active) : data?.planUsers;
|
this.plan.planUsers = this.isActive ? data?.planUsers?.filter((x) => x.isActive === IsActive.Active) : data?.planUsers;
|
||||||
this.plan.otherPlanVersions = data.otherPlanVersions?.filter(x => x.isActive === IsActive.Active) || null;
|
this.plan.otherPlanVersions = data.otherPlanVersions?.filter(x => x.isActive === IsActive.Active) || null;
|
||||||
if (this.plan.descriptions) {
|
if (this.plan.descriptions) {
|
||||||
if (this.plan.status == PlanStatusEnum.Finalized) {
|
if (this.plan.status?.internalStatus == PlanStatusEnum.Finalized) {
|
||||||
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus === DescriptionStatusEnum.Finalized);
|
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus === DescriptionStatusEnum.Finalized);
|
||||||
} else {
|
} else {
|
||||||
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus !== DescriptionStatusEnum.Canceled);
|
this.plan.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status?.internalStatus !== DescriptionStatusEnum.Canceled);
|
||||||
|
@ -230,6 +235,15 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
return this.language.instant('PLAN-OVERVIEW.INFOS.UNAUTHORIZED-ORCID');
|
return this.language.instant('PLAN-OVERVIEW.INFOS.UNAUTHORIZED-ORCID');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAvailableStatuses(id: Guid){
|
||||||
|
this.pLanStatusService.getAvailableTransitions(id).pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(
|
||||||
|
(statuses) => {
|
||||||
|
this.availableStatusesTransitions = statuses;
|
||||||
|
},
|
||||||
|
(error) => this.httpErrorHandlingService.handleBackedRequestError(error)
|
||||||
|
); }
|
||||||
|
|
||||||
onFetchingDeletedCallbackError(redirectRoot: string) {
|
onFetchingDeletedCallbackError(redirectRoot: string) {
|
||||||
this.router.navigate([this.routerUtils.generateUrl(redirectRoot)]);
|
this.router.navigate([this.routerUtils.generateUrl(redirectRoot)]);
|
||||||
}
|
}
|
||||||
|
@ -412,15 +426,15 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
isDraftPlan() {
|
isDraftPlan() {
|
||||||
return this.plan.status == PlanStatusEnum.Draft;
|
return this.plan.status?.internalStatus == PlanStatusEnum.Draft;
|
||||||
}
|
}
|
||||||
|
|
||||||
isFinalizedPlan(plan: Plan) {
|
isFinalizedPlan(plan: Plan) {
|
||||||
return plan.status == PlanStatusEnum.Finalized;
|
return plan.status?.internalStatus == PlanStatusEnum.Finalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
isPublishedPlan() {
|
isPublishedPlan() {
|
||||||
return (this.plan.status == PlanStatusEnum.Finalized && this.plan.accessType === PlanAccessType.Public);
|
return (this.plan.status?.internalStatus == PlanStatusEnum.Finalized && this.plan.accessType === PlanAccessType.Public);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasDoi() {
|
hasDoi() {
|
||||||
|
@ -442,7 +456,24 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
return (this.plan.entityDois.length < this.depositRepos.length);
|
return (this.plan.entityDois.length < this.depositRepos.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize() {
|
persistStatus(status: PlanStatus) {
|
||||||
|
if (status.internalStatus != null && status.internalStatus === PlanStatusEnum.Finalized) {
|
||||||
|
this.finalize(status.id);
|
||||||
|
} else if (this.plan.status.internalStatus === PlanStatusEnum.Finalized){
|
||||||
|
this.reverseFinalization(status.id);
|
||||||
|
} else {
|
||||||
|
// other statuses
|
||||||
|
this.planService.setStatus(this.plan.id, status.id).pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe({
|
||||||
|
complete: () => {this.reloadPage(); this.onUpdateCallbackSuccess()},
|
||||||
|
error:(error: any) => {
|
||||||
|
this.onUpdateCallbackError(error)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalize(newStatusId) {
|
||||||
const dialogRef = this.dialog.open(PlanFinalizeDialogComponent, {
|
const dialogRef = this.dialog.open(PlanFinalizeDialogComponent, {
|
||||||
maxWidth: '500px',
|
maxWidth: '500px',
|
||||||
restoreFocus: false,
|
restoreFocus: false,
|
||||||
|
@ -454,7 +485,7 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: PlanFinalizeDialogOutput) => {
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: PlanFinalizeDialogOutput) => {
|
||||||
if (result && !result.cancelled) {
|
if (result && !result.cancelled) {
|
||||||
|
|
||||||
this.planService.finalize(this.plan.id, result.descriptionsToBeFinalized)
|
this.planService.setStatus(this.plan.id, newStatusId, result.descriptionsToBeFinalized)
|
||||||
.pipe(takeUntil(this._destroyed))
|
.pipe(takeUntil(this._destroyed))
|
||||||
.subscribe({
|
.subscribe({
|
||||||
complete: () => {
|
complete: () => {
|
||||||
|
@ -512,7 +543,7 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseFinalization() {
|
reverseFinalization(newStatusId: Guid) {
|
||||||
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||||
restoreFocus: false,
|
restoreFocus: false,
|
||||||
data: {
|
data: {
|
||||||
|
@ -524,7 +555,7 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
});
|
});
|
||||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
this.planService.undoFinalize(this.plan.id, PlanEditorEntityResolver.lookupFields()).pipe(takeUntil(this._destroyed))
|
this.planService.setStatus(this.plan.id, newStatusId).pipe(takeUntil(this._destroyed))
|
||||||
.subscribe({
|
.subscribe({
|
||||||
complete: () => {this.reloadPage(); this.onUpdateCallbackSuccess()},
|
complete: () => {this.reloadPage(); this.onUpdateCallbackSuccess()},
|
||||||
error:(error: any) => {
|
error:(error: any) => {
|
||||||
|
@ -637,7 +668,9 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
|
||||||
nameof<Plan>(x => x.id),
|
nameof<Plan>(x => x.id),
|
||||||
nameof<Plan>(x => x.label),
|
nameof<Plan>(x => x.label),
|
||||||
nameof<Plan>(x => x.description),
|
nameof<Plan>(x => x.description),
|
||||||
nameof<Plan>(x => x.status),
|
[nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.internalStatus)].join('.'),
|
||||||
nameof<Plan>(x => x.accessType),
|
nameof<Plan>(x => x.accessType),
|
||||||
nameof<Plan>(x => x.version),
|
nameof<Plan>(x => x.version),
|
||||||
nameof<Plan>(x => x.versionStatus),
|
nameof<Plan>(x => x.versionStatus),
|
||||||
|
|
|
@ -52,12 +52,11 @@
|
||||||
<button [disabled]="saving" mat-menu-item (click)="formSubmit()" type="button">{{ 'PLAN-EDITOR.ACTIONS.SAVE-AND-CONTINUE' | translate }}</button>
|
<button [disabled]="saving" mat-menu-item (click)="formSubmit()" type="button">{{ 'PLAN-EDITOR.ACTIONS.SAVE-AND-CONTINUE' | translate }}</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto d-flex align-items-center" *ngIf="canFinalize && this.hasNotDoi() && formGroup.enabled" [matTooltipDisabled]="canFinalize && formGroup.pristine" matTooltip="{{'PLAN-EDITOR.ACTIONS.FINALIZE.CAN-NOT-FINALIZE' | translate}}">
|
<div *ngIf="availableStatusesTransitions && availableStatusesTransitions.length > 0 && !isLocked && !isNew && hasNotDoi()" class="col-auto d-flex align-items-center" [matTooltipDisabled]="formGroup.pristine" matTooltip="{{'PLAN-EDITOR.ACTIONS.FINALIZE.CAN-NOT-FINALIZE' | translate}}">
|
||||||
<button [disabled]="!formGroup.pristine" mat-button class="rounded-btn primary-inverted mr-2" type="button" (click)="finalize()">{{ 'PLAN-EDITOR.ACTIONS.FINALIZE.FINALIZE' | translate }}</button>
|
<button *ngFor='let status of availableStatusesTransitions' [disabled]="saving || !formGroup.pristine" mat-button class="rounded-btn primary-inverted mr-2" type="button" (click)="persistStatus(status)">{{ status.name}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="formGroup.pristine" class="col-auto d-flex align-items-center">
|
<div *ngIf="isLocked" class="col-auto d-flex align-items-center">
|
||||||
<button [disabled]="saving" *ngIf="isLocked" mat-button class="rounded-btn primary-inverted mr-2" type="button">{{ 'PLAN-EDITOR.ACTIONS.LOCKED' | translate}}</button>
|
<button class="col-auto d-flex align-items-center" [disabled]="saving" mat-button class="rounded-btn primary-inverted mr-2" type="button">{{ 'PLAN-EDITOR.ACTIONS.LOCKED' | translate}}</button>
|
||||||
<button [disabled]="saving" *ngIf="canReverseFinalize && this.hasNotDoi()" mat-button class="rounded-btn primary-inverted mr-2" type="button" (click)="reverseFinalization()">{{ 'PLAN-EDITOR.ACTIONS.REVERSE' | translate }}</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -60,6 +60,8 @@ import { PlanEditorService } from './plan-editor.service';
|
||||||
import { PlanEditorEntityResolver } from './resolvers/plan-editor-enitity.resolver';
|
import { PlanEditorEntityResolver } from './resolvers/plan-editor-enitity.resolver';
|
||||||
import { FormAnnotationService } from '@app/ui/annotations/annotation-dialog-component/form-annotation.service';
|
import { FormAnnotationService } from '@app/ui/annotations/annotation-dialog-component/form-annotation.service';
|
||||||
import { PlanAssociatedUser } from '@app/core/model/user/user';
|
import { PlanAssociatedUser } from '@app/core/model/user/user';
|
||||||
|
import { PlanStatusService } from '@app/core/services/plan/plan-status.service';
|
||||||
|
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-plan-editor',
|
selector: 'app-plan-editor',
|
||||||
|
@ -97,6 +99,8 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
|
|
||||||
hoveredContact: number = -1;
|
hoveredContact: number = -1;
|
||||||
|
|
||||||
|
availableStatusesTransitions: PlanStatus[];
|
||||||
|
|
||||||
singleAutocompleteBlueprintConfiguration: SingleAutoCompleteConfiguration = {
|
singleAutocompleteBlueprintConfiguration: SingleAutoCompleteConfiguration = {
|
||||||
initialItems: (data?: any) => this.planBlueprintService.query(this.planBlueprintService.buildAutocompleteLookup(null, null, null, [PlanBlueprintStatus.Finalized])).pipe(map(x => x.items)),
|
initialItems: (data?: any) => this.planBlueprintService.query(this.planBlueprintService.buildAutocompleteLookup(null, null, null, [PlanBlueprintStatus.Finalized])).pipe(map(x => x.items)),
|
||||||
filterFn: (searchQuery: string, data?: any) => this.planBlueprintService.query(this.planBlueprintService.buildAutocompleteLookup(searchQuery, null, null, [PlanBlueprintStatus.Finalized])).pipe(map(x => x.items)),
|
filterFn: (searchQuery: string, data?: any) => this.planBlueprintService.query(this.planBlueprintService.buildAutocompleteLookup(searchQuery, null, null, [PlanBlueprintStatus.Finalized])).pipe(map(x => x.items)),
|
||||||
|
@ -136,7 +140,7 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get canReverseFinalize(): boolean {
|
protected get canReverseFinalize(): boolean {
|
||||||
return !this.isDeleted && !this.isNew && this.canEdit && this.isLockedByUser && this.item.status == PlanStatusEnum.Finalized && (this.hasPermission(this.authService.permissionEnum.EditPlan) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditPlan));
|
return !this.isDeleted && !this.isNew && this.canEdit && this.isLockedByUser && this.item.status?.internalStatus == PlanStatusEnum.Finalized && (this.hasPermission(this.authService.permissionEnum.EditPlan) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditPlan));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected canEditSection(id: Guid): boolean {
|
protected canEditSection(id: Guid): boolean {
|
||||||
|
@ -193,6 +197,7 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
private breadcrumbService: BreadcrumbService,
|
private breadcrumbService: BreadcrumbService,
|
||||||
public fileTransformerService: FileTransformerService,
|
public fileTransformerService: FileTransformerService,
|
||||||
private formAnnotationService: FormAnnotationService,
|
private formAnnotationService: FormAnnotationService,
|
||||||
|
private pLanStatusService: PlanStatusService
|
||||||
) {
|
) {
|
||||||
const descriptionLabel: string = route.snapshot.data['entity']?.label;
|
const descriptionLabel: string = route.snapshot.data['entity']?.label;
|
||||||
if (descriptionLabel) {
|
if (descriptionLabel) {
|
||||||
|
@ -261,8 +266,9 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
}
|
}
|
||||||
this.editorModel = data ? new PlanEditorModel().fromModel(data) : new PlanEditorModel();
|
this.editorModel = data ? new PlanEditorModel().fromModel(data) : new PlanEditorModel();
|
||||||
if (data) {
|
if (data) {
|
||||||
|
if (data.id) this.getAvailableStatuses(data.id);
|
||||||
if (data.descriptions) {
|
if (data.descriptions) {
|
||||||
if (data.status == PlanStatusEnum.Finalized) {
|
if (data.status?.internalStatus == PlanStatusEnum.Finalized) {
|
||||||
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status.internalStatus === DescriptionStatusEnum.Finalized);
|
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status.internalStatus === DescriptionStatusEnum.Finalized);
|
||||||
} else {
|
} else {
|
||||||
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status.internalStatus !== DescriptionStatusEnum.Canceled);
|
data.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status.internalStatus !== DescriptionStatusEnum.Canceled);
|
||||||
|
@ -278,7 +284,6 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
|
|
||||||
this.selectedBlueprint = data?.blueprint;
|
this.selectedBlueprint = data?.blueprint;
|
||||||
this.isDeleted = data ? data.isActive === IsActive.Inactive : false;
|
this.isDeleted = data ? data.isActive === IsActive.Inactive : false;
|
||||||
this.isFinalized = data ? data.status === PlanStatusEnum.Finalized : false;
|
|
||||||
|
|
||||||
if (data && data.id) {
|
if (data && data.id) {
|
||||||
const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = {
|
const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = {
|
||||||
|
@ -291,6 +296,14 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
this.buildForm();
|
this.buildForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data && data.status?.internalStatus == PlanStatusEnum.Finalized || this.isDeleted) {
|
||||||
|
this.viewOnly = true;
|
||||||
|
this.isFinalized = true;
|
||||||
|
this.formGroup.disable();
|
||||||
|
} else {
|
||||||
|
this.viewOnly = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.item && this.item.id != null) {
|
if (this.item && this.item.id != null) {
|
||||||
this.checkLock(this.item.id, LockTargetType.Plan, 'PLAN-EDITOR.LOCKED-DIALOG.TITLE', 'PLAN-EDITOR.LOCKED-DIALOG.MESSAGE');
|
this.checkLock(this.item.id, LockTargetType.Plan, 'PLAN-EDITOR.LOCKED-DIALOG.TITLE', 'PLAN-EDITOR.LOCKED-DIALOG.MESSAGE');
|
||||||
}
|
}
|
||||||
|
@ -304,16 +317,17 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.canEdit);
|
this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.canEdit);
|
||||||
|
|
||||||
this.sectionToFieldsMap = this.prepareErrorIndication();
|
this.sectionToFieldsMap = this.prepareErrorIndication();
|
||||||
|
|
||||||
if (this.editorModel.status == PlanStatusEnum.Finalized || this.isDeleted) {
|
|
||||||
this.viewOnly = true;
|
|
||||||
this.isFinalized = this.editorModel.status == PlanStatusEnum.Finalized;
|
|
||||||
this.formGroup.disable();
|
|
||||||
} else {
|
|
||||||
this.viewOnly = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAvailableStatuses(id: Guid){
|
||||||
|
this.pLanStatusService.getAvailableTransitions(id).pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(
|
||||||
|
(statuses) => {
|
||||||
|
this.availableStatusesTransitions = statuses;
|
||||||
|
},
|
||||||
|
(error) => this.httpErrorHandlingService.handleBackedRequestError(error)
|
||||||
|
); }
|
||||||
|
|
||||||
prepareErrorIndication(): Map<string, PlanFieldIndicator> {
|
prepareErrorIndication(): Map<string, PlanFieldIndicator> {
|
||||||
if (this.selectedBlueprint?.definition == null) return;
|
if (this.selectedBlueprint?.definition == null) return;
|
||||||
|
|
||||||
|
@ -449,7 +463,23 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
return (this.item.entityDois == null || this.item.entityDois.length == 0);
|
return (this.item.entityDois == null || this.item.entityDois.length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize() {
|
persistStatus(status: PlanStatus) {
|
||||||
|
if (status.internalStatus != null && status.internalStatus === PlanStatusEnum.Finalized) {
|
||||||
|
this.finalize(status.id);
|
||||||
|
} else if (this.item.status.internalStatus === PlanStatusEnum.Finalized){
|
||||||
|
this.reverseFinalization(status.id);
|
||||||
|
} else {
|
||||||
|
// other statuses
|
||||||
|
this.planService.setStatus(this.item.id, status.id).pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(data => {
|
||||||
|
this.onCallbackSuccess()
|
||||||
|
}, (error: any) => {
|
||||||
|
this.onCallbackError(error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalize(newStatusId) {
|
||||||
const dialogRef = this.dialog.open(PlanFinalizeDialogComponent, {
|
const dialogRef = this.dialog.open(PlanFinalizeDialogComponent, {
|
||||||
maxWidth: '500px',
|
maxWidth: '500px',
|
||||||
restoreFocus: false,
|
restoreFocus: false,
|
||||||
|
@ -461,7 +491,7 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: PlanFinalizeDialogOutput) => {
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: PlanFinalizeDialogOutput) => {
|
||||||
if (result && !result.cancelled) {
|
if (result && !result.cancelled) {
|
||||||
|
|
||||||
this.planService.finalize(this.item.id, result.descriptionsToBeFinalized)
|
this.planService.setStatus(this.item.id, newStatusId, result.descriptionsToBeFinalized)
|
||||||
.pipe(takeUntil(this._destroyed))
|
.pipe(takeUntil(this._destroyed))
|
||||||
.subscribe(data => {
|
.subscribe(data => {
|
||||||
this.onCallbackSuccess()
|
this.onCallbackSuccess()
|
||||||
|
@ -474,7 +504,7 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseFinalization() {
|
reverseFinalization(newStatusId: Guid) {
|
||||||
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||||
restoreFocus: false,
|
restoreFocus: false,
|
||||||
data: {
|
data: {
|
||||||
|
@ -486,7 +516,7 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
});
|
});
|
||||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
this.planService.undoFinalize(this.item.id, PlanEditorEntityResolver.lookupFields()).pipe(takeUntil(this._destroyed))
|
this.planService.setStatus(this.item.id, newStatusId).pipe(takeUntil(this._destroyed))
|
||||||
.subscribe(data => {
|
.subscribe(data => {
|
||||||
this.onCallbackSuccess()
|
this.onCallbackSuccess()
|
||||||
}, (error: any) => {
|
}, (error: any) => {
|
||||||
|
@ -594,7 +624,6 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
|
||||||
label: this.formGroup.get('label').value,
|
label: this.formGroup.get('label').value,
|
||||||
description: this.formGroup.get('description').value,
|
description: this.formGroup.get('description').value,
|
||||||
blueprint: this.selectedBlueprint,
|
blueprint: this.selectedBlueprint,
|
||||||
status: PlanStatusEnum.Draft
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.prepareForm(plan);
|
this.prepareForm(plan);
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { Guid } from "@common/types/guid";
|
||||||
|
|
||||||
export class PlanEditorModel extends BaseEditorModel implements PlanPersist {
|
export class PlanEditorModel extends BaseEditorModel implements PlanPersist {
|
||||||
label: string;
|
label: string;
|
||||||
status: PlanStatusEnum;
|
statusId: Guid;
|
||||||
properties: PlanPropertiesEditorModel = new PlanPropertiesEditorModel(this.validationErrorModel);
|
properties: PlanPropertiesEditorModel = new PlanPropertiesEditorModel(this.validationErrorModel);
|
||||||
description: String;
|
description: String;
|
||||||
language: String;
|
language: String;
|
||||||
|
@ -37,7 +37,7 @@ export class PlanEditorModel extends BaseEditorModel implements PlanPersist {
|
||||||
if (item) {
|
if (item) {
|
||||||
super.fromModel(item);
|
super.fromModel(item);
|
||||||
this.label = item.label;
|
this.label = item.label;
|
||||||
this.status = item.status;
|
this.statusId = item.status?.id;
|
||||||
this.properties = new PlanPropertiesEditorModel(this.validationErrorModel).fromModel(item.properties, item.planReferences?.filter(x => x.isActive === IsActive.Active), item.blueprint);
|
this.properties = new PlanPropertiesEditorModel(this.validationErrorModel).fromModel(item.properties, item.planReferences?.filter(x => x.isActive === IsActive.Active), item.blueprint);
|
||||||
this.description = item.description;
|
this.description = item.description;
|
||||||
this.language = item.language;
|
this.language = item.language;
|
||||||
|
@ -85,7 +85,7 @@ export class PlanEditorModel extends BaseEditorModel implements PlanPersist {
|
||||||
const formGroup = this.formBuilder.group({
|
const formGroup = this.formBuilder.group({
|
||||||
id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators],
|
id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators],
|
||||||
label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators],
|
label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators],
|
||||||
status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators],
|
statusId: [{ value: this.statusId, disabled: disabled }, context.getValidation('statusId').validators],
|
||||||
properties: this.properties.buildForm({
|
properties: this.properties.buildForm({
|
||||||
rootPath: `properties.`,
|
rootPath: `properties.`,
|
||||||
disabled: disabled
|
disabled: disabled
|
||||||
|
@ -121,7 +121,7 @@ export class PlanEditorModel extends BaseEditorModel implements PlanPersist {
|
||||||
const baseValidationArray: Validation[] = new Array<Validation>();
|
const baseValidationArray: Validation[] = new Array<Validation>();
|
||||||
baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] });
|
baseValidationArray.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] });
|
||||||
baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] });
|
baseValidationArray.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] });
|
||||||
baseValidationArray.push({ key: 'status', validators: [BackendErrorValidator(this.validationErrorModel, 'status')] });
|
baseValidationArray.push({ key: 'statusId', validators: [BackendErrorValidator(this.validationErrorModel, 'status')] });
|
||||||
baseValidationArray.push({ key: 'properties', validators: [BackendErrorValidator(this.validationErrorModel, 'properties')] });
|
baseValidationArray.push({ key: 'properties', validators: [BackendErrorValidator(this.validationErrorModel, 'properties')] });
|
||||||
baseValidationArray.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] });
|
baseValidationArray.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] });
|
||||||
baseValidationArray.push({ key: 'language', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'language')] });
|
baseValidationArray.push({ key: 'language', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'language')] });
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { takeUntil, tap } from 'rxjs/operators';
|
||||||
import { nameof } from 'ts-simple-nameof';
|
import { nameof } from 'ts-simple-nameof';
|
||||||
import { EntityDoi } from '@app/core/model/entity-doi/entity-doi';
|
import { EntityDoi } from '@app/core/model/entity-doi/entity-doi';
|
||||||
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
|
||||||
|
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PlanEditorEntityResolver extends BaseEditorResolver {
|
export class PlanEditorEntityResolver extends BaseEditorResolver {
|
||||||
|
@ -29,7 +30,13 @@ export class PlanEditorEntityResolver extends BaseEditorResolver {
|
||||||
...BaseEditorResolver.lookupFields(),
|
...BaseEditorResolver.lookupFields(),
|
||||||
nameof<Plan>(x => x.id),
|
nameof<Plan>(x => x.id),
|
||||||
nameof<Plan>(x => x.label),
|
nameof<Plan>(x => x.label),
|
||||||
|
// TODO status remove later
|
||||||
nameof<Plan>(x => x.status),
|
nameof<Plan>(x => x.status),
|
||||||
|
|
||||||
|
[nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.id)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.name)].join('.'),
|
||||||
|
[nameof<Plan>(x => x.status), nameof<PlanStatus>(x => x.internalStatus)].join('.'),
|
||||||
|
|
||||||
nameof<Plan>(x => x.versionStatus),
|
nameof<Plan>(x => x.versionStatus),
|
||||||
nameof<Plan>(x => x.groupId),
|
nameof<Plan>(x => x.groupId),
|
||||||
nameof<Plan>(x => x.description),
|
nameof<Plan>(x => x.description),
|
||||||
|
|
Loading…
Reference in New Issue