Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring
This commit is contained in:
commit
346ef4476a
|
@ -13,6 +13,7 @@ import org.opencdmp.commons.enums.IsActive;
|
||||||
import org.opencdmp.convention.ConventionService;
|
import org.opencdmp.convention.ConventionService;
|
||||||
import org.opencdmp.data.DmpEntity;
|
import org.opencdmp.data.DmpEntity;
|
||||||
import org.opencdmp.model.*;
|
import org.opencdmp.model.*;
|
||||||
|
import org.opencdmp.model.dmp.Dmp;
|
||||||
import org.opencdmp.query.*;
|
import org.opencdmp.query.*;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -88,7 +89,10 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
|
||||||
if (dmpUsersMap != null && !dmpUsersMap.isEmpty() && dmpUsersMap.containsKey(d.getId())) m.setDmpUsers(dmpUsersMap.get(d.getId()));
|
if (dmpUsersMap != null && !dmpUsersMap.isEmpty() && dmpUsersMap.containsKey(d.getId())) m.setDmpUsers(dmpUsersMap.get(d.getId()));
|
||||||
if (descriptionsMap != null && !descriptionsMap.isEmpty() && descriptionsMap.containsKey(d.getId())) m.setDescriptions(descriptionsMap.get(d.getId()));
|
if (descriptionsMap != null && !descriptionsMap.isEmpty() && descriptionsMap.containsKey(d.getId())) m.setDescriptions(descriptionsMap.get(d.getId()));
|
||||||
if (entityDoisMap != null && !entityDoisMap.isEmpty() && entityDoisMap.containsKey(d.getId())) m.setEntityDois(entityDoisMap.get(d.getId()));
|
if (entityDoisMap != null && !entityDoisMap.isEmpty() && entityDoisMap.containsKey(d.getId())) m.setEntityDois(entityDoisMap.get(d.getId()));
|
||||||
if (otherDmpVersionsMap != null && !otherDmpVersionsMap.isEmpty() && otherDmpVersionsMap.containsKey(d.getGroupId())) m.setOtherDmpVersions(otherDmpVersionsMap.get(d.getGroupId()));
|
if (otherDmpVersionsMap != null && !otherDmpVersionsMap.isEmpty() && otherDmpVersionsMap.containsKey(d.getGroupId())){
|
||||||
|
m.setOtherDmpVersions(otherDmpVersionsMap.get(d.getGroupId()));
|
||||||
|
m.getOtherDmpVersions().sort(Comparator.comparing(PublicDmp::getVersion));
|
||||||
|
}
|
||||||
|
|
||||||
models.add(m);
|
models.add(m);
|
||||||
}
|
}
|
||||||
|
@ -178,7 +182,7 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
|
||||||
DmpQuery query = this.queryFactory.query(DmpQuery.class).disableTracking().authorize(this.authorize).groupIds(data.stream().map(DmpEntity::getGroupId).distinct().collect(Collectors.toList())).isActive(IsActive.Active);
|
DmpQuery query = this.queryFactory.query(DmpQuery.class).disableTracking().authorize(this.authorize).groupIds(data.stream().map(DmpEntity::getGroupId).distinct().collect(Collectors.toList())).isActive(IsActive.Active);
|
||||||
itemMap = this.builderFactory.builder(PublicDmpBuilder.class).authorize(this.authorize).asMasterKey(query, clone, PublicDmp::getGroupId);
|
itemMap = this.builderFactory.builder(PublicDmpBuilder.class).authorize(this.authorize).asMasterKey(query, clone, PublicDmp::getGroupId);
|
||||||
|
|
||||||
if (!fields.hasField(this.asIndexer(PublicDmp._otherDmpVersions, PublicDmp._id))) {
|
if (!fields.hasField(PublicDmp._id)) {
|
||||||
itemMap.values().stream().flatMap(List::stream).filter(Objects::nonNull).forEach(x -> {
|
itemMap.values().stream().flatMap(List::stream).filter(Objects::nonNull).forEach(x -> {
|
||||||
x.setId(null);
|
x.setId(null);
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.opencdmp.model.dmpblueprint.DmpBlueprint;
|
||||||
import org.opencdmp.model.dmpreference.DmpReference;
|
import org.opencdmp.model.dmpreference.DmpReference;
|
||||||
import org.opencdmp.model.user.User;
|
import org.opencdmp.model.user.User;
|
||||||
import org.opencdmp.query.*;
|
import org.opencdmp.query.*;
|
||||||
|
import org.opencdmp.service.externalfetcher.config.entities.SourceBaseConfiguration;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
@ -137,7 +138,10 @@ public class DmpBuilder extends BaseBuilder<Dmp, DmpEntity> {
|
||||||
if (dmpUsersMap != null && !dmpUsersMap.isEmpty() && dmpUsersMap.containsKey(d.getId())) m.setDmpUsers(dmpUsersMap.get(d.getId()));
|
if (dmpUsersMap != null && !dmpUsersMap.isEmpty() && dmpUsersMap.containsKey(d.getId())) m.setDmpUsers(dmpUsersMap.get(d.getId()));
|
||||||
if (descriptionsMap != null && !descriptionsMap.isEmpty() && descriptionsMap.containsKey(d.getId())) m.setDescriptions(descriptionsMap.get(d.getId()));
|
if (descriptionsMap != null && !descriptionsMap.isEmpty() && descriptionsMap.containsKey(d.getId())) m.setDescriptions(descriptionsMap.get(d.getId()));
|
||||||
if (dmpDescriptionTemplatesMap != null && !dmpDescriptionTemplatesMap.isEmpty() && dmpDescriptionTemplatesMap.containsKey(d.getId())) m.setDmpDescriptionTemplates(dmpDescriptionTemplatesMap.get(d.getId()));
|
if (dmpDescriptionTemplatesMap != null && !dmpDescriptionTemplatesMap.isEmpty() && dmpDescriptionTemplatesMap.containsKey(d.getId())) m.setDmpDescriptionTemplates(dmpDescriptionTemplatesMap.get(d.getId()));
|
||||||
if (otherDmpVersionsMap != null && !otherDmpVersionsMap.isEmpty() && otherDmpVersionsMap.containsKey(d.getGroupId())) m.setOtherDmpVersions(otherDmpVersionsMap.get(d.getGroupId()));
|
if (otherDmpVersionsMap != null && !otherDmpVersionsMap.isEmpty() && otherDmpVersionsMap.containsKey(d.getGroupId())) {
|
||||||
|
m.setOtherDmpVersions(otherDmpVersionsMap.get(d.getGroupId()));
|
||||||
|
m.getOtherDmpVersions().sort(Comparator.comparing(Dmp::getVersion));
|
||||||
|
}
|
||||||
if (!propertiesFields.isEmpty() && d.getProperties() != null){
|
if (!propertiesFields.isEmpty() && d.getProperties() != null){
|
||||||
DmpPropertiesEntity propertyDefinition = this.jsonHandlingService.fromJsonSafe(DmpPropertiesEntity.class, d.getProperties());
|
DmpPropertiesEntity propertyDefinition = this.jsonHandlingService.fromJsonSafe(DmpPropertiesEntity.class, d.getProperties());
|
||||||
m.setProperties(this.builderFactory.builder(DmpPropertiesBuilder.class).authorize(this.authorize).build(propertiesFields, propertyDefinition));
|
m.setProperties(this.builderFactory.builder(DmpPropertiesBuilder.class).authorize(this.authorize).build(propertiesFields, propertyDefinition));
|
||||||
|
@ -310,7 +314,7 @@ public class DmpBuilder extends BaseBuilder<Dmp, DmpEntity> {
|
||||||
DmpQuery query = this.queryFactory.query(DmpQuery.class).disableTracking().authorize(this.authorize).groupIds(data.stream().map(DmpEntity::getGroupId).distinct().collect(Collectors.toList()));
|
DmpQuery query = this.queryFactory.query(DmpQuery.class).disableTracking().authorize(this.authorize).groupIds(data.stream().map(DmpEntity::getGroupId).distinct().collect(Collectors.toList()));
|
||||||
itemMap = this.builderFactory.builder(DmpBuilder.class).authorize(this.authorize).asMasterKey(query, clone, Dmp::getGroupId);
|
itemMap = this.builderFactory.builder(DmpBuilder.class).authorize(this.authorize).asMasterKey(query, clone, Dmp::getGroupId);
|
||||||
|
|
||||||
if (!fields.hasField(this.asIndexer(Dmp._otherDmpVersions, Dmp._id))) {
|
if (!fields.hasField(Dmp._id)) {
|
||||||
itemMap.values().stream().flatMap(List::stream).filter(Objects::nonNull).forEach(x -> {
|
itemMap.values().stream().flatMap(List::stream).filter(Objects::nonNull).forEach(x -> {
|
||||||
x.setId(null);
|
x.setId(null);
|
||||||
});
|
});
|
||||||
|
|
|
@ -128,17 +128,18 @@ public class FieldPersist {
|
||||||
protected List<Specification> specifications(FieldPersist item) {
|
protected List<Specification> specifications(FieldPersist item) {
|
||||||
FieldType fieldType = this.fieldEntity != null && this.fieldEntity.getData() != null ? this.fieldEntity.getData().getFieldType() : FieldType.FREE_TEXT;
|
FieldType fieldType = this.fieldEntity != null && this.fieldEntity.getData() != null ? this.fieldEntity.getData().getFieldType() : FieldType.FREE_TEXT;
|
||||||
boolean required = this.fieldEntity != null && this.fieldEntity.getValidations() != null ? this.fieldEntity.getValidations().contains(FieldValidationType.Required) : false;
|
boolean required = this.fieldEntity != null && this.fieldEntity.getValidations() != null ? this.fieldEntity.getValidations().contains(FieldValidationType.Required) : false;
|
||||||
boolean isUrlRequired = this.fieldEntity != null && this.fieldEntity.getValidations() != null ? this.fieldEntity.getValidations().contains(FieldValidationType.Url) : false;
|
// boolean isUrlRequired = this.fieldEntity != null && this.fieldEntity.getValidations() != null ? this.fieldEntity.getValidations().contains(FieldValidationType.Url) : false;
|
||||||
boolean isVisible = this.fieldEntity != null ? this.visibilityService.isVisible(this.fieldEntity.getId(), this.ordinal) : true;
|
boolean isVisible = this.fieldEntity != null ? this.visibilityService.isVisible(this.fieldEntity.getId(), this.ordinal) : true;
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
this.spec()
|
this.spec()
|
||||||
.iff(()-> FieldType.isTextType(fieldType) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required)
|
.iff(()-> FieldType.isTextType(fieldType) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required)
|
||||||
.must(() -> !this.isEmpty(item.getTextValue()))
|
.must(() -> !this.isEmpty(item.getTextValue()))
|
||||||
.failOn(FieldPersist._textValue).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{FieldPersist._textValue}, LocaleContextHolder.getLocale())),
|
.failOn(FieldPersist._textValue).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{FieldPersist._textValue}, LocaleContextHolder.getLocale())),
|
||||||
this.spec()
|
//TODO
|
||||||
.iff(()-> fieldType.equals(FieldType.FREE_TEXT) && DescriptionStatus.Finalized.equals(this.status) && isVisible && isUrlRequired)
|
// this.spec()
|
||||||
.must(() -> this.isValidURL(item.getTextValue()))
|
// .iff(()-> fieldType.equals(FieldType.FREE_TEXT) && DescriptionStatus.Finalized.equals(this.status) && isVisible && isUrlRequired && (required || !this.isEmpty(item.getTextValue())))
|
||||||
.failOn(FieldPersist._textValue).failWith(this.messageSource.getMessage("Validation_UrlRequired", new Object[]{FieldPersist._textValue}, LocaleContextHolder.getLocale())),
|
// .must(() -> this.isValidURL(item.getTextValue()))
|
||||||
|
// .failOn(FieldPersist._textValue).failWith(this.messageSource.getMessage("Validation_UrlRequired", new Object[]{FieldPersist._textValue}, LocaleContextHolder.getLocale())),
|
||||||
this.spec()
|
this.spec()
|
||||||
.iff(()-> FieldType.isDateType(fieldType) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required)
|
.iff(()-> FieldType.isDateType(fieldType) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required)
|
||||||
.must(() -> !this.isNull(item.getDateValue()))
|
.must(() -> !this.isNull(item.getDateValue()))
|
||||||
|
|
|
@ -343,7 +343,7 @@ public class DmpServiceImpl implements DmpService {
|
||||||
.groupIds(data.getGroupId());
|
.groupIds(data.getGroupId());
|
||||||
|
|
||||||
dmpQuery.setOrder(new Ordering().addDescending(Dmp._version));
|
dmpQuery.setOrder(new Ordering().addDescending(Dmp._version));
|
||||||
previousDmp = dmpQuery.first();
|
previousDmp = dmpQuery.collect().get(0);
|
||||||
if (previousDmp != null){
|
if (previousDmp != null){
|
||||||
if (previousDmp.getStatus().equals(DmpStatus.Finalized)) previousDmp.setVersionStatus(DmpVersionStatus.Current);
|
if (previousDmp.getStatus().equals(DmpStatus.Finalized)) previousDmp.setVersionStatus(DmpVersionStatus.Current);
|
||||||
else previousDmp.setVersionStatus(DmpVersionStatus.NotFinalized);
|
else previousDmp.setVersionStatus(DmpVersionStatus.NotFinalized);
|
||||||
|
@ -566,7 +566,8 @@ public class DmpServiceImpl implements DmpService {
|
||||||
|
|
||||||
if (newStatus.equals(DmpStatus.Finalized)) {
|
if (newStatus.equals(DmpStatus.Finalized)) {
|
||||||
List<DmpEntity> latestVersionDmps = this.queryFactory.query(DmpQuery.class)
|
List<DmpEntity> latestVersionDmps = this.queryFactory.query(DmpQuery.class)
|
||||||
.versionStatuses(DmpVersionStatus.Current).isActive(IsActive.Active).groupIds(data.getGroupId()).collect();
|
.versionStatuses(DmpVersionStatus.Current).excludedIds(data.getId())
|
||||||
|
.isActive(IsActive.Active).groupIds(data.getGroupId()).collect();
|
||||||
if (latestVersionDmps.size() > 1)
|
if (latestVersionDmps.size() > 1)
|
||||||
throw new MyValidationException("Multiple previous template found");
|
throw new MyValidationException("Multiple previous template found");
|
||||||
DmpEntity oldDmpEntity = latestVersionDmps.stream().findFirst().orElse(null);
|
DmpEntity oldDmpEntity = latestVersionDmps.stream().findFirst().orElse(null);
|
||||||
|
@ -1086,11 +1087,28 @@ public class DmpServiceImpl implements DmpService {
|
||||||
|
|
||||||
dmp.setStatus(DmpStatus.Draft);
|
dmp.setStatus(DmpStatus.Draft);
|
||||||
dmp.setUpdatedAt(Instant.now());
|
dmp.setUpdatedAt(Instant.now());
|
||||||
dmp.setVersionStatus(DmpVersionStatus.NotFinalized);
|
|
||||||
|
|
||||||
this.entityManager.merge(dmp);
|
this.entityManager.merge(dmp);
|
||||||
this.entityManager.flush();
|
this.entityManager.flush();
|
||||||
|
|
||||||
|
this.updateVersionStatusAndSave(dmp, DmpStatus.Finalized, dmp.getStatus());
|
||||||
|
this.entityManager.flush();
|
||||||
|
|
||||||
|
DmpQuery dmpQuery = this.queryFactory.query(DmpQuery.class).disableTracking()
|
||||||
|
.versionStatuses(DmpVersionStatus.Previous)
|
||||||
|
.excludedIds(dmp.getId())
|
||||||
|
.isActive(IsActive.Active)
|
||||||
|
.groupIds(dmp.getGroupId());
|
||||||
|
|
||||||
|
dmpQuery.setOrder(new Ordering().addDescending(Dmp._version));
|
||||||
|
DmpEntity previousDmp = dmpQuery.collect().get(0);
|
||||||
|
if (previousDmp != null){
|
||||||
|
if (previousDmp.getStatus().equals(DmpStatus.Finalized)) previousDmp.setVersionStatus(DmpVersionStatus.Current);
|
||||||
|
else previousDmp.setVersionStatus(DmpVersionStatus.NotFinalized);
|
||||||
|
this.entityManager.merge(previousDmp);
|
||||||
|
}
|
||||||
|
this.entityManager.flush();
|
||||||
|
|
||||||
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(dmp.getId());
|
this.annotationEntityTouchedIntegrationEventHandler.handleDmp(dmp.getId());
|
||||||
this.sendNotification(dmp);
|
this.sendNotification(dmp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,9 @@ description: Discover how to create a new plan
|
||||||
|
|
||||||
-img- start a new plan -img-
|
-img- start a new plan -img-
|
||||||
|
|
||||||
To create a new Plan in OpenCDMP you can either [import](/docs/documentation/application/plans/imports) an existing plan from other source or writting a Plan from start. It provides an editor that you must fill **Title**, **Description** and select the [**Blueprint**](/docs/documentation/administration/blueprints/) of this plan that describes the structure. Also there is a Default Plan Blueprint for use. After save, the plan is automatically in draft status.
|
To create a new Plan in OpenCDMP you can either [import](/docs/documentation/application/plans/imports) an existing plan from a file or fill in a Plan from the start.
|
||||||
|
|
||||||
|
To do this, there is a form available where you must fill a **Title**, a **Description** and select the **[Blueprint](/docs/documentation/administration/blueprints/)** of this plan that describes its structure. Also, there is a Default Plan Blueprint for use. When ready, after you press `save`, the plan is automatically saved having the `draft` status. More information about the lifecycle of a plan, can be found [here](/docs/documentation/application/plans/plan-lifecycle).
|
||||||
|
|
||||||
-img- plan editor first step -img-
|
-img- plan editor first step -img-
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,10 @@ description: Discover how to edit a plan
|
||||||
|
|
||||||
# Edit a Plan
|
# Edit a Plan
|
||||||
|
|
||||||
You can view a plan by either from `Home Page` or from `My Plans`. By selecting the plan you can view the overview and all actions for this.
|
You can view a plan either from `Home Page` or from `My Plans`. By selecting the plan you can view the overview and all the actions available for it.
|
||||||
|
|
||||||
-img- plan overview -img-
|
-img- plan overview -img-
|
||||||
|
|
||||||
In edit state you can make and revert changes but also add descriptions to specific section that contains description templates field.
|
While in the edit view, you can make and revert changes but also add descriptions to specific sections that contain description template fields.
|
||||||
|
|
||||||
-img- plan editor in edit state -img-
|
-img- plan editor in edit state -img-
|
|
@ -7,7 +7,7 @@ description: Discover export options for a plan
|
||||||
|
|
||||||
-img- export plan-img-
|
-img- export plan-img-
|
||||||
|
|
||||||
Application supports download the structure of the plan in the following formats:
|
You can export the structure of a plan in the following formats:
|
||||||
- **PDF**
|
- **PDF**
|
||||||
- **DOCX**
|
- **DOCX**
|
||||||
- **RDA JSON**
|
- **RDA JSON**
|
||||||
|
@ -15,7 +15,7 @@ Application supports download the structure of the plan in the following formats
|
||||||
|
|
||||||
:::tip
|
:::tip
|
||||||
|
|
||||||
- You can use the export feature in anytime in plans' lifecycle
|
- You can use the export feature anytime in a plans' lifecycle
|
||||||
- Export is also available in Public Plans
|
- Export is also available for the Public Plans
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
|
@ -5,6 +5,6 @@ description: Discover import options for a plan
|
||||||
|
|
||||||
# Imports
|
# Imports
|
||||||
|
|
||||||
You can import an existing plan to continue work in appliation. Import supports upload of `.json` files that are produced according to [RDA specifications](https://github.com/RDA-DMP-Common/RDA-DMP-Common-Standard) for machine-actionable plans.
|
You can import an existing plan so that you don't have to work on a new one from scratch. Import supports the upload of `.json` files that are produced according to [RDA specifications](https://github.com/RDA-DMP-Common/RDA-DMP-Common-Standard) for machine-actionable plans.
|
||||||
|
|
||||||
-img- import plan pop up dialog -img-
|
-img- import plan pop up dialog -img-
|
||||||
|
|
|
@ -7,18 +7,19 @@ description: Discover how you invite people to a plan
|
||||||
|
|
||||||
-img- invite users -img-
|
-img- invite users -img-
|
||||||
|
|
||||||
Before finalization, the plan can be further edited by inviting users collaborate on completing this. There are two methods to invite users:
|
Before finalization, the plan can be further edited by inviting users in order to collaborate on it and complete it. There are two methods to invite users:
|
||||||
- **External**: If user is registered in application then a notification (email or in App) sends to him. If not, a registration email sends.
|
- **External**: If the user is registered in the application, then a notification (email or in App) gets sent to him. If not, a registration email is being sent instead.
|
||||||
- **Internal**: It's a quick way, that we can invite users that is already associated to other plans we work with as well.
|
- **Internal**: It's a quick way, that we can invite users already associated to other plans we work with as well.
|
||||||
|
|
||||||
|
For each member, a role on the plan must be defined. There are three different roles:
|
||||||
|
|
||||||
For each member, must be defined the role for the plan. There are three different roles:
|
- **Owner**: Manage and edit all plan features.
|
||||||
|
- **Description Contributor**: Edit only the descriptions of this plan.
|
||||||
- **Owner**: manage and edit all plan features.
|
- **Reviewer**: View the plan without being able to edit it.
|
||||||
- **Description Contributor**: only edit descriptions of this plan.
|
|
||||||
- **Reviewer**: view the plan but no rights to edit.
|
|
||||||
|
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
the roles' features can be apply to entire plan or specific section
|
|
||||||
|
The collaboration roles we discussed above, can be applied to an entire plan or only to a specific section of it.
|
||||||
|
|
||||||
:::
|
:::
|
|
@ -5,4 +5,14 @@ description: Discover the lifecycle of a plan
|
||||||
|
|
||||||
# Plan lifecycle
|
# Plan lifecycle
|
||||||
|
|
||||||
After a plan is created automatically get the draft status. In `My Plans` they appears all the plans that user has or collaborate.
|
After a plan is created, it gets saved automatically in `draft` mode. While in this mode, the user can make any changes he wants and save it as many times as he wants. When ready, the user can then `finalize` it which means no more changes will be possible. If there comes a need for further editing after the plan is already finalized, the user has the option to undo the finalization and bring it back into `draft` mode.
|
||||||
|
|
||||||
|
A finalized plan can then be [deposited](/docs/documentation/application/plans/doi-assignment.md).
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
|
||||||
|
When a plan gets deposited it can not be edited anymore. This action is irreversible. In this case, the only option is to either clone it or make a new [version](/docs/documentation/application/plans/versions) of it.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
In the `My Plans` page, the user can view all the plans he has created or the ones he has been invited as a [collaborator](/docs/documentation/application/plans/invite-collaborators).
|
|
@ -5,15 +5,15 @@ description: Discover plan versioning options
|
||||||
|
|
||||||
# Versions
|
# Versions
|
||||||
|
|
||||||
|
A plan can have many versions. There is always one version that is marked as `current`, it is the most recent version and it is the one that gets displayed on the listing views. All the other ones are marked as `previous` and can be viewed when the `All Plan Versions` option is pressed.
|
||||||
|
|
||||||
:::info
|
:::info
|
||||||
If the plan is finalized you can create a new version for it. New Version don't delete the previous version of this plan, just creates a new with draft status.
|
|
||||||
|
If the plan is finalized you can create a new version for it, which will have all the properties of the last one and it will be in `draft` mode ready for changes. Making a new version doesn't delete the previous ones.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
`New Version` button exists in `My Plans` or `Plan Overview` actions. In new version form can change the title, description, plan blueprint and optional select which descriptions include in the new version. After the process is completed, plan and descriptions are available to edit.
|
The `New Version` option cab be found in the `My Plans` or `Plan Overview` pages. In the new version form, the user can change titles, descriptions, plan blueprints and optionally select which descriptions to include in the new version. After the process is completed, the new plan and descriptions are available for editing.
|
||||||
|
|
||||||
-img- new version overview -img-
|
-img- new version overview -img-
|
||||||
-img- new version listing -img-
|
-img- new version listing -img-
|
||||||
|
|
||||||
:::tip
|
|
||||||
`All Plan Versions` - shows the history of the different versions of the existing plan
|
|
||||||
:::
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Supplementary Services
|
# Supplementary Services
|
||||||
|
|
||||||
There are four supplementary services directly integrated into this platform. They are used to extend it's functionality and improve the user experience. In this section of the docs, we will dive into each one of them, and see how they contribute to the overall usage of the platform.
|
There are four supplementary services directly integrated into this platform. They are used to extend its functionality and improve the user experience. In this section of the docs, we will dive into each one of them, and see how they contribute to the overall usage of the platform.
|
||||||
|
|
||||||
Follow the links below, to find out more information about them respectively.
|
Follow the links below, to find out more information about them respectively.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue