From ae75fd64b075c0f75f4765d6b31233322b63f5d6 Mon Sep 17 00:00:00 2001 From: Sofia Papacharalampous Date: Wed, 19 Jun 2024 13:04:51 +0300 Subject: [PATCH] fixed tenant-permissions on dmp and description editor --- ...ption-template-preview-dialog.component.ts | 4 +- .../editor/description-editor.component.html | 6 +- .../editor/description-editor.component.ts | 63 +++++------- .../editor/description-editor.routing.ts | 17 ++-- .../prefill-description.component.ts | 4 +- .../description-editor-entity.resolver.ts} | 20 ++-- ...description-editor-permissions.resolver.ts | 99 +++++++++++++++++++ .../dmp-clone-dialog.component.ts | 4 +- .../dmp-editor.component.ts | 19 ++-- .../dmp-editor.routing.ts | 9 +- .../dmp-editor-enitity.resolver.ts} | 6 +- .../dmp-editor-permissions.resolver.ts | 44 +++++++++ .../dmp-new-version-dialog.component.ts | 4 +- .../ui/dmp/overview/dmp-overview.component.ts | 9 +- 14 files changed, 219 insertions(+), 89 deletions(-) rename dmp-frontend/src/app/ui/description/editor/{description-editor.resolver.ts => resolvers/description-editor-entity.resolver.ts} (95%) create mode 100644 dmp-frontend/src/app/ui/description/editor/resolvers/description-editor-permissions.resolver.ts rename dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/{dmp-editor.resolver.ts => resolvers/dmp-editor-enitity.resolver.ts} (98%) create mode 100644 dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/resolvers/dmp-editor-permissions.resolver.ts diff --git a/dmp-frontend/src/app/ui/admin/description-template/description-template-preview/description-template-preview-dialog.component.ts b/dmp-frontend/src/app/ui/admin/description-template/description-template-preview/description-template-preview-dialog.component.ts index 23f1363d8..2aca72031 100644 --- a/dmp-frontend/src/app/ui/admin/description-template/description-template-preview/description-template-preview-dialog.component.ts +++ b/dmp-frontend/src/app/ui/admin/description-template/description-template-preview/description-template-preview-dialog.component.ts @@ -8,7 +8,7 @@ import { LoggingService } from '@app/core/services/logging/logging-service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { ProgressIndicationService } from '@app/core/services/progress-indication/progress-indication-service'; import { DescriptionEditorModel } from '@app/ui/description/editor/description-editor.model'; -import { DescriptionEditorResolver } from '@app/ui/description/editor/description-editor.resolver'; +import { DescriptionEditorEntityResolver } from '@app/ui/description/editor/resolvers/description-editor-entity.resolver'; import { DescriptionFormService } from '@app/ui/description/editor/description-form/components/services/description-form.service'; import { VisibilityRulesService } from '@app/ui/description/editor/description-form/visibility-rules/visibility-rules.service'; import { BaseComponent } from '@common/base/base.component'; @@ -52,7 +52,7 @@ export class DescriptionTemplatePreviewDialogComponent extends BaseComponent imp if (this.data && this.data.descriptionTemplateId) { - this.descriptionTemplateService.getSingle(this.data.descriptionTemplateId, DescriptionEditorResolver.descriptionTemplateLookupFields()) + this.descriptionTemplateService.getSingle(this.data.descriptionTemplateId, DescriptionEditorEntityResolver.descriptionTemplateLookupFields()) .pipe(takeUntil(this._destroyed)) .subscribe(item => { this.descriptionTemplate = item; diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.component.html b/dmp-frontend/src/app/ui/description/editor/description-editor.component.html index cb11d87fd..9718789c7 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.component.html +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.component.html @@ -42,7 +42,7 @@ - +
- - +
diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts b/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts index b97ba1165..f501902b1 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.component.ts @@ -10,7 +10,7 @@ import { IsActive } from '@app/core/common/enum/is-active.enum'; import { LockTargetType } from '@app/core/common/enum/lock-target-type'; import { AppPermission } from '@app/core/common/enum/permission.enum'; import { DescriptionTemplate, DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplatePage, DescriptionTemplateSection } from '@app/core/model/description-template/description-template'; -import { Description, DescriptionPersist, DescriptionSectionPermissionResolver, DescriptionStatusPersist } from '@app/core/model/description/description'; +import { Description, DescriptionPersist, DescriptionStatusPersist } from '@app/core/model/description/description'; import { DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint'; import { DmpDescriptionTemplate } from '@app/core/model/dmp/dmp'; import { AuthService } from '@app/core/services/auth/auth.service'; @@ -21,10 +21,7 @@ import { FileTransformerService } from '@app/core/services/file-transformer/file import { LockService } from '@app/core/services/lock/lock.service'; import { LoggingService } from '@app/core/services/logging/logging-service'; import { AnalyticsService } from '@app/core/services/matomo/analytics-service'; -import { - SnackBarNotificationLevel, - UiNotificationService -} from '@app/core/services/notification/ui-notification-service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; import { QueryParamsService } from '@app/core/services/utilities/query-params.service'; import { VisibilityRulesService } from '@app/ui/description/editor/description-form/visibility-rules/visibility-rules.service'; @@ -39,7 +36,7 @@ import { TranslateService } from '@ngx-translate/core'; import { map, takeUntil } from 'rxjs/operators'; import { nameof } from 'ts-simple-nameof'; import { DescriptionEditorModel, DescriptionFieldIndicator, DescriptionPropertyDefinitionEditorModel } from './description-editor.model'; -import { DescriptionEditorResolver } from './description-editor.resolver'; +import { DescriptionEditorEntityResolver } from './resolvers/description-editor-entity.resolver'; import { DescriptionEditorService } from './description-editor.service'; import { PrefillDescriptionDialogComponent } from './prefill-description/prefill-description.component'; import { ToCEntry } from './table-of-contents/models/toc-entry'; @@ -78,6 +75,7 @@ export class DescriptionEditorComponent extends BaseEditor = new Map(); private initialTemplateId: string = Guid.EMPTY; + private permissionPerSection: Map; constructor( // BaseFormEditor injected dependencies @@ -119,6 +117,10 @@ export class DescriptionEditorComponent extends BaseEditor ?? new Map(); + this.permissionPerSection = this.route.snapshot.data['permissions'] as Map ?? new Map(); + super.ngOnInit(); @@ -177,11 +179,10 @@ export class DescriptionEditorComponent extends BaseEditor void) { - this.descriptionService.getSingle(itemId, DescriptionEditorResolver.lookupFields()) + this.descriptionService.getSingle(itemId, DescriptionEditorEntityResolver.lookupFields()) .pipe(map(data => data as Description), takeUntil(this._destroyed)) .subscribe( data => successFunction(data), @@ -205,6 +206,7 @@ export class DescriptionEditorComponent extends BaseEditor x === AppPermission.EditDescription); + this.canReview = this.permissionPerSection && this.permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()] && this.permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()].some(x => x === AppPermission.ReviewDescription); + this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.canEdit, this.visibilityRulesService); + if (this.item.descriptionTemplate?.definition) this.visibilityRulesService.setContext(this.item.descriptionTemplate.definition, this.formGroup.get('properties')); + if (this.item.descriptionTemplate?.definition) this.pageToFieldSetMap = this.mapPageToFieldSet(this.item.descriptionTemplate);; + + // this.selectedSystemFields = this.selectedSystemFieldDisabled(); + this.descriptionEditorService.setValidationErrorModel(this.editorModel.validationErrorModel); + if (this.editorModel.status == DescriptionStatus.Finalized || this.isDeleted || !this.canEdit) { + this.viewOnly = true; + this.isFinalized = true; + this.formGroup.disable(); + } else { + this.viewOnly = false; } - this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel) - .pipe(takeUntil(this._destroyed)).subscribe( - permissionPerSection => { - this.canEdit = permissionPerSection && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()] && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()].some(x => x === AppPermission.EditDescription); - this.canReview = permissionPerSection && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()] && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()].some(x => x === AppPermission.ReviewDescription); - this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.canEdit, this.visibilityRulesService); - if (this.item.descriptionTemplate?.definition) this.visibilityRulesService.setContext(this.item.descriptionTemplate.definition, this.formGroup.get('properties')); - if (this.item.descriptionTemplate?.definition) this.pageToFieldSetMap = this.mapPageToFieldSet(this.item.descriptionTemplate);; - // this.selectedSystemFields = this.selectedSystemFieldDisabled(); - this.descriptionEditorService.setValidationErrorModel(this.editorModel.validationErrorModel); - if (this.editorModel.status == DescriptionStatus.Finalized || this.isDeleted || !this.canEdit) { - this.viewOnly = true; - this.isFinalized = true; - this.formGroup.disable(); - } else { - this.viewOnly = false; - } - - this.registerFormListeners(); - }, - error => this.onCallbackError(error) - ); + this.registerFormListeners(); } calculateMultiplicityRejectedDmpDescriptionTemplates(section: DmpBlueprintDefinitionSection, descriptions: Description[]): DmpDescriptionTemplate[] { @@ -624,7 +615,7 @@ export class DescriptionEditorComponent extends BaseEditor { this.initialTemplateId = descriptionTemplateId.toString(); @@ -752,7 +743,7 @@ export class DescriptionEditorComponent extends BaseEditor { this.isFinalized = false; this.refreshData(); diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.routing.ts b/dmp-frontend/src/app/ui/description/editor/description-editor.routing.ts index 7df1ddffc..e4d9acc30 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.routing.ts +++ b/dmp-frontend/src/app/ui/description/editor/description-editor.routing.ts @@ -4,7 +4,8 @@ import { AuthGuard } from '@app/core/auth-guard.service'; import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service'; import { PendingChangesGuard } from '@common/forms/pending-form-changes/pending-form-changes-guard.service'; import { DescriptionEditorComponent } from './description-editor.component'; -import { DescriptionEditorResolver } from './description-editor.resolver'; +import { DescriptionEditorEntityResolver } from './resolvers/description-editor-entity.resolver'; +import { DescriptionEditorPermissionsResolver } from './resolvers/description-editor-permissions.resolver'; const routes: Routes = [ { @@ -13,7 +14,8 @@ const routes: Routes = [ component: DescriptionEditorComponent, canDeactivate: [PendingChangesGuard], resolve: { - 'entity': DescriptionEditorResolver + 'entity': DescriptionEditorEntityResolver, + 'permissions': DescriptionEditorPermissionsResolver, }, data: { breadcrumbs: true, @@ -28,7 +30,8 @@ const routes: Routes = [ component: DescriptionEditorComponent, canDeactivate: [PendingChangesGuard], resolve: { - 'entity': DescriptionEditorResolver + 'entity': DescriptionEditorEntityResolver, + 'permissions': DescriptionEditorPermissionsResolver, }, data: { breadcrumbs: true, @@ -44,7 +47,8 @@ const routes: Routes = [ component: DescriptionEditorComponent, canDeactivate: [PendingChangesGuard], resolve: { - 'entity': DescriptionEditorResolver + 'entity': DescriptionEditorEntityResolver, + 'permissions': DescriptionEditorPermissionsResolver, }, data: { breadcrumbs: true, @@ -59,7 +63,8 @@ const routes: Routes = [ component: DescriptionEditorComponent, canDeactivate: [PendingChangesGuard], resolve: { - 'entity': DescriptionEditorResolver + 'entity': DescriptionEditorEntityResolver, + 'permissions': DescriptionEditorPermissionsResolver, }, data: { breadcrumbs: true, @@ -76,6 +81,6 @@ const routes: Routes = [ @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], - providers: [DescriptionEditorResolver] + providers: [DescriptionEditorEntityResolver, DescriptionEditorPermissionsResolver] }) export class DescriptionEditorRoutingModule { } diff --git a/dmp-frontend/src/app/ui/description/editor/prefill-description/prefill-description.component.ts b/dmp-frontend/src/app/ui/description/editor/prefill-description/prefill-description.component.ts index 262ff4b8b..34770f217 100644 --- a/dmp-frontend/src/app/ui/description/editor/prefill-description/prefill-description.component.ts +++ b/dmp-frontend/src/app/ui/description/editor/prefill-description/prefill-description.component.ts @@ -13,7 +13,7 @@ import { FormService } from "@common/forms/form-service"; import { Guid } from "@common/types/guid"; import { Observable } from "rxjs"; import { takeUntil } from "rxjs/operators"; -import { DescriptionEditorResolver } from "../description-editor.resolver"; +import { DescriptionEditorEntityResolver } from "../resolvers/description-editor-entity.resolver"; import { IsActive } from "@app/core/common/enum/is-active.enum"; import { DescriptionPrefillingRequestEditorModel } from "./prefill-description-editor.model"; import { HttpErrorHandlingService } from "@common/modules/errors/error-handling/http-error-handling.service"; @@ -89,7 +89,7 @@ export class PrefillDescriptionDialogComponent extends BaseComponent implements next() { const formData = this.formService.getValue(this.prefillForm.value) as DescriptionPrefillingRequest; - this.prefillingSourceService.generate(formData, DescriptionEditorResolver.descriptionTemplateLookupFieldsForDescrption()) + this.prefillingSourceService.generate(formData, DescriptionEditorEntityResolver.descriptionTemplateLookupFieldsForDescrption()) .pipe(takeUntil(this._destroyed)).subscribe(description => { if (description) { this.closeDialog(description); diff --git a/dmp-frontend/src/app/ui/description/editor/description-editor.resolver.ts b/dmp-frontend/src/app/ui/description/editor/resolvers/description-editor-entity.resolver.ts similarity index 95% rename from dmp-frontend/src/app/ui/description/editor/description-editor.resolver.ts rename to dmp-frontend/src/app/ui/description/editor/resolvers/description-editor-entity.resolver.ts index 1c8049c43..d5dffa114 100644 --- a/dmp-frontend/src/app/ui/description/editor/description-editor.resolver.ts +++ b/dmp-frontend/src/app/ui/description/editor/resolvers/description-editor-entity.resolver.ts @@ -20,7 +20,7 @@ import { concatMap, map, takeUntil, tap } from 'rxjs/operators'; import { nameof } from 'ts-simple-nameof'; @Injectable() -export class DescriptionEditorResolver extends BaseEditorResolver { +export class DescriptionEditorEntityResolver extends BaseEditorResolver { constructor( private descriptionService: DescriptionService, @@ -33,16 +33,16 @@ export class DescriptionEditorResolver extends BaseEditorResolver { public static lookupFields(): string[] { return [ - ...DescriptionEditorResolver.descriptionLookupFields(), - ...DescriptionEditorResolver.dmpLookupFields(nameof(x => x.dmp)), - ...DescriptionEditorResolver.descriptionTemplateLookupFieldsForDescrption(), + ...DescriptionEditorEntityResolver.descriptionLookupFields(), + ...DescriptionEditorEntityResolver.dmpLookupFields(nameof(x => x.dmp)), + ...DescriptionEditorEntityResolver.descriptionTemplateLookupFieldsForDescrption(), ] } public static cloneLookupFields(): string[] { return [ - ...DescriptionEditorResolver.descriptionLookupFields(), - ...DescriptionEditorResolver.descriptionTemplateLookupFieldsForDescrption(), + ...DescriptionEditorEntityResolver.descriptionLookupFields(), + ...DescriptionEditorEntityResolver.descriptionTemplateLookupFieldsForDescrption(), ] } @@ -155,7 +155,7 @@ export class DescriptionEditorResolver extends BaseEditorResolver { resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { const fields = [ - ...DescriptionEditorResolver.lookupFields() + ...DescriptionEditorEntityResolver.lookupFields() ]; const id = route.paramMap.get('id'); const dmpId = route.paramMap.get('dmpId'); @@ -165,7 +165,7 @@ export class DescriptionEditorResolver extends BaseEditorResolver { if (id != null && copyDmpId == null && dmpSectionId == null) { return this.descriptionService.getSingle(Guid.parse(id), fields).pipe(tap(d => this.breadcrumbService.addIdResolvedValue(d.id.toString(), d.label))); } else if (dmpId != null && dmpSectionId != null && copyDmpId == null) { - return this.dmpService.getSingle(Guid.parse(dmpId), DescriptionEditorResolver.dmpLookupFields()) + return this.dmpService.getSingle(Guid.parse(dmpId), DescriptionEditorEntityResolver.dmpLookupFields()) .pipe(tap(x => { this.breadcrumbService.addExcludedParam(dmpId, true); this.breadcrumbService.addIdResolvedValue(dmpSectionId, this.language.instant("DESCRIPTION-EDITOR.TITLE-NEW")); @@ -178,8 +178,8 @@ export class DescriptionEditorResolver extends BaseEditorResolver { return description; })); } else if (copyDmpId != null && id != null && dmpSectionId != null) { - return this.dmpService.getSingle(Guid.parse(copyDmpId), DescriptionEditorResolver.dmpLookupFields()).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(x.id?.toString(), x.label)), takeUntil(this._destroyed), concatMap(dmp => { - return this.descriptionService.getSingle(Guid.parse(id), DescriptionEditorResolver.cloneLookupFields()) + return this.dmpService.getSingle(Guid.parse(copyDmpId), DescriptionEditorEntityResolver.dmpLookupFields()).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(x.id?.toString(), x.label)), takeUntil(this._destroyed), concatMap(dmp => { + return this.descriptionService.getSingle(Guid.parse(id), DescriptionEditorEntityResolver.cloneLookupFields()) .pipe(tap(x => { this.breadcrumbService.addExcludedParam(copyDmpId, true) this.breadcrumbService.addExcludedParam(dmpSectionId, true) diff --git a/dmp-frontend/src/app/ui/description/editor/resolvers/description-editor-permissions.resolver.ts b/dmp-frontend/src/app/ui/description/editor/resolvers/description-editor-permissions.resolver.ts new file mode 100644 index 000000000..1835478f9 --- /dev/null +++ b/dmp-frontend/src/app/ui/description/editor/resolvers/description-editor-permissions.resolver.ts @@ -0,0 +1,99 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { DescriptionStatus } from '@app/core/common/enum/description-status'; +import { Description, DescriptionSectionPermissionResolver } from '@app/core/model/description/description'; +import { DescriptionService } from '@app/core/services/description/description.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service'; +import { BaseEditorResolver } from '@common/base/base-editor.resolver'; +import { Guid } from '@common/types/guid'; +import { TranslateService } from '@ngx-translate/core'; +import { concatMap, map, mergeMap, takeUntil, tap } from 'rxjs/operators'; +import { DescriptionEditorEntityResolver } from './description-editor-entity.resolver'; +import { AppPermission } from '@app/core/common/enum/permission.enum'; + +@Injectable() +export class DescriptionEditorPermissionsResolver extends BaseEditorResolver { + + constructor( + private descriptionService: DescriptionService, + private breadcrumbService: BreadcrumbService, + private language: TranslateService, + private dmpService: DmpService + ) { + super(); + } + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + + const fields = [ + ...DescriptionEditorEntityResolver.lookupFields() + ]; + const id = route.paramMap.get('id'); + const dmpId = route.paramMap.get('dmpId'); + const dmpSectionId = route.paramMap.get('dmpSectionId'); + const copyDmpId = route.paramMap.get('copyDmpId'); + // const cloneid = route.paramMap.get('cloneid'); + if (id != null && copyDmpId == null && dmpSectionId == null) { + return this.descriptionService.getSingle(Guid.parse(id), fields).pipe(tap(d => this.breadcrumbService.addIdResolvedValue(d.id.toString(), d.label))) + .pipe(mergeMap( description => { + const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = { + dmpId: description.dmp.id, + sectionIds: [description.dmpDescriptionTemplate.sectionId], + permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription, AppPermission.FinalizeDescription, AppPermission.ReviewDescription] + } + return this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel).pipe(takeUntil(this._destroyed)); + })); + + } else if (dmpId != null && dmpSectionId != null && copyDmpId == null) { + return this.dmpService.getSingle(Guid.parse(dmpId), DescriptionEditorEntityResolver.dmpLookupFields()) + .pipe(tap(x => { + this.breadcrumbService.addExcludedParam(dmpId, true); + this.breadcrumbService.addIdResolvedValue(dmpSectionId, this.language.instant("DESCRIPTION-EDITOR.TITLE-NEW")); + }), takeUntil(this._destroyed), map(dmp => { + const description: Description = {}; + description.dmp = dmp; + description.dmpDescriptionTemplate = { + sectionId: Guid.parse(dmpSectionId) + } + return description; + })) + .pipe(mergeMap( description => { + const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = { + dmpId: description.dmp.id, + sectionIds: [description.dmpDescriptionTemplate.sectionId], + permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription, AppPermission.FinalizeDescription, AppPermission.ReviewDescription] + } + return this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel).pipe(takeUntil(this._destroyed)); + })); + } else if (copyDmpId != null && id != null && dmpSectionId != null) { + return this.dmpService.getSingle(Guid.parse(copyDmpId), DescriptionEditorEntityResolver.dmpLookupFields()).pipe(tap(x => this.breadcrumbService.addIdResolvedValue(x.id?.toString(), x.label)), takeUntil(this._destroyed), concatMap(dmp => { + //TODO + return this.descriptionService.getSingle(Guid.parse(id), DescriptionEditorEntityResolver.cloneLookupFields()) + .pipe(tap(x => { + this.breadcrumbService.addExcludedParam(copyDmpId, true) + this.breadcrumbService.addExcludedParam(dmpSectionId, true) + this.breadcrumbService.addIdResolvedValue(id, x.label) + }), takeUntil(this._destroyed), map(description => { + + description.id = null; + description.hash = null; + description.status = DescriptionStatus.Draft; + description.dmp = dmp; + description.dmpDescriptionTemplate = { + id: dmp.dmpDescriptionTemplates.filter(x => x.sectionId == Guid.parse(dmpSectionId) && x.descriptionTemplateGroupId == description.descriptionTemplate.groupId)[0].id, + sectionId: Guid.parse(dmpSectionId) + } + return description; + })); + })).pipe(mergeMap( description => { + const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = { + dmpId: description.dmp.id, + sectionIds: [description.dmpDescriptionTemplate.sectionId], + permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription, AppPermission.FinalizeDescription, AppPermission.ReviewDescription] + } + return this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel).pipe(takeUntil(this._destroyed)); + })); + } + } +} diff --git a/dmp-frontend/src/app/ui/dmp/clone-dialog/dmp-clone-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/clone-dialog/dmp-clone-dialog.component.ts index c9bfdc61b..1b4dba71a 100644 --- a/dmp-frontend/src/app/ui/dmp/clone-dialog/dmp-clone-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/clone-dialog/dmp-clone-dialog.component.ts @@ -8,7 +8,7 @@ import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; import { DmpCloneDialogEditorModel } from './dmp-clone-dialog.editor.model'; -import { DmpEditorResolver } from '../dmp-editor-blueprint/dmp-editor.resolver'; +import { DmpEditorEntityResolver } from '../dmp-editor-blueprint/resolvers/dmp-editor-enitity.resolver'; import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; import { HttpErrorResponse } from '@angular/common/http'; @@ -72,7 +72,7 @@ export class CloneDmpDialogComponent extends BaseComponent { confirm() { if (!this.formGroup.valid) { return; } const value: CloneDmpPersist = this.formGroup.value; - this.dmpService.clone(value, DmpEditorResolver.lookupFields()).pipe(takeUntil(this._destroyed)).subscribe( + this.dmpService.clone(value, DmpEditorEntityResolver.lookupFields()).pipe(takeUntil(this._destroyed)).subscribe( dmp => this.dialogRef.close(dmp), error => this.onCallbackError(error) ); diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts index 0b19c392b..5bea4a12c 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.component.ts @@ -50,7 +50,7 @@ import { TranslateService } from '@ngx-translate/core'; import { map, takeUntil } from 'rxjs/operators'; import { DmpContactPrefillDialogComponent } from '../dmp-contact-prefill-dialog/dmp-contact-prefill-dialog.component'; import { DmpEditorModel, DmpFieldIndicator } from './dmp-editor.model'; -import { DmpEditorResolver } from './dmp-editor.resolver'; +import { DmpEditorEntityResolver } from './resolvers/dmp-editor-enitity.resolver'; import { DmpEditorService } from './dmp-editor.service'; import { RouterUtilsService } from '@app/core/services/router/router-utils.service'; @@ -183,13 +183,13 @@ export class DmpEditorComponent extends BaseEditor implemen ngOnInit(): void { this.analyticsService.trackPageView(AnalyticsService.DmpEditor); + this.permissionPerSection = this.route.snapshot.data['permissions'] as Map ?? new Map(); super.ngOnInit(); - if (this.isNew === false && this.step === 0) this.nextStep(); } getItem(itemId: Guid, successFunction: (item: Dmp) => void) { - this.dmpService.getSingle(itemId, DmpEditorResolver.lookupFields()) + this.dmpService.getSingle(itemId, DmpEditorEntityResolver.lookupFields()) .pipe(map(data => data as Dmp), takeUntil(this._destroyed)) .subscribe( data => successFunction(data), @@ -231,14 +231,7 @@ export class DmpEditorComponent extends BaseEditor implemen sectionIds: data?.blueprint?.definition?.sections?.map(x => x.id), permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription] } - this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel) - .pipe(takeUntil(this._destroyed)).subscribe( - complete => { - this.permissionPerSection = complete, - this.buildForm(); - }, - error => this.onCallbackError(error) - ); + this.buildForm(); } else { this.buildForm(); } @@ -445,7 +438,7 @@ export class DmpEditorComponent extends BaseEditor implemen // // selectBlueprint() { - this.dmpBlueprintService.getSingle(this.formGroup.get('blueprint').value, DmpEditorResolver.blueprintLookupFields()).pipe(takeUntil(this._destroyed)) + this.dmpBlueprintService.getSingle(this.formGroup.get('blueprint').value, DmpEditorEntityResolver.blueprintLookupFields()).pipe(takeUntil(this._destroyed)) .subscribe(data => { this.selectedBlueprint = data; this.buildFormAfterBlueprintSelection(); @@ -455,7 +448,7 @@ export class DmpEditorComponent extends BaseEditor implemen } selectDefaultBlueprint(): void { - this.dmpBlueprintService.getSingle(this.configurationService.defaultBlueprintId, DmpEditorResolver.blueprintLookupFields()).pipe(takeUntil(this._destroyed)) + this.dmpBlueprintService.getSingle(this.configurationService.defaultBlueprintId, DmpEditorEntityResolver.blueprintLookupFields()).pipe(takeUntil(this._destroyed)) .subscribe(data => { this.selectedBlueprint = data; this.formGroup.get('blueprint').setValue(this.selectedBlueprint.id); diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.routing.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.routing.ts index afaa11e06..a8aeeb29c 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.routing.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.routing.ts @@ -5,9 +5,9 @@ import { AppPermission } from '@app/core/common/enum/permission.enum'; import { PendingChangesGuard } from '@common/forms/pending-form-changes/pending-form-changes-guard.service'; // import { DmpOverviewComponent } from './overview/description-overview.component'; import { AuthGuard } from '@app/core/auth-guard.service'; -import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service'; import { DmpEditorComponent } from './dmp-editor.component'; -import { DmpEditorResolver } from './dmp-editor.resolver'; +import { DmpEditorEntityResolver } from './resolvers/dmp-editor-enitity.resolver'; +import { DmpEditorPermissionsResolver } from './resolvers/dmp-editor-permissions.resolver'; const routes: Routes = [ { @@ -28,7 +28,8 @@ const routes: Routes = [ component: DmpEditorComponent, canDeactivate: [PendingChangesGuard], resolve: { - 'entity': DmpEditorResolver + 'entity': DmpEditorEntityResolver, + 'permissions': DmpEditorPermissionsResolver }, data: { breadcrumb: true, @@ -42,6 +43,6 @@ const routes: Routes = [ @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], - providers: [DmpEditorResolver] + providers: [DmpEditorEntityResolver, DmpEditorPermissionsResolver] }) export class DmpEditorRoutingModule { } diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/resolvers/dmp-editor-enitity.resolver.ts similarity index 98% rename from dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts rename to dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/resolvers/dmp-editor-enitity.resolver.ts index 2a6b803e0..08b716d02 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/dmp-editor.resolver.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/resolvers/dmp-editor-enitity.resolver.ts @@ -16,7 +16,7 @@ import { takeUntil, tap } from 'rxjs/operators'; import { nameof } from 'ts-simple-nameof'; @Injectable() -export class DmpEditorResolver extends BaseEditorResolver { +export class DmpEditorEntityResolver extends BaseEditorResolver { constructor(private descriptionService: DmpService, private breadcrumbService: BreadcrumbService) { super(); @@ -85,7 +85,7 @@ export class DmpEditorResolver extends BaseEditorResolver { [nameof(x => x.dmpDescriptionTemplates), nameof(x => x.isActive)].join('.'), - ...DmpEditorResolver.blueprintLookupFields(nameof(x => x.blueprint)), + ...DmpEditorEntityResolver.blueprintLookupFields(nameof(x => x.blueprint)), ] } @@ -121,7 +121,7 @@ export class DmpEditorResolver extends BaseEditorResolver { resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { const fields = [ - ...DmpEditorResolver.lookupFields() + ...DmpEditorEntityResolver.lookupFields() ]; const id = route.paramMap.get('id'); if (id != null) { diff --git a/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/resolvers/dmp-editor-permissions.resolver.ts b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/resolvers/dmp-editor-permissions.resolver.ts new file mode 100644 index 000000000..6be5acc75 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/dmp-editor-blueprint/resolvers/dmp-editor-permissions.resolver.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { AppPermission } from '@app/core/common/enum/permission.enum'; +import { DescriptionSectionPermissionResolver } from '@app/core/model/description/description'; +import { DescriptionService } from '@app/core/services/description/description.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { BreadcrumbService } from '@app/ui/misc/breadcrumb/breadcrumb.service'; +import { BaseEditorResolver } from '@common/base/base-editor.resolver'; +import { Guid } from '@common/types/guid'; +import { mergeMap, takeUntil, tap } from 'rxjs/operators'; +import { DmpEditorEntityResolver } from './dmp-editor-enitity.resolver'; + +@Injectable() +export class DmpEditorPermissionsResolver extends BaseEditorResolver { + + constructor(private dmpService: DmpService, + private breadcrumbService: BreadcrumbService, + private descriptionService: DescriptionService, + ) { + super(); + } + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + + const fields = [ + ...DmpEditorEntityResolver.lookupFields() + ]; + const id = route.paramMap.get('id'); + if (id != null) { + return this.dmpService + .getSingle(Guid.parse(id), fields) + .pipe(tap(x => this.breadcrumbService.addIdResolvedValue(id, x.label)), takeUntil(this._destroyed)) + .pipe(mergeMap( data => { + let descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = { + dmpId: data.id, + sectionIds: data?.blueprint?.definition?.sections?.map(x => x.id), + permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription] + }; + return this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel).pipe(takeUntil(this._destroyed)); + } + )); + } + } +} diff --git a/dmp-frontend/src/app/ui/dmp/new-version-dialog/dmp-new-version-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/new-version-dialog/dmp-new-version-dialog.component.ts index 72c9f8a6b..cdc225815 100644 --- a/dmp-frontend/src/app/ui/dmp/new-version-dialog/dmp-new-version-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/new-version-dialog/dmp-new-version-dialog.component.ts @@ -9,7 +9,7 @@ import { TranslateService } from '@ngx-translate/core'; import { map, takeUntil } from 'rxjs/operators'; import { DmpNewVersionDialogEditorModel } from './dmp-new-version-dialog.editor.model'; import { DmpBlueprintService } from '@app/core/services/dmp/dmp-blueprint.service'; -import { DmpEditorResolver } from '../dmp-editor-blueprint/dmp-editor.resolver'; +import { DmpEditorEntityResolver } from '../dmp-editor-blueprint/resolvers/dmp-editor-enitity.resolver'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint'; import { DmpBlueprintStatus } from '@app/core/common/enum/dmp-blueprint-status'; @@ -186,7 +186,7 @@ export class NewVersionDmpDialogComponent extends BaseComponent { if (formData.descriptions.length > 0){ formData.descriptions = formData.descriptions.filter(x => x.blueprintSectionId != null) } - this.dmpService.newVersion(formData, DmpEditorResolver.lookupFields()).pipe(takeUntil(this._destroyed)).subscribe( + this.dmpService.newVersion(formData, DmpEditorEntityResolver.lookupFields()).pipe(takeUntil(this._destroyed)).subscribe( dmp => this.dialogRef.close(dmp), error => this.onCallbackError(error) ); diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index eb3bf79ef..9548746f6 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -28,10 +28,7 @@ import { DmpService } from '@app/core/services/dmp/dmp.service'; import { FileTransformerService } from '@app/core/services/file-transformer/file-transformer.service'; import { LockService } from '@app/core/services/lock/lock.service'; import { AnalyticsService } from '@app/core/services/matomo/analytics-service'; -import { - SnackBarNotificationLevel, - UiNotificationService -} from '@app/core/services/notification/ui-notification-service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { ReferenceTypeService } from '@app/core/services/reference-type/reference-type.service'; import { ReferenceService } from '@app/core/services/reference/reference.service'; import { UserService } from '@app/core/services/user/user.service'; @@ -48,7 +45,7 @@ import { map, takeUntil } from 'rxjs/operators'; import { nameof } from 'ts-simple-nameof'; import { CloneDmpDialogComponent } from '../clone-dialog/dmp-clone-dialog.component'; import { DmpDeleteDialogComponent } from '../dmp-delete-dialog/dmp-delete-dialog.component'; -import { DmpEditorResolver } from '../dmp-editor-blueprint/dmp-editor.resolver'; +import { DmpEditorEntityResolver } from '../dmp-editor-blueprint/resolvers/dmp-editor-enitity.resolver'; import { DmpFinalizeDialogComponent, DmpFinalizeDialogOutput } from '../dmp-finalize-dialog/dmp-finalize-dialog.component'; import { DmpInvitationDialogComponent } from '../invitation/dialog/dmp-invitation-dialog.component'; import { NewVersionDmpDialogComponent } from '../new-version-dialog/dmp-new-version-dialog.component'; @@ -491,7 +488,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { if (result) { - this.dmpService.undoFinalize(this.dmp.id, DmpEditorResolver.lookupFields()).pipe(takeUntil(this._destroyed)) + this.dmpService.undoFinalize(this.dmp.id, DmpEditorEntityResolver.lookupFields()).pipe(takeUntil(this._destroyed)) .subscribe(data => { this.reloadPage(); this.onUpdateCallbackSuccess()