diff --git a/dmp-frontend/src/app/core/model/dataset/dataset-overview.ts b/dmp-frontend/src/app/core/model/dataset/dataset-overview.ts index 34bbe936c..3080a1548 100644 --- a/dmp-frontend/src/app/core/model/dataset/dataset-overview.ts +++ b/dmp-frontend/src/app/core/model/dataset/dataset-overview.ts @@ -1,5 +1,6 @@ import { DatasetProfileModel } from "./dataset-profile"; import { GrantOverviewModel } from '../grant/grant-overview'; +import { DmpOverviewModel } from '../dmp/dmp-overview'; export interface DatasetOverviewModel { id: string; @@ -8,7 +9,7 @@ export interface DatasetOverviewModel { datasetTemplate: DatasetProfileModel; users: any[]; - dmp: String; + dmp: DmpOverviewModel; grant: GrantOverviewModel; description: String; public: boolean; diff --git a/dmp-frontend/src/app/core/model/researcher/researcher.ts b/dmp-frontend/src/app/core/model/researcher/researcher.ts index 6c5bf6a98..9d23a8403 100644 --- a/dmp-frontend/src/app/core/model/researcher/researcher.ts +++ b/dmp-frontend/src/app/core/model/researcher/researcher.ts @@ -1,5 +1,5 @@ export interface ResearcherModel { - id: String; + id: string; name: String; reference: String; lastName: String; diff --git a/dmp-frontend/src/app/core/services/dataset/dataset.service.ts b/dmp-frontend/src/app/core/services/dataset/dataset.service.ts index d21df6676..e7306d139 100644 --- a/dmp-frontend/src/app/core/services/dataset/dataset.service.ts +++ b/dmp-frontend/src/app/core/services/dataset/dataset.service.ts @@ -11,7 +11,7 @@ import { BaseHttpService } from '../http/base-http.service'; import { DatasetProfileCriteria } from '../../query/dataset-profile/dataset-profile-criteria'; import { ConfigurationService } from '../configuration/configuration.service'; import { DatasetOverviewModel } from '@app/core/model/dataset/dataset-overview'; -import { HttpHeaders } from '@angular/common/http'; +import { HttpHeaders, HttpResponse, HttpClient } from '@angular/common/http'; import { DatasetModel } from '@app/core/model/dataset/dataset'; @Injectable() @@ -22,7 +22,8 @@ export class DatasetService { constructor( private http: BaseHttpService, - private configurationSevice: ConfigurationService) { + private configurationSevice: ConfigurationService, + private httpClient: HttpClient) { this.actionUrl = configurationSevice.server + 'datasets/'; } @@ -69,4 +70,27 @@ export class DatasetService { delete(id: String): Observable { return this.http.delete(this.actionUrl + 'delete/' + id, { headers: this.headers }); // + 'delete/' } + + publish(id: String): Observable { + return this.http.get(this.actionUrl + 'makepublic/' + id, { headers: this.headers }); + } + + public downloadXML(id: string): Observable> { + let headerXml: HttpHeaders = this.headers.set('Content-Type', 'application/xml') + return this.httpClient.get(this.actionUrl + id, { responseType: 'blob', observe: 'response', headers: headerXml }); //+ "/getXml/" + } + + public downloadDocx(id: string): Observable> { + let headerDoc: HttpHeaders = this.headers.set('Content-Type', 'application/msword') + return this.httpClient.get(this.actionUrl + id, { responseType: 'blob', observe: 'response', headers: headerDoc }); + } + + public downloadPDF(id: string): Observable> { + let headerPdf: HttpHeaders = this.headers.set('Content-Type', 'application/pdf') + return this.httpClient.get(this.actionUrl + 'getPDF/' + id, { responseType: 'blob', observe: 'response', headers: headerPdf }); + } + + public downloadJson(id: string): Observable> { + return this.httpClient.get(this.actionUrl + 'rda/' + id, { responseType: 'blob', observe: 'response' }); + } } diff --git a/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.html b/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.html index ea6fa3f22..a85436ba8 100644 --- a/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.html +++ b/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.html @@ -8,8 +8,8 @@
- -

{{ dataset.label }}

+ +

{{ dataset.label }}

@@ -27,56 +27,40 @@ {{'DMP-OVERVIEW.PRIVATE' | translate}}
- - -
{{'GENERAL.STATUSES.EDIT' | translate}} : +
+ lock_outline + {{'DMP-OVERVIEW.LOCKED' | translate}} +
+
{{'GENERAL.STATUSES.EDIT' | translate}} : {{dataset.modified | date:"longDate"}}
- +
- -
{{'DATASET-LISTING.TOOLTIP.PART-OF' | translate}}
-
{{'DMP-OVERVIEW.GRANT' | translate}}
-
Grant label
- +
{{ dataset.grant.label }}
{{'DMP-OVERVIEW.RESEARCHERS' | translate}}
- +
{{'DATASET-LISTING.COLUMNS.DESCRIPTION' | translate}}
@@ -104,31 +87,9 @@
-
- - - - - - +
diff --git a/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.scss b/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.scss index cc76c8022..6b918f358 100644 --- a/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.scss +++ b/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.scss @@ -20,7 +20,7 @@ font-size: 1.2em; } -.mat-mini-fab:hover { +.actions-btn:hover { background-color: #129D99; color: #FFFFFF; } @@ -139,6 +139,7 @@ .dataset-label { font-weight: bold; + width: auto; } .uppercase { @@ -149,14 +150,13 @@ font-size: 0.875em; color: #008887; padding-right: 0.5em; - align-self: center; - + align-self: center;; } .header { opacity: 0.6; margin-top: 1em; - margin-bottom: 0.25em; + margin-bottom: 0.5em; } .dataset-label, .header { @@ -262,7 +262,7 @@ // ********CENTER ELEMENTS******** -.mat-mini-fab, .mat-mini-fab-icon, +.mat-mini-fab, .mat-mini-fab-icon, .actions-btn, .status-icon, .dataset-logo, .frame-btn, .finalize-btn { display: flex; justify-content: center; diff --git a/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.ts b/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.ts index e7cbd4742..adb861816 100644 --- a/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.ts +++ b/dmp-frontend/src/app/ui/dataset/overview/dataset-overview.component.ts @@ -19,6 +19,15 @@ import { Location } from '@angular/common'; import { UserInfoListingModel } from '@app/core/model/user/user-info-listing'; import { DatasetStatus } from '@app/core/common/enum/dataset-status'; import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import * as FileSaver from 'file-saver'; +import { DmpInvitationDialogComponent } from '@app/ui/dmp/invitation/dmp-invitation.component'; +import { DatasetWizardEditorModel } from '../dataset-wizard/dataset-wizard-editor.model'; +import { DatasetWizardService } from '@app/core/services/dataset-wizard/dataset-wizard.service'; +import { FormControl } from '@angular/forms'; +import { DatasetCopyDialogueComponent } from '../dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { ResearcherModel } from '@app/core/model/researcher/researcher'; +import { LockService } from '@app/core/services/lock/lock.service'; @Component({ @@ -29,6 +38,7 @@ import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog export class DatasetOverviewComponent extends BaseComponent implements OnInit { dataset: DatasetOverviewModel; + datasetWizardModel: DatasetWizardEditorModel; isNew = true; isFinalized = false; isPublicView = true; @@ -37,6 +47,8 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit { isUserOwner: boolean; expand = false; hasDOIToken = false; + researchers: ResearcherModel[]; + lockStatus: Boolean; constructor( private route: ActivatedRoute, @@ -50,7 +62,10 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit { private configurationService: ConfigurationService, private oauth2DialogService: Oauth2DialogService, private userService: UserService, - private location: Location + private dmpService: DmpService, + private location: Location, + private datasetWizardService: DatasetWizardService, + private lockService: LockService ) { super(); } @@ -69,7 +84,12 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit { .pipe(takeUntil(this._destroyed)) .subscribe(data => { this.dataset = data; - // this.checkLockStatus(this.dataset.id); + this.getDmpResearchers(); + this.datasetWizardService.getSingle(this.dataset.id).pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data); + }); + this.checkLockStatus(this.dataset.id); this.setIsUserOwner(); const breadCrumbs = []; breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.MY-DATASET-DESCRIPTIONS'), url: "/datasets" }); @@ -92,7 +112,12 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit { .pipe(takeUntil(this._destroyed)) .subscribe(data => { this.dataset = data; - // this.checkLockStatus(this.dataset.id); + this.getDmpResearchers(); + this.datasetWizardService.getSingle(this.dataset.id).pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.datasetWizardModel = new DatasetWizardEditorModel().fromModel(data); + }); + this.checkLockStatus(this.dataset.id); this.setIsUserOwner(); const breadCrumbs = []; breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC DATASETS'), url: "/explore" }); @@ -110,112 +135,241 @@ export class DatasetOverviewComponent extends BaseComponent implements OnInit { }); } - onFetchingDeletedCallbackError(redirectRoot: string) { - this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-OVERVIEW.ERROR.DELETED-DATASET'), SnackBarNotificationLevel.Error); - this.router.navigate([redirectRoot]); + checkLockStatus(id: string){ + this.lockService.checkLockStatus(id).pipe(takeUntil(this._destroyed)) + .subscribe(lockStatus => this.lockStatus = lockStatus); } - onFetchingForbiddenCallbackError(redirectRoot: string) { - this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-OVERVIEW.ERROR.FORBIDEN-DATASET'), SnackBarNotificationLevel.Error); - this.router.navigate([redirectRoot]); + onFetchingDeletedCallbackError(redirectRoot: string) { + this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-OVERVIEW.ERROR.DELETED-DATASET'), SnackBarNotificationLevel.Error); + this.router.navigate([redirectRoot]); } - + + onFetchingForbiddenCallbackError(redirectRoot: string) { + this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-OVERVIEW.ERROR.FORBIDEN-DATASET'), SnackBarNotificationLevel.Error); + this.router.navigate([redirectRoot]); + } + goBack(): void { - this.location.back(); - } + this.location.back(); + } + + getDmpResearchers() { + this.dmpService.getSingle(this.dataset.dmp.id).pipe(takeUntil(this._destroyed)) + .subscribe(data => { + this.researchers = data.researchers; + }); + } setIsUserOwner() { - if (this.dataset) { - const principal: Principal = this.authentication.current(); - if (principal) this.isUserOwner = principal.id === this.dataset.users.find(x => x.role === Role.Owner).id; - } + if (this.dataset) { + const principal: Principal = this.authentication.current(); + if (principal) this.isUserOwner = principal.id === this.dataset.users.find(x => x.role === Role.Owner).id; + } + } + + isUserAuthor(userId: string): boolean { + const principal: Principal = this.authentication.current(); + return userId === principal.id; } isUserDatasetRelated() { - const principal: Principal = this.authentication.current(); - let isRelated: boolean = false; - if (this.dataset && principal) { - this.dataset.users.forEach(element => { - if (element.id === principal.id) { - isRelated = true; - } - }) - } - return isRelated; + const principal: Principal = this.authentication.current(); + let isRelated: boolean = false; + if (this.dataset && principal) { + this.dataset.users.forEach(element => { + if (element.id === principal.id) { + isRelated = true; + } + }) + } + return isRelated; } - - roleDisplayFromList(value: UserInfoListingModel[]) { - const principal: Principal = this.authentication.current(); - let role: number; - if (principal) { - value.forEach(element => { - if (principal.id === element.id) { - role = element.role; - } - }); - } - if (role === Role.Owner) { - return this.translate.instant('DMP-LISTING.OWNER'); - } else if (role === Role.Member) { - return this.translate.instant('DMP-LISTING.MEMBER'); - } else { - return this.translate.instant('DMP-LISTING.OWNER'); - } - } - - public isAuthenticated(): boolean { - return !(!this.authentication.current()); - } - - cloneClicked(dataset: DatasetOverviewModel) { - this.router.navigate(['/datasets/clone/' + dataset.id]); - } - - isDraftDataset(dataset: DatasetOverviewModel) { - return dataset.status == DatasetStatus.Draft; - } - - editClicked(dataset: DatasetOverviewModel) { - this.router.navigate(['/datasets/edit/' + dataset.id]); - } - - deleteClicked() { - const dialogRef = this.dialog.open(ConfirmationDialogComponent, { - maxWidth: '300px', - data: { - message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), - confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.DELETE'), - cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), - isDeleteConfirmation: true - } - }); - dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { - if (result) { - this.datasetService.delete(this.dataset.id) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => { this.onCallbackSuccess() }, - error => this.onDeleteCallbackError(error) - ); - } - }); - } - - onCallbackSuccess(): void { - this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); - this.router.navigate(['/datasets']); - } - onDeleteCallbackError(error) { - this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); + roleDisplay(value: UserInfoListingModel) { + if (value.role === Role.Owner) { + return this.translate.instant('DMP-LISTING.OWNER'); + } else if (value.role === Role.Member) { + return this.translate.instant('DMP-LISTING.MEMBER'); + } else { + return this.translate.instant('DMP-LISTING.OWNER'); + } } - + + + roleDisplayFromList(value: UserInfoListingModel[]) { + const principal: Principal = this.authentication.current(); + let role: number; + if (principal) { + value.forEach(element => { + if (principal.id === element.id) { + role = element.role; + } + }); + } + if (role === Role.Owner) { + return this.translate.instant('DMP-LISTING.OWNER'); + } else if (role === Role.Member) { + return this.translate.instant('DMP-LISTING.MEMBER'); + } else { + return this.translate.instant('DMP-LISTING.OWNER'); + } + } + + openShareDialog(rowId: any, rowName: any) { + const dialogRef = this.dialog.open(DmpInvitationDialogComponent, { + restoreFocus: false, + data: { + dmpId: rowId, + dmpName: rowName + } + }); + } + + public isAuthenticated(): boolean { + return !(!this.authentication.current()); + } + + isDraftDataset(dataset: DatasetOverviewModel) { + return dataset.status == DatasetStatus.Draft; + } + + isFinalizedDataset(dataset: DatasetOverviewModel) { + return dataset.status == DatasetStatus.Finalized; + } + + editClicked(dataset: DatasetOverviewModel) { + if (dataset.public) { + this.router.navigate(['/datasets/publicEdit/' + dataset.id]); + } else { + this.router.navigate(['/datasets/edit/' + dataset.id]); + } + } + + deleteClicked() { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + maxWidth: '300px', + data: { + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.DELETE'), + cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), + isDeleteConfirmation: true + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + if (result) { + this.datasetService.delete(this.dataset.id) + .pipe(takeUntil(this._destroyed)) + .subscribe( + complete => { this.onCallbackSuccess() }, + error => this.onDeleteCallbackError(error) + ); + } + }); + } + + dmpClicked(dmpId: String) { + this.router.navigate(['/plans/overview/' + dmpId]); + } + + onCallbackSuccess(): void { + this.uiNotificationService.snackBarNotification(this.isNew ? this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-CREATION') : this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); + this.router.navigate(['/datasets']); + } + + onDeleteCallbackError(error) { + this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); + } + public getOrcidPath(): string { - return this.configurationService.orcidPath; + return this.configurationService.orcidPath; } - - // showPublishButton(dataset: DatasetOverviewModel) { - // return this.isFinalizedDmp(dmp) && !dmp.isPublic && this.hasPublishButton; - // } + + downloadPDF(id: string) { + this.datasetService.downloadPDF(id) + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/pdf' }); + const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); + + FileSaver.saveAs(blob, filename); + }); + } + + downloadDocx(id: string) { + this.datasetService.downloadDocx(id) + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/msword' }); + const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition')); + + FileSaver.saveAs(blob, filename); + }); + } + + downloadXml(id: string) { + this.datasetService.downloadXML(id) + .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); + }); + } + + downloadJson(id: string) { + this.datasetService.downloadJson(id) + .pipe(takeUntil(this._destroyed)) + .subscribe(response => { + const blob = new Blob([response.body], { type: 'application/json' }); + 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; + } + + openDmpSearchDialogue() { + const formControl = new FormControl(); + const dialogRef = this.dialog.open(DatasetCopyDialogueComponent, { + width: '500px', + restoreFocus: false, + data: { + formControl: formControl, + datasetId: this.dataset.id, + datasetProfileId: this.datasetWizardModel.profile, + datasetProfileExist: false, + confirmButton: this.language.instant('DATASET-WIZARD.DIALOGUE.COPY'), + cancelButton: this.language.instant('DATASET-WIZARD.DIALOGUE.CANCEL') + } + }); + + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)) + .subscribe(result => { + if (result && result.datasetProfileExist) { + const newDmpId = result.formControl.value.id + this.router.navigate(['/datasets/copy/' + result.datasetId], { queryParams: { newDmpId: newDmpId } }); + } + }); + } + + } diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index cd5c4e1f2..e69f6c004 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -26,15 +26,9 @@ {{'DMP-OVERVIEW.PRIVATE' | translate}} -
-
- lock_outline - {{'DMP-OVERVIEW.LOCKED' | translate}} -
-
- lock_open - {{'DMP-OVERVIEW.UNLOCKED' | translate}} -
+
+ lock_outline + {{'DMP-OVERVIEW.LOCKED' | translate}}
@@ -56,22 +50,16 @@ matTooltip="{{'DMP-LISTING.ACTIONS.CLONE' | translate}}" matTooltipPosition="above"> content_copy - - -
{{'DMP-OVERVIEW.GRANT' | translate}}
{{ dmp.grant.label }}
@@ -141,7 +129,7 @@
-
+
- + +
@@ -60,7 +62,7 @@
-
About
+
FAQs
FAQs
@@ -108,7 +110,7 @@
-

ARGOS is comprised of two main functionalities: DMP templates and Dataset Descriptions. +

ARGOS is comprised of two main functionalities: DMP templates and Dataset Descriptions. Additional entities are Projects that link to funders and grants information.
ARGOS can be used for:

A. viewing/ consulting publicly released DMPs and @@ -131,7 +133,7 @@ Examples may refer to embedding DMP and DMP tools in specific curricula or even utilization of the tool for researchers and students familiarization with the concept and process, as part of library instructions’ sessions. -

+
@@ -206,4 +208,4 @@ - \ No newline at end of file + diff --git a/dmp-frontend/src/assets/splash/about/how-it-works.html b/dmp-frontend/src/assets/splash/about/how-it-works.html index 9bfe06404..7446523a2 100644 --- a/dmp-frontend/src/assets/splash/about/how-it-works.html +++ b/dmp-frontend/src/assets/splash/about/how-it-works.html @@ -59,7 +59,7 @@
-
About
+
How it works
How it works