deposit, export actions based by status definition, ui fixes

This commit is contained in:
CITE\amentis 2024-09-20 18:09:21 +03:00
parent 12a57f875a
commit cd8c5d05ff
23 changed files with 252 additions and 62 deletions

View File

@ -14,6 +14,9 @@ public class PublicDescriptionStatus {
public final static String _internalStatus = "internalStatus";
private org.opencdmp.commons.enums.DescriptionStatus internalStatus;
public final static String _definition = "definition";
private PublicDescriptionStatusDefinition definition;
public UUID getId() { return this.id; }
public void setId(UUID id) { this.id = id; }
@ -22,4 +25,12 @@ public class PublicDescriptionStatus {
public org.opencdmp.commons.enums.DescriptionStatus getInternalStatus() { return this.internalStatus; }
public void setInternalStatus(org.opencdmp.commons.enums.DescriptionStatus internalStatus) { this.internalStatus = internalStatus; }
public PublicDescriptionStatusDefinition getDefinition() {
return definition;
}
public void setDefinition(PublicDescriptionStatusDefinition definition) {
this.definition = definition;
}
}

View File

@ -0,0 +1,20 @@
package org.opencdmp.model;
import org.opencdmp.commons.enums.DescriptionStatusAvailableActionType;
import java.util.List;
public class PublicDescriptionStatusDefinition {
public final static String _availableActions = "availableActions";
private List<DescriptionStatusAvailableActionType> availableActions;
public List<DescriptionStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<DescriptionStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
}

View File

@ -16,6 +16,9 @@ public class PublicPlanStatus {
public final static String _internalStatus = "internalStatus";
private PlanStatus internalStatus;
public final static String _definition = "definition";
private PublicPlanStatusDefinition definition;
public UUID getId() { return this.id; }
public void setId(UUID id) { this.id = id; }
@ -29,4 +32,12 @@ public class PublicPlanStatus {
public void setInternalStatus(PlanStatus internalStatus) {
this.internalStatus = internalStatus;
}
public PublicPlanStatusDefinition getDefinition() {
return definition;
}
public void setDefinition(PublicPlanStatusDefinition definition) {
this.definition = definition;
}
}

View File

@ -0,0 +1,21 @@
package org.opencdmp.model;
import org.opencdmp.commons.enums.PlanStatusAvailableActionType;
import java.util.List;
public class PublicPlanStatusDefinition {
public final static String _availableActions = "availableActions";
private List<PlanStatusAvailableActionType> availableActions;
public List<PlanStatusAvailableActionType> getAvailableActions() {
return availableActions;
}
public void setAvailableActions(List<PlanStatusAvailableActionType> availableActions) {
this.availableActions = availableActions;
}
}

View File

@ -1,10 +1,13 @@
package org.opencdmp.model.builder;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
import org.opencdmp.convention.ConventionService;
@ -22,11 +25,16 @@ import java.util.*;
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PublicDescriptionStatusBuilder extends BaseBuilder<PublicDescriptionStatus, DescriptionStatusEntity> {
private final XmlHandlingService xmlHandlingService;
private final BuilderFactory builderFactory;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PublicDescriptionStatusBuilder(
ConventionService conventionService) {
ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicDescriptionStatusBuilder.class)));
this.xmlHandlingService = xmlHandlingService;
this.builderFactory = builderFactory;
}
public PublicDescriptionStatusBuilder authorize(EnumSet<AuthorizationFlags> values) {
@ -41,11 +49,17 @@ public class PublicDescriptionStatusBuilder extends BaseBuilder<PublicDescriptio
if (fields == null || data == null || fields.isEmpty())
return new ArrayList<>();
List<PublicDescriptionStatus> models = new ArrayList<>();
FieldSet definitionFields = fields.extractPrefixed(this.asPrefix(PublicDescriptionStatus._definition));
for (DescriptionStatusEntity d : data) {
PublicDescriptionStatus m = new PublicDescriptionStatus();
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._name))) m.setName(d.getName());
if (fields.hasField(this.asIndexer(PublicDescriptionStatus._internalStatus))) m.setInternalStatus(d.getInternalStatus());
if (!definitionFields.isEmpty() && d.getDefinition() != null) {
DescriptionStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(DescriptionStatusDefinitionEntity.class, d.getDefinition());
m.setDefinition(this.builderFactory.builder(PublicDescriptionStatusDefinitionBuilder.class).authorize(this.authorize).build(definitionFields, definition));
}
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));

