From bc1894586b9973356730f8842b354d80ef652a8b Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Wed, 4 Oct 2023 09:43:16 +0300 Subject: [PATCH] 1) update dmp blueprint listing table view, 2) create clone functionality for dmp blueprints, 3) section description is not required in editor, 4) in the deletion of a dmp blueprint check if any dmps are accosiated with it --- .../criteria/DataManagementPlanCriteria.java | 9 ++ .../eudat/data/dao/entities/DMPDaoImpl.java | 2 + ...taManagementPlanBlueprintTableRequest.java | 2 + .../controllers/DMPProfileController.java | 24 ++++- .../DmpBlueprintUsedException.java | 18 ++++ .../DataManagementProfileManager.java | 18 ++++ .../core/services/dmp/dmp-profile.service.ts | 8 ++ .../admin/dmp-profile/dmp-profile.routing.ts | 1 + .../editor/dmp-blueprint-editor.model.ts | 2 +- .../editor/dmp-profile-editor.component.html | 8 +- .../editor/dmp-profile-editor.component.ts | 46 ++++++++-- .../dmp-profile-criteria.component.html | 30 ++++-- .../dmp-profile-criteria.component.scss | 16 ++-- .../dmp-profile-criteria.component.ts | 17 +--- .../dmp-profile-listing.component.html | 45 +++++++-- .../listing/dmp-profile-listing.component.ts | 91 +++++++++++++++++-- dmp-frontend/src/assets/i18n/en.json | 19 ++++ 17 files changed, 301 insertions(+), 55 deletions(-) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/exceptions/dmpblueprint/DmpBlueprintUsedException.java diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DataManagementPlanCriteria.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DataManagementPlanCriteria.java index 6b8de9a48..4dab4e2f0 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DataManagementPlanCriteria.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/criteria/DataManagementPlanCriteria.java @@ -1,6 +1,7 @@ package eu.eudat.data.dao.criteria; import eu.eudat.data.entities.DMP; +import eu.eudat.data.entities.DMPProfile; import eu.eudat.data.entities.Grant; import java.util.Date; @@ -10,6 +11,7 @@ import java.util.UUID; public class DataManagementPlanCriteria extends Criteria { private Date periodStart; private Date periodEnd; + private DMPProfile profile; private List grants; private boolean allVersions; private List groupIds; @@ -37,6 +39,13 @@ public class DataManagementPlanCriteria extends Criteria { this.periodEnd = periodEnd; } + public DMPProfile getProfile() { + return profile; + } + public void setProfile(DMPProfile profile) { + this.profile = profile; + } + public List getGrants() { return grants; } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java index ac8ce47d7..e33fc5a48 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/DMPDaoImpl.java @@ -42,6 +42,8 @@ public class DMPDaoImpl extends DatabaseAccess implements DMPDao { query.where((builder, root) -> builder.lessThan(root.get("created"), criteria.getPeriodEnd())); if (criteria.getPeriodStart() != null) query.where((builder, root) -> builder.greaterThan(root.get("created"), criteria.getPeriodStart())); + if (criteria.getProfile() != null) + query.where((builder, root) -> builder.equal(root.get("profile"), criteria.getProfile())); if (criteria.getGrants() != null && !criteria.getGrants().isEmpty()) query.where(((builder, root) -> root.get("grant").in(criteria.getGrants()))); if (!criteria.getAllVersions()) diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/query/items/dmpblueprint/DataManagementPlanBlueprintTableRequest.java b/dmp-backend/data/src/main/java/eu/eudat/data/query/items/dmpblueprint/DataManagementPlanBlueprintTableRequest.java index b1b83e5d6..388a024a7 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/query/items/dmpblueprint/DataManagementPlanBlueprintTableRequest.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/query/items/dmpblueprint/DataManagementPlanBlueprintTableRequest.java @@ -15,6 +15,8 @@ public class DataManagementPlanBlueprintTableRequest extends TableQuery query = this.getQuery(); if (this.getCriteria().getLike() != null && !this.getCriteria().getLike().isEmpty()) query.where((builder, root) -> builder.like(root.get("label"), "%" + this.getCriteria().getLike() + "%")); + if (this.getCriteria().getStatus() != null) + query.where((builder, root) -> builder.equal(root.get("status"), this.getCriteria().getStatus())); return query; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPProfileController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPProfileController.java index 871c87bc2..d7f6fc7ea 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPProfileController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPProfileController.java @@ -5,6 +5,7 @@ import eu.eudat.data.entities.DMPProfile; import eu.eudat.data.entities.DescriptionTemplate; import eu.eudat.data.query.items.dmpblueprint.DataManagementPlanBlueprintTableRequest; import eu.eudat.data.query.items.table.dmpprofile.DataManagementPlanProfileTableRequest; +import eu.eudat.exceptions.dmpblueprint.DmpBlueprintUsedException; import eu.eudat.logic.managers.DataManagementProfileManager; import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.services.ApiContext; @@ -29,6 +30,7 @@ import java.io.IOException; import java.util.List; import static eu.eudat.types.Authorities.ADMIN; +import static eu.eudat.types.Authorities.DATASET_PROFILE_MANAGER; /** * Created by ikalyvas on 3/21/2018. @@ -71,7 +73,7 @@ public class DMPProfileController extends BaseController { @RequestMapping(method = RequestMethod.GET, value = {"/getSingleBlueprint/{id}"}, produces = "application/json") public @ResponseBody - ResponseEntity> getSingleBlueprint(@PathVariable String id, Principal principal) throws IllegalAccessException, InstantiationException { + ResponseEntity> getSingleBlueprint(@PathVariable String id, Principal principal) { DataManagementPlanBlueprintListingModel dataManagementPlanBlueprintListingModel = this.dataManagementProfileManager.getSingleBlueprint(id, principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlanBlueprintListingModel)); } @@ -90,6 +92,26 @@ public class DMPProfileController extends BaseController { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); } + @Transactional + @RequestMapping(method = RequestMethod.POST, value = {"/clone/{id}"}, consumes = "application/json", produces = "application/json") + public ResponseEntity> clone(@PathVariable String id, @ClaimedAuthorities(claims = {ADMIN}) Principal principal) { + DataManagementPlanBlueprintListingModel dmpBlueprint = this.dataManagementProfileManager.getSingleBlueprint(id, principal); + dmpBlueprint.setLabel(dmpBlueprint.getLabel() + " new "); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(dmpBlueprint)); + } + + @Transactional + @RequestMapping(method = RequestMethod.DELETE, value = {"{id}"}, consumes = "application/json", produces = "application/json") + public @ResponseBody + ResponseEntity> inactivate(@PathVariable String id, @ClaimedAuthorities(claims = {ADMIN}) Principal principal) { + try { + this.dataManagementProfileManager.inactivate(id); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE)); + } catch (DmpBlueprintUsedException exception) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.UNSUCCESS_DELETE).message(exception.getMessage())); + } + } + @RequestMapping(method = RequestMethod.GET, value = {"/getXml/{id}"}, produces = "application/json") public @ResponseBody ResponseEntity getXml( @RequestHeader("Content-Type") String contentType, @PathVariable String id, Principal principal) throws IOException { diff --git a/dmp-backend/web/src/main/java/eu/eudat/exceptions/dmpblueprint/DmpBlueprintUsedException.java b/dmp-backend/web/src/main/java/eu/eudat/exceptions/dmpblueprint/DmpBlueprintUsedException.java new file mode 100644 index 000000000..3d5e7ec95 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/exceptions/dmpblueprint/DmpBlueprintUsedException.java @@ -0,0 +1,18 @@ +package eu.eudat.exceptions.dmpblueprint; + +public class DmpBlueprintUsedException extends RuntimeException { + public DmpBlueprintUsedException() { + } + + public DmpBlueprintUsedException(String message) { + super(message); + } + + public DmpBlueprintUsedException(String message, Throwable cause) { + super(message, cause); + } + + public DmpBlueprintUsedException(Throwable cause) { + super(cause); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementProfileManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementProfileManager.java index 12764f424..714733da3 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementProfileManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementProfileManager.java @@ -2,11 +2,17 @@ package eu.eudat.logic.managers; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; +import eu.eudat.data.dao.criteria.DataManagementPlanCriteria; import eu.eudat.data.dao.criteria.RequestItem; +import eu.eudat.data.dao.entities.DatasetDao; +import eu.eudat.data.dao.entities.DatasetProfileDao; import eu.eudat.data.entities.DMPProfile; +import eu.eudat.data.entities.DescriptionTemplate; import eu.eudat.data.query.items.dmpblueprint.DataManagementPlanBlueprintTableRequest; import eu.eudat.data.query.items.item.dmpprofile.DataManagementPlanProfileCriteriaRequest; import eu.eudat.data.query.items.table.dmpprofile.DataManagementPlanProfileTableRequest; +import eu.eudat.exceptions.datasetprofile.DatasetProfileWithDatasetsExeption; +import eu.eudat.exceptions.dmpblueprint.DmpBlueprintUsedException; import eu.eudat.logic.services.operations.DatabaseRepository; import eu.eudat.logic.utilities.builders.XmlBuilder; import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; @@ -145,6 +151,18 @@ public class DataManagementProfileManager { apiContext.getOperationsContext().getDatabaseRepository().getDmpProfileDao().createOrUpdate(dmpProfile); } + public void inactivate(String id) { + DMPProfile dmpProfile = databaseRepository.getDmpProfileDao().find(UUID.fromString(id)); + DataManagementPlanCriteria dataManagementPlanCriteria = new DataManagementPlanCriteria(); + dataManagementPlanCriteria.setProfile(dmpProfile); + if (dmpProfile.getStatus() == DMPProfile.Status.SAVED.getValue() || databaseRepository.getDmpDao().getWithCriteria(dataManagementPlanCriteria).count() == 0) { + dmpProfile.setStatus(DMPProfile.Status.DELETED.getValue()); + databaseRepository.getDmpProfileDao().createOrUpdate(dmpProfile); + } else { + throw new DmpBlueprintUsedException("This blueprint can not deleted, because DMPs are associated with it"); + } + } + public ResponseEntity getDocument(DataManagementPlanBlueprintListingModel dmpProfile) throws IOException { FileEnvelope envelope = getXmlDocument(dmpProfile); InputStream resource = new FileInputStream(envelope.getFile()); diff --git a/dmp-frontend/src/app/core/services/dmp/dmp-profile.service.ts b/dmp-frontend/src/app/core/services/dmp/dmp-profile.service.ts index 94b666594..de242c230 100644 --- a/dmp-frontend/src/app/core/services/dmp/dmp-profile.service.ts +++ b/dmp-frontend/src/app/core/services/dmp/dmp-profile.service.ts @@ -67,6 +67,14 @@ export class DmpProfileService { return this.http.post(this.actionUrl + "upload", formData, { params: params }); } + clone(id: string): Observable { + return this.http.post(this.actionUrl + 'clone/' + id, { headers: this.headers }); + } + + delete(id: string): Observable { + return this.http.delete(this.actionUrl + id, { headers: this.headers }); + } + externalAutocomplete(lookUpItem: RequestItem): Observable { return this.httpClient.post(this.actionUrl + 'search/autocomplete', lookUpItem); } diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.routing.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.routing.ts index f5c51ec6b..9014940a1 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.routing.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/dmp-profile.routing.ts @@ -8,6 +8,7 @@ import { AdminAuthGuard } from '@app/core/admin-auth-guard.service'; const routes: Routes = [ { path: '', component: DmpProfileListingComponent, canActivate: [AdminAuthGuard] }, { path: 'new', component: DmpProfileEditorComponent, canActivate: [AdminAuthGuard], data: { title: 'GENERAL.TITLES.DMP-BLUEPRINT-NEW' } }, + { path: 'clone/:cloneid', component: DmpProfileEditorComponent, canActivate: [AdminAuthGuard], data: { title: 'GENERAL.TITLES.DMP-BLUEPRINT-CLONE' } }, { path: ':id', component: DmpProfileEditorComponent, canActivate: [AdminAuthGuard], data: { title: 'GENERAL.TITLES.DMP-BLUEPRINT-EDIT' } }, ]; diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-blueprint-editor.model.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-blueprint-editor.model.ts index c90354afd..bda17b1b1 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-blueprint-editor.model.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-blueprint-editor.model.ts @@ -121,7 +121,7 @@ export class SectionDmpBlueprintEditor { const baseContext: ValidationContext = new ValidationContext(); baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] }); baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); - baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] }); + baseContext.validation.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] }); baseContext.validation.push({ key: 'ordinal', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'ordinal')] }); baseContext.validation.push({ key: 'hasTemplates', validators: [BackendErrorValidator(this.validationErrorModel, 'hasTemplates')] }); baseContext.validation.push({ key: 'descriptionTemplates', validators: [BackendErrorValidator(this.validationErrorModel, 'descriptionTemplates')] }); diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html index f8eb58905..b044c607b 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.html @@ -2,7 +2,11 @@
-

{{'DMP-PROFILE-EDITOR.TITLE.NEW' | translate}}

+

{{'DMP-PROFILE-EDITOR.TITLE.NEW' | translate}}

+

+ {{'DMP-PROFILE-EDITOR.TITLE.NEW-PROFILE-CLONE' | translate}} + {{formGroup.get('label').value}} +

{{formGroup.get('label').value}}

@@ -65,7 +69,7 @@
Section description - + {{'GENERAL.VALIDATION.REQUIRED' | translate}} diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts index 3ad205bb3..df0d27117 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/editor/dmp-profile-editor.component.ts @@ -49,6 +49,7 @@ import { FormValidationErrorsDialogComponent } from '@common/forms/form-validati export class DmpProfileEditorComponent extends BaseComponent implements AfterViewInit { isNew = true; + isClone = false; viewOnly = false; dmpProfileModel: DmpProfileEditorModel; dmpBlueprintModel: DmpBlueprintEditor; @@ -112,6 +113,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie .pipe(takeUntil(this._destroyed)) .subscribe((params: Params) => { this.dmpProfileId = params['id']; + const cloneId = params['cloneid']; if (this.dmpProfileId != null) { this.isNew = false; @@ -132,6 +134,20 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie url: '/dmp-profiles/' + this.dmpProfileId }]); }); + } else if (cloneId != null) { + this.isClone = true; + this.dmpProfileService.clone(cloneId).pipe(map(data => data as DmpBlueprint), takeUntil(this._destroyed)) + .subscribe( + data => { + this.dmpBlueprintModel = new DmpBlueprintEditor().fromModel(data); + this.dmpBlueprintModel.id = null; + this.dmpBlueprintModel.status = DmpProfileStatus.Draft; + this.formGroup = this.dmpBlueprintModel.buildForm(); + this.buildSystemFields(); + this.fillDescriptionTemplatesInMultAutocomplete(); + }, + error => this.onCallbackError(error) + ); } else { this.dmpProfileModel = new DmpProfileEditorModel(); this.dmpBlueprintModel = new DmpBlueprintEditor(); @@ -553,13 +569,29 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie .subscribe( confirmed =>{ if(confirmed){ - this.formGroup.get('status').setValue(DmpProfileStatus.Deleted); - this.dmpProfileService.createBlueprint(this.formGroup.value) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => this.onCallbackSuccess(), - error => this.onCallbackError(error) - ); + if(this.formGroup.get('status').value == DmpProfileStatus.Draft) { + this.formGroup.get('status').setValue(DmpProfileStatus.Deleted); + this.dmpProfileService.createBlueprint(this.formGroup.value) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + else { + this.dmpProfileService.delete(this.dmpProfileId) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => { + if (error.error.statusCode == 674) { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DMP-BLUEPRINT-DELETE'), SnackBarNotificationLevel.Error); + } else { + this.uiNotificationService.snackBarNotification(this.language.instant(error.message), SnackBarNotificationLevel.Error); + } + } + ); + } } } ) diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.html b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.html index 34dd7626d..f1a256ced 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.html +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.html @@ -1,11 +1,23 @@ -
-
-
- - - search - -
+
+
+
+ {{'CRITERIA.USERS.SHOW' | translate}}:
+ + + + {{'BLUEPRINT-STATUS.NONE' | translate}} + {{'BLUEPRINT-STATUS.DRAFT' | translate}} + {{'BLUEPRINT-STATUS.FINALIZED' | translate}} + + + +
+
+ + + search + +
diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.scss b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.scss index 7389ee36f..9b64c055a 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.scss +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.scss @@ -1,13 +1,17 @@ +.mat-form-field{ + display: inline-block !important; +} + +:host ::ng-deep .status-form-field .mat-form-field-wrapper { + background-color: white !important; + padding-bottom: 0 !important; +} :host ::ng-deep .search-form-field .mat-form-field-wrapper { background-color: white !important; padding-bottom: 0 !important; } -:host ::ng-deep .search-container .mat-form-field-appearance-outline .mat-form-field-infix { - padding: 0.3rem 0rem 0.6rem 0rem !important; -} -.dmp-criteria{ - margin-top: 3em; - margin-bottom: 0em; +:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix { + padding: 0.3rem 0rem 0.6rem 0rem !important; } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts index 9e7cc3b8c..e80bea6b3 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/criteria/dmp-profile-criteria.component.ts @@ -1,14 +1,10 @@ import { Component, Input, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; -import { GrantListingModel } from '@app/core/model/grant/grant-listing'; -import { DmpCriteria } from '@app/core/query/dmp/dmp-criteria'; -import { DmpProfileCriteria } from '@app/core/query/dmp/dmp-profile-criteria'; +import { DmpBlueprintCriteria } from '@app/core/query/dmp/dmp-blueprint-criteria'; import { DmpProfileService } from '@app/core/services/dmp/dmp-profile.service'; -import { DialodConfirmationUploadDmpProfiles } from '@app/ui/admin/dmp-profile/listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; import { BaseCriteriaComponent } from '@app/ui/misc/criteria/base-criteria.component'; import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-dmp-profile-criteria-component', @@ -17,11 +13,8 @@ import { takeUntil } from 'rxjs/operators'; }) export class DmpProfileCriteriaComponent extends BaseCriteriaComponent implements OnInit { - @Input() - showGrant: boolean; - public criteria: DmpProfileCriteria = new DmpProfileCriteria(); - filteringGrantsAsync = false; - filteredGrants: GrantListingModel[]; + public criteria: DmpBlueprintCriteria = new DmpBlueprintCriteria(); + constructor( private dmpProfileService: DmpProfileService, private dialog: MatDialog, @@ -32,10 +25,10 @@ export class DmpProfileCriteriaComponent extends BaseCriteriaComponent implement ngOnInit() { super.ngOnInit(); - if (this.criteria == null) { this.criteria = new DmpCriteria(); } + if (this.criteria == null) { this.criteria = new DmpBlueprintCriteria(); } } - setCriteria(criteria: DmpProfileCriteria): void { + setCriteria(criteria: DmpBlueprintCriteria): void { this.criteria = criteria; } diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.html b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.html index 582bb35ce..e138c7d8a 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.html +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.html @@ -19,9 +19,14 @@
- +
+
+ +
+
+
- + @@ -30,6 +35,13 @@ {{row.label}} + + + + {{'DMP-PROFILE-LISTING.COLUMNS.CREATED' | translate}} + {{row.created | date:'short'}} + + @@ -41,14 +53,29 @@ - - - - {{'DMP-PROFILE-LISTING.COLUMNS.CREATED' | translate}} - {{row.created | date:'shortDate'}} - - + + + + + + + + + + + + diff --git a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts index b4189b030..cac8ff4a9 100644 --- a/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts +++ b/dmp-frontend/src/app/ui/admin/dmp-profile/listing/dmp-profile-listing.component.ts @@ -1,6 +1,6 @@ import { DataSource } from '@angular/cdk/table'; -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Component, OnInit, ViewChild } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { MatPaginator, PageEvent } from '@angular/material/paginator'; @@ -21,6 +21,11 @@ import { TranslateService } from '@ngx-translate/core'; import { merge as observableMerge, Observable, of as observableOf } from 'rxjs'; import { map, startWith, switchMap, takeUntil } from 'rxjs/operators'; import { DialodConfirmationUploadDmpProfiles } from './criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; +import { DmpBlueprintCriteria } from '@app/core/query/dmp/dmp-blueprint-criteria'; +import { DmpBlueprintListing } from '@app/core/model/dmp/dmp-blueprint/dmp-blueprint-listing'; +import { DmpProfileStatus } from '@app/core/common/enum/dmp-profile-status'; +import * as FileSaver from 'file-saver'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; @Component({ @@ -35,11 +40,12 @@ export class DmpProfileListingComponent extends BaseComponent implements OnInit @ViewChild(DmpProfileCriteriaComponent, { static: true }) criteria: DmpProfileCriteriaComponent; dataSource: DatasetDataSource | null; - displayedColumns: String[] = ['label', 'status', 'created']; + displayedColumns: String[] = ['label', 'created', 'status', 'actions']; pageEvent: PageEvent; titlePrefix: String; dmpId: String; breadCrumbs: Observable; + dmpBlueprintStatus = DmpProfileStatus; statuses = [ { value: '0', viewValue: 'DMP-PROFILE-LISTING.STATUS.DRAFT' },// active @@ -81,12 +87,81 @@ export class DmpProfileListingComponent extends BaseComponent implements OnInit this.dataSource = new DatasetDataSource(this.dmpProfileService, this._paginator, this.sort, this.criteria); } + clone(id: string) { + this.router.navigate(['dmp-profiles/clone/' + id]); + } + rowClick(rowId: String) { this.router.navigate(['dmp-profiles/' + rowId]); } - getDefaultCriteria(): DmpProfileCriteria { - const defaultCriteria = new DmpProfileCriteria(); + downloadXML(dmpProfileId: string): void { + this.dmpProfileService.downloadXML(dmpProfileId) + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/xml' }); + const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); + FileSaver.saveAs(blob, filename); + }); + } + getFilenameFromContentDispositionHeader(header: string): string { + const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g); + + const matches = header.match(regex); + let filename: string; + for (let i = 0; i < matches.length; i++) { + const match = matches[i]; + if (match.includes('filename="')) { + filename = match.substring(10, match.length - 1); + break; + } else if (match.includes('filename=')) { + filename = match.substring(9); + break; + } + } + return filename; + } + + deleteTemplate(id: string) { + if (id) { + this.dialog.open(ConfirmationDialogComponent,{data:{ + isDeleteConfirmation: true, + confirmButton: this.languageService.instant('DMP-PROFILE-EDITOR.CONFIRM-DELETE-DIALOG.CONFIRM-BUTTON'), + cancelButton: this.languageService.instant("DMP-PROFILE-EDITOR.CONFIRM-DELETE-DIALOG.CANCEL-BUTTON"), + message: this.languageService.instant("DMP-PROFILE-EDITOR.CONFIRM-DELETE-DIALOG.MESSAGE") + }}) + .afterClosed() + .subscribe( + confirmed =>{ + if(confirmed){ + this.dmpProfileService.delete(id) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => { + this.uiNotificationService.snackBarNotification(this.languageService.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DMP-BLUEPRINT-DELETE'), SnackBarNotificationLevel.Success); + this.refresh(); + }, + error => { + this.onCallbackError(error); + if (error.error.statusCode == 674) { + this.uiNotificationService.snackBarNotification(this.languageService.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DMP-BLUEPRINT-DELETE'), SnackBarNotificationLevel.Error); + } else { + this.uiNotificationService.snackBarNotification(this.languageService.instant(error.message), SnackBarNotificationLevel.Error); + } + } + ); + } + } + ) + } + } + + onCallbackError(errorResponse: HttpErrorResponse) { + this.uiNotificationService.snackBarNotification(errorResponse.message, SnackBarNotificationLevel.Warning); + } + + getDefaultCriteria(): DmpBlueprintCriteria { + const defaultCriteria = new DmpBlueprintCriteria(); return defaultCriteria; } @@ -142,7 +217,7 @@ export class DmpProfileListingComponent extends BaseComponent implements OnInit } } -export class DatasetDataSource extends DataSource { +export class DatasetDataSource extends DataSource { totalCount = 0; @@ -156,7 +231,7 @@ export class DatasetDataSource extends DataSource { } - connect(): Observable { + connect(): Observable { const displayDataChanges = [ this._paginator.page //this._sort.matSortChange @@ -168,9 +243,9 @@ export class DatasetDataSource extends DataSource { const startIndex = this._paginator.pageIndex * this._paginator.pageSize; let fields: Array = new Array(); if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; } - const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); + const request = new DataTableRequest(startIndex, this._paginator.pageSize, { fields: fields }); request.criteria = this._criteria.criteria; - return this._service.getPaged(request); + return this._service.getPagedBlueprint(request); }), /*.catch((error: any) => { this._snackBar.openFromComponent(SnackBarNotificationComponent, { diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 18d93532a..27e76d916 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -28,6 +28,8 @@ "UNSUCCESSFUL-LOGIN": "Unsuccessful Login", "SUCCESSFUL-DATASET-PROFILE-DELETE": "Successful Delete", "UNSUCCESSFUL-DATASET-PROFILE-DELETE": "This template can not deleted, because Datasets are associated with it", + "SUCCESSFUL-DMP-BLUEPRINT-DELETE": "Successful Delete", + "UNSUCCESSFUL-DMP-BLUEPRINT-DELETE": "This blueprint can not deleted, because DMPs are associated with it", "SUCCESSFUL-DESCRIPTION-TEMPLATE-TYPE-DELETE": "Successful Delete", "UNSUCCESSFUL-DESCRIPTION-TEMPLATE-TYPE-DELETE": "This type can not deleted, because Descriptions are associated with it", "SUCCESSFUL-DELETE": "Successful Delete", @@ -155,6 +157,7 @@ "GRANT-NEW": "New Grant", "GRANT-EDIT": "View/Edit Grant", "DMP-BLUEPRINT-NEW": "New DMP Blueprint", + "DMP-BLUEPRINT-CLONE": "New Clone of DMP Blueprint", "DMP-BLUEPRINT-EDIT": "Edit DMP Blueprint", "DATASET-PROFILES-NEW": "New Dataset Template", "DATASET-PROFILES-EDIT": "Edit Dataset Template", @@ -999,6 +1002,7 @@ "DMP-PROFILE-EDITOR": { "TITLE": { "NEW": "New DMP Blueprint", + "NEW-PROFILE-CLONE": "New Clone Of ", "EDIT": "Edit" }, "FIELDS": { @@ -1203,6 +1207,11 @@ "PUBLISHED": "Published", "LAST-EDITED": "Last Edited" }, + "ACTIONS": { + "CLONE": "Clone", + "DOWNLOAD-XML":"Download XML", + "DELETE": "Delete" + }, "UPLOAD": { "UPLOAD-XML": "Import", "UPLOAD-XML-FILE-TITLE": "Import Data Management Plan Template", @@ -1277,6 +1286,10 @@ "SELECT-DATASET-TEMPLATES": "Select Dataset Templates", "RELATED-DATASET-TEMPLATES": "Related Dataset Templates" }, + "BLUEPRINT": { + "LIKE": "Search", + "STATUS": "Status" + }, "USERS": { "LABEL": "Search", "ROLE": "Role", @@ -1949,5 +1962,11 @@ "DRAFT": "Draft", "FINALIZED": "Finalized", "DELETED": "Deleted" + }, + "BLUEPRINT-STATUS": { + "NONE": "None", + "DRAFT": "Draft", + "FINALIZED": "Finalized", + "DELETED": "Deleted" } }