You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
argos/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts

569 lines
19 KiB
TypeScript

import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { Principal } from '@app/core/model/auth/principal';
import { DatasetOverviewModel } from '@app/core/model/dataset/dataset-overview';
import { DatasetsToBeFinalized } from '@app/core/model/dataset/datasets-toBeFinalized';
import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview';
import { UserInfoListingModel } from '@app/core/model/user/user-info-listing';
import { AuthService } from '@app/core/services/auth/auth.service';
import { DmpService } from '@app/core/services/dmp/dmp.service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import { DmpFinalizeDialogComponent, DmpFinalizeDialogInput, DmpFinalizeDialogOutput } from '@app/ui/dmp/editor/dmp-finalize-dialog/dmp-finalize-dialog.component';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { BaseComponent } from '@common/base/base.component';
import { TranslateService } from '@ngx-translate/core';
import * as FileSaver from 'file-saver';
import { Observable, of as observableOf } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Role } from "@app/core/common/enum/role";
import { DmpInvitationDialogComponent } from '../invitation/dmp-invitation.component';
import { MultipleChoiceDialogModule } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module';
import { MultipleChoiceDialogComponent } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.component';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
import { Oauth2DialogComponent } from '@app/ui/misc/oauth2-dialog/oauth2-dialog.component';
import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service';
import { isNullOrUndefined } from 'util';
import { UserService } from '@app/core/services/user/user.service';
@Component({
selector: 'app-dmp-overview',
templateUrl: './dmp-overview.component.html',
styleUrls: ['./dmp-overview.component.scss']
})
export class DmpOverviewComponent extends BaseComponent implements OnInit {
dmp: DmpOverviewModel;
isNew = true;
isFinalized = false;
isPublicView = true;
hasPublishButton: boolean = true;
breadCrumbs: Observable<BreadcrumbItem[]> = observableOf();
isUserOwner: boolean;
expand = false;
hasDOIToken = false;
constructor(
private route: ActivatedRoute,
private router: Router,
private dmpService: DmpService,
private translate: TranslateService,
private authentication: AuthService,
private dialog: MatDialog,
private language: TranslateService,
private uiNotificationService: UiNotificationService,
private configurationService: ConfigurationService,
private oauth2DialogService: Oauth2DialogService,
private userService: UserService
) {
super();
}
ngOnInit() {
// Gets dmp data using parameter id
this.route.params
.pipe(takeUntil(this._destroyed))
.subscribe((params: Params) => {
const itemId = params['id'];
const publicId = params['publicId'];
if (itemId != null) {
this.isNew = false;
this.isPublicView = false;
this.dmpService.getOverviewSingle(itemId)
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
this.dmp = data;
this.setIsUserOwner();
const breadCrumbs = [];
breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.MY-DMPS'), url: "/plans" });
breadCrumbs.push({ parentComponentName: 'DmpListingComponent', label: this.dmp.label, url: '/plans/overview/' + this.dmp.id });
this.breadCrumbs = observableOf(breadCrumbs);
}, (error: any) => {
if (error.status === 404) {
return this.onFetchingDeletedCallbackError('/plans/');
}
if (error.status === 403) {
return this.onFetchingForbiddenCallbackError('/plans/');
}
});
}
else if (publicId != null) {
this.isNew = false;
this.isFinalized = true;
this.isPublicView = true;
this.dmpService.getOverviewSinglePublic(publicId)
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
this.dmp = data;
this.setIsUserOwner();
const breadCrumbs = [];
breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC-DMPS'), url: "/explore-plans" });
breadCrumbs.push({ parentComponentName: 'DmpListingComponent', label: this.dmp.label, url: '/plans/publicOverview/' + this.dmp.id });
this.breadCrumbs = observableOf(breadCrumbs);
}, (error: any) => {
if (error.status === 404) {
return this.onFetchingDeletedCallbackError('/explore-plans');
}
if (error.status === 403) {
return this.onFetchingForbiddenCallbackError('/explore-plans');
}
});
}
});
}
onFetchingDeletedCallbackError(redirectRoot: string) {
this.uiNotificationService.snackBarNotification(this.language.instant('DMP-OVERVIEW.ERROR.DELETED-DMP'), SnackBarNotificationLevel.Error);
this.router.navigate([redirectRoot]);
}
onFetchingForbiddenCallbackError(redirectRoot: string) {
this.uiNotificationService.snackBarNotification(this.language.instant('DMP-OVERVIEW.ERROR.FORBIDEN-DMP'), SnackBarNotificationLevel.Error);
this.router.navigate([redirectRoot]);
}
setIsUserOwner() {
if (this.dmp) {
const principal: Principal = this.authentication.current();
if (principal) this.isUserOwner = principal.id === this.dmp.users.find(x => x.role === Role.Owner).id;
}
}
editClicked(dmp: DmpOverviewModel) {
this.router.navigate(['/plans/edit/' + dmp.id]);
}
cloneClicked(dmp: DmpOverviewModel) {
this.router.navigate(['/plans/clone/' + dmp.id]);
}
grantClicked(grantId: String) {
// ----------- UNCOMMENT TO ADD AGAIN GRANTS --------
// this.router.navigate(['/grants/edit/' + grantId]);
}
expandDesc() {
this.expand = !this.expand;
}
checkOverflow(element) {
if (this.expand || (element.offsetHeight < element.scrollHeight ||
element.offsetWidth < element.scrollWidth)) {
return true;
} else {
return false;
}
}
datasetClicked(datasetId: String) {
if (this.isPublicView) {
this.router.navigate(['/datasets/publicEdit/' + datasetId]);
} else {
this.router.navigate(['/datasets/edit/' + datasetId]);
}
}
datasetsClicked(dmpId: String) {
if (!this.isFinalized)
this.router.navigate(['/plans/edit/' + dmpId], { queryParams: { tab: "datasetDescriptions" } });
else
this.router.navigate(['/explore'], { queryParams: { dmpId: dmpId } });
}
goToUri(uri: string) {
window.open(uri, "_blank");
}
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.dmpService.delete(this.dmp.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(['/plans']);
}
onDeleteCallbackError(error) {
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error);
}
downloadXml(id: string) {
this.dmpService.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);
});
}
downloadDocx(id: string) {
this.dmpService.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);
});
}
downloadPDF(id: string) {
this.dmpService.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);
});
}
downloadJson(id: string) {
this.dmpService.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;
}
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');
}
}
isUserDMPRelated() {
const principal: Principal = this.authentication.current();
let isRelated: boolean = false;
if (this.dmp && principal) {
this.dmp.users.forEach(element => {
if (element.id === principal.id) {
isRelated = true;
}
})
}
return isRelated;
}
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');
}
}
isDraftDataset(dataset: DatasetOverviewModel) {
return dataset.status == DatasetStatus.Draft;
}
isDraftDmp(dmp: DmpOverviewModel) {
return dmp.status == DmpStatus.Draft;
}
isFinalizedDmp(dmp: DmpOverviewModel) {
return dmp.status == DmpStatus.Finalized;
}
isPublishedDMP(dmp: DmpOverviewModel) {
return (dmp.status == DmpStatus.Finalized && dmp.isPublic);
}
hasDoi(dmp: DmpOverviewModel) {
return dmp.doi == null ? true : false;
}
getAccessUrl(): string {
const redirectUri = this.configurationService.app + 'oauth2';
const url = this.configurationService.loginProviders.zenodoConfiguration.oauthUrl
+ '?client_id=' + this.configurationService.loginProviders.zenodoConfiguration.clientId
+ '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri='
+ redirectUri;
return url;
}
getDoi(dmp: DmpOverviewModel) {
this.userService.hasDOIToken().subscribe(response => {
this.hasDOIToken = true;
this.showConfirmationDOIDialog(dmp);
}, error => {
this.hasDOIToken = false;
this.showErrorConfirmationDOIDialog(error.error.message, dmp);
});
}
showConfirmationDOIDialog(dmp: DmpOverviewModel) {
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '600px',
restoreFocus: false,
data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ZENODO-DOI', { 'username': this.hasDOIToken ? this.authentication.current().zenodoEmail : 'default' }),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
this.dmpService.getDoi(dmp.id)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => {
this.onDOICallbackSuccess();
this.dmp.doi = complete;
},
error => this.onDeleteCallbackError(error)
);
}
});
}
showErrorConfirmationDOIDialog(message: string, dmp: DmpOverviewModel) {
const dialogRef = this.dialog.open(MultipleChoiceDialogComponent, {
maxWidth: '600px',
restoreFocus: false,
data: {
message: message,
titles: [this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.ZENODO-LOGIN'), this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')]
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
switch (result) {
case 0:
// this.authentication.logout();
// this.router.navigate(['/login/external/zenodo']);
this.showOauth2Dialog(this.getAccessUrl(), dmp);
break;
case 1:
this.showConfirmationDOIDialog(dmp);
break;
}
});
}
showOauth2Dialog(url: string, dmp: DmpOverviewModel) {
this.oauth2DialogService.login(url)
.pipe(takeUntil(this._destroyed))
.subscribe(code => {
if (!isNullOrUndefined(code)) {
this.userService.registerDOIToken(code, this.configurationService.app + 'oauth2')
.pipe(takeUntil(this._destroyed))
.subscribe(() => {
this.hasDOIToken = true;
this.showConfirmationDOIDialog(dmp);
});
}
});
}
onDOICallbackSuccess(): void {
this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success);
}
onDOICallbackError(error) {
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-DOI'), SnackBarNotificationLevel.Error);
}
showPublishButton(dmp: DmpOverviewModel) {
return this.isFinalizedDmp(dmp) && !dmp.isPublic && this.hasPublishButton;
}
publish(dmpId: String) {
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '500px',
restoreFocus: false,
data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.PUBLISH-ITEM'),
privacyPolicyNames: this.language.instant('GENERAL.CONFIRMATION-DIALOG.PRIVACY-POLICY-NAMES'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
isDeleteConfirmation: false
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
this.dmpService.publish(dmpId)
.pipe(takeUntil(this._destroyed))
.subscribe(() => { this.hasPublishButton = false });
}
});
}
finalize(dmp: DmpOverviewModel) {
const dialogInputModel: DmpFinalizeDialogInput = {
dmpLabel: this.dmp.label,
dmpDescription: this.dmp.description,
datasets: this.dmp.datasets.map(x => {
return { label: x.label, id: x.id, status: x.status }
})
}
const dialogRef = this.dialog.open(DmpFinalizeDialogComponent, {
maxWidth: '500px',
restoreFocus: false,
data: {
dialogInputModel: dialogInputModel,
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'),
confirmButton: this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: DmpFinalizeDialogOutput) => {
if (result && !result.cancelled) {
var datasetsToBeFinalized: DatasetsToBeFinalized = {
uuids: result.datasetsToBeFinalized
};
this.dmpService.finalize(datasetsToBeFinalized, this.dmp.id)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => {
this.dmp.status = DmpStatus.Finalized;
this.onCallbackSuccess()
},
error => this.onFinalizeCallbackError(error)
);
}
});
}
onFinalizeCallbackError(error) {
this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-FINALIZE'), SnackBarNotificationLevel.Error);
}
newVersion(id: String, label: String) {
this.router.navigate(['/plans/new_version/' + id, { dmpLabel: label }]);
}
viewVersions(rowId: String, rowLabel: String) {
if (this.dmp.isPublic && !this.isUserOwner) {
this.router.navigate(['/explore-plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } });
} else {
this.router.navigate(['/plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } });
}
}
public isAuthenticated(): boolean {
return !(!this.authentication.current());
}
openShareDialog(rowId: any, rowName: any) {
const dialogRef = this.dialog.open(DmpInvitationDialogComponent, {
// height: '250px',
// width: '700px',
restoreFocus: false,
data: {
dmpId: rowId,
dmpName: rowName
}
});
}
addDataset(rowId: String) {
this.router.navigate(['/datasets/new/' + rowId]);
}
// advancedClicked() {
// const dialogRef = this.dialog.open(ExportMethodDialogComponent, {
// maxWidth: '500px',
// data: {
// message: "Download as:",
// XMLButton: "XML",
// documentButton: "Document",
// pdfButton: "PDF",
// jsonButton: "JSON"
// }
// });
// dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
// if (result == "pdf") {
// this.downloadPDF(this.dmp.id);
// } else if (result == "xml") {
// this.downloadXml(this.dmp.id);
// } else if (result == "doc") {
// this.downloadDocx(this.dmp.id);
// } else if (result == "json") {
// this.downloadJson(this.dmp.id);
// }
// });
// }
// advancedClickedFinalized() {
// const dialogRef = this.dialog.open(ExportMethodDialogComponent, {
// maxWidth: '250px',
// data: {
// message: "Download as:",
// documentButton: "Document",
// pdfButton: "PDF",
// isFinalized: true
// }
// });
// dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
// if (result == "pdf") {
// this.downloadPDF(this.dmp.id);
// } else if (result == "doc") {
// this.downloadDocx(this.dmp.id);
// }
// });
// }
}