diff --git a/dmp-frontend/src/app/core/services/dmp/dmp.service.ts b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts index 662e40359..a3eb91475 100644 --- a/dmp-frontend/src/app/core/services/dmp/dmp.service.ts +++ b/dmp-frontend/src/app/core/services/dmp/dmp.service.ts @@ -82,8 +82,8 @@ export class DmpService { return this.http.post(this.actionUrl + 'datasetprofiles/get', dataSetProfileRequest, { headers: this.headers }); } - newVersion(dataManagementPlanModel: DmpModel, id: String): Observable { - return this.http.post(this.actionUrl + 'new/' + id, dataManagementPlanModel, { headers: this.headers }); + newVersion(dataManagementPlanModel: DmpModel, id: String): Observable { + return this.http.post(this.actionUrl + 'new/' + id, dataManagementPlanModel, { headers: this.headers }); } clone(dataManagementPlanModel: DmpModel, id: String): Observable { diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.html b/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.html index 17890c5eb..380ac2101 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.html +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.html @@ -60,7 +60,7 @@ open_in_new{{'DMP-LISTING.ACTIONS.EXPORT' | translate}} add{{'DMP-LISTING.ACTIONS.ADD-DATASET-SHORT' | translate}} group_add{{'DMP-LISTING.ACTIONS.INVITE-SHORT' | translate}} - filter_none{{'DMP-LISTING.ACTIONS.CLONE' | translate}} + filter_none{{'DMP-LISTING.ACTIONS.CLONE' | translate}} more_horiz @@ -83,7 +83,7 @@ - - +
+ + diff --git a/dmp-frontend/src/app/ui/dmp/clone/clone-dialog/clone-dialog.component.scss b/dmp-frontend/src/app/ui/dmp/clone/clone-dialog/clone-dialog.component.scss new file mode 100644 index 000000000..6347977a7 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/clone/clone-dialog/clone-dialog.component.scss @@ -0,0 +1,21 @@ +.clone-dialog { + .heading { + text-align: left; + font-weight: 700; + font-size: 18px; + letter-spacing: 0px; + color: #212121; + opacity: 0.81; + margin-bottom: 0.625rem; + } + + .heading-1 { + text-align: center; + font-weight: 700; + font-size: 20px; + letter-spacing: 0px; + color: #212121; + opacity: 0.81; + margin-bottom: 0.625rem; + } +} diff --git a/dmp-frontend/src/app/ui/dmp/clone/clone-dialog/clone-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/clone/clone-dialog/clone-dialog.component.ts new file mode 100644 index 000000000..a82be1604 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/clone/clone-dialog/clone-dialog.component.ts @@ -0,0 +1,80 @@ +import { Component, Inject } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { map, takeUntil } from 'rxjs/operators'; +import { DmpModel } from '@app/core/model/dmp/dmp'; +import { FormBuilder, FormArray, FormControl } from '@angular/forms'; +import { DatasetDescriptionFormEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model'; +import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration'; +import { Observable } from 'rxjs'; +import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; +import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; +import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; +import { AvailableProfilesComponent } from '../../editor/available-profiles/available-profiles.component'; + +@Component({ + selector: 'app-clone-dialog', + templateUrl: './clone-dialog.component.html', + styleUrls: ['./clone-dialog.component.scss'] +}) +export class CloneDialogComponent { + + agreePrivacyPolicyNames = false; + initialItems = []; + profilesAutoCompleteConfiguration: MultipleAutoCompleteConfiguration; + + constructor( + public dialogRef: MatDialogRef, + private dmpService: DmpService, + @Inject(MAT_DIALOG_DATA) public data: any + ) { + this.selectionChanged(this.initialItems) + + this.profilesAutoCompleteConfiguration = { + filterFn: this.filterProfiles.bind(this), + initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'], + subtitleFn: (item) => item['description'] + }; + + if (this.data.isNewVersion) { + this.data.formGroup.get('label').disable(); + } + } + + close() { + this.dialogRef.close(false); + } + + cancel() { + this.dialogRef.close(false); + } + + confirm() { + this.dialogRef.close(true); + } + + selectionChanged(selectedItems) { + this.data.formGroup.removeControl('datasets'); + this.data.formGroup.addControl('datasets', new FormBuilder().array(new Array())); + if (selectedItems && selectedItems.selectedOptions && selectedItems.selectedOptions.selected.length > 0) { + selectedItems.selectedOptions.selected.forEach(element => { + (this.data.formGroup.get('datasets')).push(new FormBuilder().group({ id: element.value })); + }); + } + } + + hasDatasets() { + return this.data.datasets.length > 0; + } + + filterProfiles(value: string): Observable { + const request = new DataTableRequest(null, null, { fields: ['+label'] }); + const criteria = new DatasetProfileCriteria(); + criteria.like = value; + request.criteria = criteria; + return this.dmpService.searchDMPProfiles(request); + } + +} diff --git a/dmp-frontend/src/app/ui/dmp/clone/clone-dialog/clone-dialog.module.ts b/dmp-frontend/src/app/ui/dmp/clone/clone-dialog/clone-dialog.module.ts new file mode 100644 index 000000000..f841d8434 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/clone/clone-dialog/clone-dialog.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { CloneDialogComponent } from './clone-dialog.component'; +import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; + +@NgModule({ + imports: [CommonUiModule, FormsModule, ReactiveFormsModule, AutoCompleteModule], + declarations: [CloneDialogComponent], + exports: [CloneDialogComponent], + entryComponents: [CloneDialogComponent] +}) +export class CloneDialogModule { + constructor() { } +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts index 789fa7394..48b9c34d6 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts @@ -601,6 +601,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC // openCloneDialog() { // const dialogRef = this.dialog.open(CloneDialogComponent, { // maxWidth: '700px', + // maxHeight: '80vh', // data: { // formGroup: this.formGroup, // datasets: this.formGroup.get('datasets').value, diff --git a/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html b/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html index fd1f30fb3..a6e33ce0a 100644 --- a/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html +++ b/dmp-frontend/src/app/ui/dmp/listing/listing-item/dmp-listing-item.component.html @@ -31,7 +31,7 @@ open_in_new{{'DMP-LISTING.ACTIONS.EXPORT' | translate}} add{{'DMP-LISTING.ACTIONS.ADD-DATASET-SHORT' | translate}} group_add{{'DMP-LISTING.ACTIONS.INVITE-SHORT' | translate}} - filter_none{{'DMP-LISTING.ACTIONS.CLONE' | translate}} + filter_none{{'DMP-LISTING.ACTIONS.CLONE' | translate}} more_horiz @@ -54,7 +54,7 @@
- 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 4eab87430..11dbdb653 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 @@ -174,7 +174,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { window.open(url.toString(), '_blank'); } - cloneClicked(dmp: DmpOverviewModel) { + cloneOrNewVersionClicked(dmp: DmpOverviewModel, isNewVersion: boolean) { this.dmpService.getSingle(this.dmp.id).pipe(map(data => data as DmpModel)) .pipe(takeUntil(this._destroyed)) .subscribe(data => { @@ -186,41 +186,53 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { this.dmpModel.fromModel(data); this.dmpModel.status = DmpStatus.Draft; this.formGroup = this.dmpModel.buildForm(); - this.formGroup.get('label').setValue(this.dmp.label + " New"); - - this.openCloneDialog(); + if (!isNewVersion) { + this.formGroup.get('label').setValue(this.dmp.label + " New"); + } + this.openCloneDialog(isNewVersion); }); } - openCloneDialog() { + openCloneDialog(isNewVersion: boolean) { const dialogRef = this.dialog.open(CloneDialogComponent, { - maxWidth: '700px', + maxWidth: '900px', + maxHeight: '80vh', data: { formGroup: this.formGroup, datasets: this.dmp.datasets, - confirmButton: this.language.instant('DMP-EDITOR.CLONE-DIALOG.CLONE'), + isNewVersion: isNewVersion, + confirmButton: this.language.instant('DMP-EDITOR.CLONE-DIALOG.SAVE'), cancelButton: this.language.instant('DMP-EDITOR.CLONE-DIALOG.CANCEL'), } }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { if (result) { - this.dmpService.clone(this.formGroup.getRawValue(), this.dmp.id) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => this.onCallbackSuccess(complete), - error => this.onCallbackError(error) - ); + if (!isNewVersion) { + this.dmpService.clone(this.formGroup.getRawValue(), this.dmp.id) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(complete), + error => this.onCallbackError(error) + ); + } else if (isNewVersion) { + this.dmpService.newVersion(this.formGroup.getRawValue(), this.dmp.id) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(complete), + error => this.onCallbackError(error) + ); + } } }); } - onCallbackSuccess(cloneId: String): void { + onCallbackSuccess(dmpId: String): void { this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); - this.router.navigate(['/plans/edit/', cloneId]); + this.router.navigate(['/plans/edit/', dmpId]); } onCallbackError(error: any) { - this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-CLONE'), SnackBarNotificationLevel.Error); + this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Error); } grantClicked(grantId: String) { @@ -588,10 +600,10 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { }); } - newVersion(id: String, label: String) { - let url = this.router.createUrlTree(['/plans/new_version/', id, { dmpLabel: label }]) - window.open(url.toString(), '_blank') - } + // newVersion(id: String, label: String) { + // let url = this.router.createUrlTree(['/plans/new_version/', id, { dmpLabel: label }]) + // window.open(url.toString(), '_blank') + // } viewVersions(rowId: String, rowLabel: String) { if (this.dmp.isPublic && !this.isUserOwner) { diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index c681c8240..d79fd2dd9 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -763,6 +763,7 @@ "ADD-DATASET": "Adding dataset to ", "EDIT-DATASET": "Editing Dataset", "CLONE-DMP": "Clone", + "NEW-VERSION": "New Version", "CREATE-DATASET": "Creating Dataset Description", "SUBTITLE": "DOI" }, @@ -855,6 +856,7 @@ "CHANGES": "unsaved changes", "CLONE-DIALOG": { "CLONE": "Clone", + "SAVE": "Save", "CANCEL": "Cancel" } },