View File

@ -0,0 +1,51 @@
package org.opencdmp.model.builder;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.types.descriptionstatus.DescriptionStatusDefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.model.PublicDescriptionStatusDefinition;
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 PublicDescriptionStatusDefinitionBuilder extends BaseBuilder<PublicDescriptionStatusDefinition, DescriptionStatusDefinitionEntity> {
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PublicDescriptionStatusDefinitionBuilder(
ConventionService conventionService) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicDescriptionStatusDefinitionBuilder.class)));
}
public PublicDescriptionStatusDefinitionBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
public List<PublicDescriptionStatusDefinition> build(FieldSet fields, List<DescriptionStatusDefinitionEntity> 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<PublicDescriptionStatusDefinition> models = new ArrayList<>();
for (DescriptionStatusDefinitionEntity d : data) {
PublicDescriptionStatusDefinition m = new PublicDescriptionStatusDefinition();
if (fields.hasField(this.asIndexer(PublicDescriptionStatusDefinition._availableActions))) m.setAvailableActions(d.getAvailableActions());
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
}

View File

@ -1,13 +1,17 @@
package org.opencdmp.model.builder;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.PlanStatusEntity;
import org.opencdmp.model.PublicPlanStatus;
import org.opencdmp.model.builder.planstatus.PlanStatusDefinitionBuilder;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -20,11 +24,16 @@ import java.util.*;
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PublicPlanStatusBuilder extends BaseBuilder<PublicPlanStatus, PlanStatusEntity> {
private final XmlHandlingService xmlHandlingService;
private final BuilderFactory builderFactory;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PublicPlanStatusBuilder(
ConventionService conventionService) {
ConventionService conventionService, XmlHandlingService xmlHandlingService, BuilderFactory builderFactory) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicPlanStatusBuilder.class)));
this.xmlHandlingService = xmlHandlingService;
this.builderFactory = builderFactory;
}
public PublicPlanStatusBuilder authorize(EnumSet<AuthorizationFlags> values) {
@ -38,12 +47,19 @@ public class PublicPlanStatusBuilder extends BaseBuilder<PublicPlanStatus, PlanS
this.logger.trace(new DataLogEntry("requested fields", fields));
if (fields == null || data == null || fields.isEmpty())
return new ArrayList<>();
FieldSet definitionFields = fields.extractPrefixed(this.asPrefix(PublicPlanStatus._definition));
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());
if (!definitionFields.isEmpty() && d.getDefinition() != null) {
PlanStatusDefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(PlanStatusDefinitionEntity.class, d.getDefinition());
m.setDefinition(this.builderFactory.builder(PublicPlanStatusDefinitionBuilder.class).authorize(this.authorize).build(definitionFields, definition));
}
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));

View File

@ -0,0 +1,50 @@
package org.opencdmp.model.builder;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.types.planstatus.PlanStatusDefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.model.PublicPlanStatusDefinition;
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 PublicPlanStatusDefinitionBuilder extends BaseBuilder<PublicPlanStatusDefinition, PlanStatusDefinitionEntity> {
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
@Autowired
public PublicPlanStatusDefinitionBuilder(
ConventionService conventionService) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PublicPlanStatusDefinitionBuilder.class)));
}
public PublicPlanStatusDefinitionBuilder authorize(EnumSet<AuthorizationFlags> values) {
this.authorize = values;
return this;
}
@Override
public List<PublicPlanStatusDefinition> build(FieldSet fields, List<PlanStatusDefinitionEntity> 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<PublicPlanStatusDefinition> models = new ArrayList<>();
for (PlanStatusDefinitionEntity d : data) {
PublicPlanStatusDefinition m = new PublicPlanStatusDefinition();
if (fields.hasField(this.asIndexer(PublicPlanStatusDefinition._availableActions))) m.setAvailableActions(d.getAvailableActions());
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));
return models;
}
}

View File

@ -198,7 +198,7 @@ public class DescriptionStatusQuery extends QueryBase<DescriptionStatusEntity> {
return DescriptionStatusEntity._tenantId;
else if (item.match(DescriptionStatus._internalStatus))
return DescriptionStatusEntity._internalStatus;
else if (item.match(DescriptionStatusEntity._definition))
else if (item.prefix(DescriptionStatusEntity._definition))
return DescriptionStatusEntity._definition;
else
return null;

View File

@ -189,7 +189,7 @@ public class PlanStatusQuery extends QueryBase<PlanStatusEntity> {
return PlanStatusEntity._name;
else if (item.match(PlanStatus._internalStatus))
return PlanStatusEntity._internalStatus;
else if (item.match(PlanStatus._definition))
else if (item.prefix(PlanStatus._definition))
return PlanStatusEntity._definition;
else if (item.match(PlanStatus._createdAt))
return PlanStatusEntity._createdAt;

View File

@ -314,6 +314,10 @@ public class PlanServiceImpl implements PlanService {
}
private void sendNotification(PlanEntity plan) throws InvalidApplicationException {
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 (planStatusEntity.getInternalStatus() == null) return;
List<PlanUserEntity> existingUsers = this.queryFactory.query(PlanUserQuery.class).disableTracking()
.planIds(plan.getId())
.isActives(IsActive.Active)
@ -327,16 +331,16 @@ public class PlanServiceImpl implements PlanService {
if (!planUser.getUserId().equals(this.userScope.getUserIdSafe())){
UserEntity user = this.queryFactory.query(UserQuery.class).disableTracking().ids(planUser.getUserId()).first();
if (user == null || user.getIsActive().equals(IsActive.Inactive)) throw new MyValidationException(this.errors.getPlanInactiveUser().getCode(), this.errors.getPlanInactiveUser().getMessage());
this.createPlanNotificationEvent(plan, user);
this.createPlanNotificationEvent(plan, planStatusEntity.getInternalStatus(), user);
}
}
}
private void createPlanNotificationEvent(PlanEntity plan, UserEntity user) throws InvalidApplicationException {
private void createPlanNotificationEvent(PlanEntity plan, PlanStatus internalStatus, UserEntity user) throws InvalidApplicationException {
NotifyIntegrationEvent event = new NotifyIntegrationEvent();
event.setUserId(user.getId());
this.applyNotificationType(plan.getStatus(), event);
this.applyNotificationType(internalStatus, event);
NotificationFieldData data = new NotificationFieldData();
List<FieldInfo> fieldInfoList = new ArrayList<>();
fieldInfoList.add(new FieldInfo("{recipient}", DataType.String, user.getName()));

View File

@ -7,7 +7,7 @@ import { Reference, ReferencePersist } from "../reference/reference";
import { Tag, TagPersist } from "../tag/tag";
import { User } from "../user/user";
import { AppPermission } from "@app/core/common/enum/permission.enum";
import { DescriptionStatus } from "../description-status/description-status";
import { DescriptionStatus, DescriptionStatusDefinition } from "../description-status/description-status";
export interface Description extends BaseDescription {
label?: string;
@ -155,6 +155,7 @@ export interface PublicDescriptionStatus {
id: Guid;
name: string;
internalStatus: DescriptionStatusEnum;
definition: DescriptionStatusDefinition;
}
export interface DescriptionSectionPermissionResolver {

View File

@ -30,7 +30,7 @@
<div class="row h-100">
<div class="col-auto d-flex align-items-center">
<button *ngIf="formGroup.get('id').value" [disabled]="isDirty()" [matTooltipDisabled]="!isDirty()" mat-button class="rounded-btn neutral" type="button" [matMenuTriggerFor]="exportMenu" (click)="$event.stopPropagation();" [matTooltip]="'DESCRIPTION-EDITOR.ACTIONS.EXPORT.CAN-NOT-EXPORT' | translate">
<button *ngIf="formGroup.get('id').value && canExport" [disabled]="isDirty()" [matTooltipDisabled]="!isDirty()" mat-button class="rounded-btn neutral" type="button" [matMenuTriggerFor]="exportMenu" (click)="$event.stopPropagation();" [matTooltip]="'DESCRIPTION-EDITOR.ACTIONS.EXPORT.CAN-NOT-EXPORT' | translate">
{{ 'DESCRIPTION-EDITOR.ACTIONS.EXPORT.EXPORT' | translate }}
<mat-icon [disabled]="isDirty()" style="width: 14px;" iconPositionEnd>expand_more</mat-icon>
</button>

View File

@ -47,6 +47,7 @@ import { TableOfContentsService } from './table-of-contents/services/table-of-co
import { TableOfContentsComponent } from './table-of-contents/table-of-contents.component';
import { DescriptionStatusService } from '@app/core/services/description-status/description-status.service';
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
import { DescriptionStatusAvailableActionType } from '@app/core/common/enum/description-status-available-action-type';
@Component({
selector: 'app-description-editor-component',
@ -61,6 +62,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
isCopy = false;
canEdit = false;
canAnnotate = false;
canExport = false;
item: Description;
fileTransformerEntityTypeEnum = FileTransformerEntityType;
showDescriptionTemplateLoader = false;
@ -225,6 +227,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
if (data) {
if (data.id) this.getAvailableStatuses(data.id);
if (data.status?.id) this.oldStatusId = data.status.id
if (data.status?.definition?.availableActions?.filter(x => x === DescriptionStatusAvailableActionType.Export).length > 0) this.canExport = true;
}
if (data && data?.plan?.planUsers) data.plan.planUsers = data.plan.planUsers.filter(x => x.isActive === IsActive.Active);
this.item = data;

View File

@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { IsActive } from '@app/core/common/enum/is-active.enum';
import { AppPermission } from '@app/core/common/enum/permission.enum';
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
import { DescriptionStatus, DescriptionStatusDefinition } from '@app/core/model/description-status/description-status';
import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
import { Description, DescriptionExternalIdentifier, DescriptionField, DescriptionPropertyDefinition, DescriptionPropertyDefinitionFieldSet, DescriptionPropertyDefinitionFieldSetItem, DescriptionReference, DescriptionReferenceData, DescriptionTag } from '@app/core/model/description/description';
import { DescriptionTemplatesInSection, PlanBlueprint, PlanBlueprintDefinition, PlanBlueprintDefinitionSection } from '@app/core/model/plan-blueprint/plan-blueprint';
@ -57,6 +57,7 @@ export class DescriptionEditorEntityResolver extends BaseEditorResolver {
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.definition), nameof<DescriptionStatusDefinition>(x => x.availableActions)].join('.'),
[nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),

View File

@ -156,7 +156,7 @@
</div>
</div>
</ng-container>
<ng-container *ngIf="fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Description).length > 0">
<ng-container *ngIf="canExport && fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Description).length > 0">
<div class="row mb-3 align-items-center">
<div class="col-auto pr-0">
<button mat-mini-fab class="frame-btn" [matMenuTriggerFor]="exportMenu">

View File

@ -44,9 +44,10 @@ import { map, takeUntil } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof';
import { DescriptionCopyDialogComponent } from '../description-copy-dialog/description-copy-dialog.component';
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
import { DescriptionStatus, DescriptionStatusDefinition } from '@app/core/model/description-status/description-status';
import { DescriptionStatusService } from '@app/core/services/description-status/description-status.service';
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
import { DescriptionStatusAvailableActionType } from '@app/core/common/enum/description-status-available-action-type';
@Component({
@ -222,6 +223,11 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
return this.language.instant('DESCRIPTION-OVERVIEW.INFOS.UNAUTHORIZED-ORCID');
}
get canExport(): boolean {
if (!this.isAuthenticated()) return false;
return this.description?.status?.definition?.availableActions?.filter(x => x === DescriptionStatusAvailableActionType.Export).length > 0;
}
getAvailableStatuses(id: Guid){
this.descriptionStatusService.getAvailableTransitions(id).pipe(takeUntil(this._destroyed))
.subscribe(
@ -557,6 +563,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
[nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.definition), nameof<DescriptionStatusDefinition>(x => x.availableActions)].join('.'),
nameof<Description>(x => x.updatedAt),
nameof<Description>(x => x.belongsToCurrentTenant),
nameof<Description>(x => x.hash),

View File

@ -45,7 +45,7 @@ import { PlanListingFilters } from './filtering/plan-filter.component';
import { Lookup } from '@common/model/lookup';
import { MatSelectChange } from '@angular/material/select';
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
import { PlanStatus, PlanStatusDefinition } from '@app/core/model/plan-status/plan-status';
@Component({
selector: 'app-plan-listing-component',
@ -498,6 +498,7 @@ export class PlanListingComponent extends BaseListingComponent<BasePlan, PlanLoo
[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.status), nameof<PlanStatus>(x => x.definition), nameof<PlanStatusDefinition>(x => x.availableActions)].join('.'),
nameof<Plan>(x => x.accessType),
nameof<Plan>(x => x.version),
@ -521,9 +522,11 @@ export class PlanListingComponent extends BaseListingComponent<BasePlan, PlanLoo
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.id)].join('.'),
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.name)].join('.'),
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'), [nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
[nameof<Plan>(x => x.descriptions), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.sectionId)].join('.'),
[nameof<Plan>(x => x.descriptions), nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.status), nameof<DescriptionStatus>(x => x.internalStatus)].join('.'),
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.groupId)].join('.'),
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.planDescriptionTemplate), nameof<PlanDescriptionTemplate>(x => x.sectionId)].join('.'),
[nameof<Plan>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
[nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.id)].join('.'),
[nameof<Plan>(x => x.blueprint), nameof<PlanBlueprint>(x => x.label)].join('.'),

View File

@ -203,36 +203,7 @@
</div>
</div>
</ng-container>
<!-- <ng-container *ngIf="isDraftPlan() && canFinalizePlan() && !isLocked">
<div class="row align-items-center" (click)="finalize(plan)">
<div class="col-auto pr-0">
<button mat-mini-fab class="finalize-btn">
<mat-icon class="mat-mini-fab-icon">check</mat-icon>
</button>
</div>
<div class="col-auto pl-0">
<p class="mb-0 pl-2 finalize-txt">{{ 'PLAN-OVERVIEW.ACTIONS.FINALIZE' | translate }}</p>
</div>
</div>
<div class="row align-items-center">0
<div class="col-12">
<hr class="hr-line">
</div>
</div>
</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>
<!-- <ng-container *ngIf="isFinalizedPlan(plan) && hasDoi(plan) && !isPublishedPlan(plan) && canFinalizePlan(plan)">
<div (click)="reverseFinalization()" class="row mb-3 align-items-center">
<div class="col-auto pr-0">
<button mat-mini-fab class="frame-btn">
<mat-icon class="mat-mini-fab-icon">unarchive</mat-icon>
</button>
</div>
<div class="col-auto pl-0">
<p class="mb-0 pl-2 frame-txt">{{ 'PLAN-OVERVIEW.ACTIONS.REVERSE' | translate }}</p>
</div>
</div>
</ng-container> -->
<app-plan-deposit-dropdown *ngIf="(hasDoi(plan) || moreDeposit()) && !this.isPublicView && canDepositPlan(plan) && inputRepos.length > 0" [inputRepos]="inputRepos" [plan]="plan" (outputReposEmitter)="afterDeposit($event)"></app-plan-deposit-dropdown>
<ng-container *ngIf="canExportPlan() && fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Plan).length > 0">
<div class="row mb-3 align-items-center">
<div class="col-auto pr-0">

View File

@ -51,8 +51,9 @@ import { PlanInvitationDialogComponent } from '../invitation/dialog/plan-invitat
import { NewVersionPlanDialogComponent } from '../new-version-dialog/plan-new-version-dialog.component';
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
import { PlanStatus, PlanStatusDefinition } from '@app/core/model/plan-status/plan-status';
import { PlanStatusService } from '@app/core/services/plan/plan-status.service';
import { PlanStatusAvailableActionType } from '@app/core/common/enum/plan-status-available-action-type';
@Component({
selector: 'app-plan-overview',
@ -310,7 +311,9 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
canExportPlan(): boolean {
const authorizationFlags = !this.isPublicView ? (this.plan as Plan).authorizationFlags : [];
return (authorizationFlags?.some(x => x === AppPermission.ExportPlan) || this.authentication.hasPermission(AppPermission.ExportPlan));
return (authorizationFlags?.some(x => x === AppPermission.ExportPlan) || this.authentication.hasPermission(AppPermission.ExportPlan)) &&
this.plan?.status?.definition?.availableActions?.filter(x => x === PlanStatusAvailableActionType.Export).length > 0;
}
canInvitePlanUsers(): boolean {
@ -328,7 +331,8 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
canDepositPlan(): boolean {
const authorizationFlags = !this.isPublicView ? (this.plan as Plan).authorizationFlags : [];
return (authorizationFlags?.some(x => x === AppPermission.DepositPlan) || this.authentication.hasPermission(AppPermission.DepositPlan)) && this.isPublicView == false && this.plan.belongsToCurrentTenant != false;
return (authorizationFlags?.some(x => x === AppPermission.DepositPlan) || this.authentication.hasPermission(AppPermission.DepositPlan)) && this.isPublicView == false && this.plan.belongsToCurrentTenant != false &&
this.plan?.status?.definition?.availableActions?.filter(x => x === PlanStatusAvailableActionType.Deposit).length > 0;
}
@ -426,11 +430,7 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
}
isDraftPlan() {
return this.plan.status?.internalStatus == PlanStatusEnum.Draft;
}
isFinalizedPlan(plan: Plan) {
return plan.status?.internalStatus == PlanStatusEnum.Finalized;
return this.plan.status?.internalStatus != PlanStatusEnum.Finalized;
}
isPublishedPlan() {
@ -671,6 +671,7 @@ export class PlanOverviewComponent extends BaseComponent implements OnInit {
[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.status), nameof<PlanStatus>(x => x.definition), nameof<PlanStatusDefinition>(x => x.availableActions)].join('.'),
nameof<Plan>(x => x.accessType),
nameof<Plan>(x => x.version),
nameof<Plan>(x => x.versionStatus),

View File

@ -11,7 +11,7 @@
</div>
<div *ngIf="step > 0" class="ml-auto d-flex flex-row">
<div *ngIf="formGroup.get('id').value" class="col-auto d-flex align-items-center">
<div *ngIf="formGroup.get('id').value && canExport" class="col-auto d-flex align-items-center">
<button [disabled]="isDirty()" [matTooltipDisabled]="!isDirty()" mat-button class="rounded-btn primary-inverted" type="button" [matMenuTriggerFor]="exportMenu" (click)="$event.stopPropagation();" [matTooltip]="'PLAN-EDITOR.ACTIONS.EXPORT.CAN-NOT-EXPORT' | translate">
{{ 'PLAN-EDITOR.ACTIONS.EXPORT.EXPORT' | translate }}
<mat-icon [disabled]="isDirty()" style="width: 14px;" iconPositionEnd>expand_more</mat-icon>

View File

@ -62,6 +62,7 @@ import { FormAnnotationService } from '@app/ui/annotations/annotation-dialog-com
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';
import { PlanStatusAvailableActionType } from '@app/core/common/enum/plan-status-available-action-type';
@Component({
selector: 'app-plan-editor',
@ -143,6 +144,10 @@ export class PlanEditorComponent extends BaseEditor<PlanEditorModel, Plan> imple
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 get canExport(): boolean {
return this.item?.status?.definition?.availableActions?.filter(x => x === PlanStatusAvailableActionType.Export).length > 0 && (this.hasPermission(this.authService.permissionEnum.ExportPlan) || this.item?.authorizationFlags?.some(x => x === AppPermission.ExportPlan));
}
protected canEditSection(id: Guid): boolean {
return this.canEdit && (this.hasPermission(this.authService.permissionEnum.EditDescription) || this.item?.authorizationFlags?.some(x => x === AppPermission.EditDescription) || (
this.permissionPerSection && this.permissionPerSection[id.toString()] && this.permissionPerSection[id.toString()].some(x => x === AppPermission.EditDescription)

View File

@ -16,7 +16,7 @@ import { takeUntil, tap } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof';
import { EntityDoi } from '@app/core/model/entity-doi/entity-doi';
import { DescriptionStatus } from '@app/core/model/description-status/description-status';
import { PlanStatus } from '@app/core/model/plan-status/plan-status';
import { PlanStatus, PlanStatusDefinition } from '@app/core/model/plan-status/plan-status';
@Injectable()
export class PlanEditorEntityResolver extends BaseEditorResolver {
@ -30,12 +30,11 @@ export class PlanEditorEntityResolver extends BaseEditorResolver {
...BaseEditorResolver.lookupFields(),
nameof<Plan>(x => x.id),
nameof<Plan>(x => x.label),
// TODO status remove later
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.status), nameof<PlanStatus>(x => x.definition), nameof<PlanStatusDefinition>(x => x.availableActions)].join('.'),
nameof<Plan>(x => x.versionStatus),
nameof<Plan>(x => x.groupId),
@ -52,6 +51,7 @@ export class PlanEditorEntityResolver extends BaseEditorResolver {
[nameof<Plan>(x => x.authorizationFlags), AppPermission.EditPlan].join('.'),
[nameof<Plan>(x => x.authorizationFlags), AppPermission.DeletePlan].join('.'),
[nameof<Plan>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
[nameof<Plan>(x => x.authorizationFlags), AppPermission.ExportPlan].join('.'),
[nameof<Plan>(x => x.properties), nameof<PlanProperties>(x => x.planBlueprintValues), nameof<PlanBlueprintValue>(x => x.fieldId)].join('.'),
[nameof<Plan>(x => x.properties), nameof<PlanProperties>(x => x.planBlueprintValues), nameof<PlanBlueprintValue>(x => x.fieldValue)].join('.'),