argos/dmp-frontend/src/app/ui/dmp/listing/dmp-listing.component.ts

616 lines
21 KiB
TypeScript

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { ActivatedRoute, Router } from '@angular/router';
import { DataTableRequest } from '@app/core/model/data-table/data-table-request';
import { DmpListingModel } from '@app/core/model/dmp/dmp-listing';
import { GrantListingModel } from '@app/core/model/grant/grant-listing';
import { DmpCriteria } from '@app/core/query/dmp/dmp-criteria';
import { DmpService } from '@app/core/services/dmp/dmp.service';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { DmpInvitationDialogComponent } from '@app/ui/dmp/invitation/dmp-invitation-dialog.component';
import { DmpCriteriaComponent } from '@app/ui/dmp/listing/criteria/dmp-criteria.component';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent';
import { BaseComponent } from '@common/base/base.component';
import { TranslateService } from '@ngx-translate/core';
import { Observable, of as observableOf } from 'rxjs';
import { debounceTime, takeUntil } from 'rxjs/operators';
import { GrantService } from "@app/core/services/grant/grant.service";
import { DmpUploadDialogue } from './upload-dialogue/dmp-upload-dialogue.component';
import { UiNotificationService, SnackBarNotificationLevel } from '@app/core/services/notification/ui-notification-service';
import { isNullOrUndefined } from '@app/utilities/enhancers/utils';
import { AuthService } from '@app/core/services/auth/auth.service';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { DmpCriteriaDialogComponent } from './criteria/dmp-criteria-dialog.component';
import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order';
import { GuidedTourService } from '@app/library/guided-tour/guided-tour.service';
import { GuidedTour, Orientation } from '@app/library/guided-tour/guided-tour.constants';
//import { NgDialogAnimationService } from "ng-dialog-animation";
import { HttpClient } from '@angular/common/http';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
@Component({
selector: 'app-dmp-listing-component',
templateUrl: 'dmp-listing.component.html',
styleUrls: ['./dmp-listing.component.scss'],
})
export class DmpListingComponent extends BaseComponent implements OnInit, IBreadCrumbComponent {
@ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
// @ViewChild(DmpCriteriaComponent, { static: true }) criteria: DmpCriteriaComponent;
breadCrumbs: Observable<BreadcrumbItem[]> = observableOf([{ parentComponentName: null, label: 'DMPs', url: "/plans" }]);
itemId: string;
grantId: string;
showGrant: boolean;
titlePrefix: string;
totalCount: number;
listingItems: DmpListingModel[] = [];
allVersions: boolean = false;
groupLabel: string;
isPublic: boolean = false;
public isVisible = true
hasListingItems = null;
startIndex: number = 0;
pageSize: number = 5;
criteria: DmpCriteria;
criteriaFormGroup: FormGroup;
public formGroup = new FormBuilder().group({
like: new FormControl(),
order: new FormControl()
});
scrollbar: boolean;
order = RecentActivityOrder;
dmpText: string;
datasetText: string;
constructor(
private dmpService: DmpService,
private router: Router,
private route: ActivatedRoute,
//public dialogAnimation: NgDialogAnimationService,
public dialog: MatDialog,
public enumUtils: EnumUtils,
private language: TranslateService,
private grantService: GrantService,
private uiNotificationService: UiNotificationService,
private authService: AuthService,
private guidedTourService: GuidedTourService,
private httpClient: HttpClient,
private matomoService: MatomoService
) {
super();
}
ngOnInit() {
this.matomoService.trackPageView('DMPs');
this.isPublic = this.router.url.startsWith('/explore-plans');
if (this.isPublic) {
this.formGroup.get('order').setValue(this.order.PUBLISHED);
} else {
this.formGroup.get('order').setValue(this.order.MODIFIED);
}
if (!this.isPublic && isNullOrUndefined(this.authService.current())) {
this.router.navigateByUrl("/explore-plans");
}
this.route.params
.pipe(takeUntil(this._destroyed))
.subscribe(async params => {
let grantLabel;
if (params['grantId']) {
this.grantId = params['grantId'];
this.showGrant = true;
this.grantService.getSingle(this.grantId)
.subscribe((grant: GrantListingModel) => {
// const grant: GrantListingModel = {
// id: this.grantId
// }
// this.breadCrumbs = Observable.of([{ parentComponentName: 'GrantEditorComponent', label: grantLabel, url: '/grants/edit/' + this.grantId }]);
grantLabel = this.route.snapshot.queryParams.grantLabel;
this.criteria = { like: null, grants: [grant], groupIds: null, allVersions: false }
// this.criteria.setCriteria({ like: null, grants: [grant], groupIds: null, allVersions: false });
this.refresh();
// this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages));
})
} else if (params['groupId']) {
this.itemId = params['groupId'];
this.showGrant = true;
this.allVersions = true;
this.language.get('NAV-BAR.MY-DMPS').pipe(takeUntil(this._destroyed)).subscribe(x => {
this.breadCrumbs = observableOf([
{
parentComponentName: null,
label: x,
url: '/plans'
}]
);
})
this.groupLabel = this.route.snapshot.queryParams.groupLabel;
// this.criteria.setCriteria(this.getDefaultCriteria());
this.criteria = this.getDefaultCriteria();
this.criteria.groupIds ? this.criteria.groupIds.push(this.itemId) : this.criteria.groupIds = [this.itemId];
this.refresh();
// this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages));
} else {
this.itemId = params['groupId'];
this.showGrant = true;
const breadCrumbs = [];
// if (this.itemId) {
// const dmplabel = this.route.snapshot.queryParams.groupLabel;
// breadCrumbs.push({
// parentComponentName: null,
// label: this.language.instant('NAV-BAR.DMPS'),
// url: '/plans'
// });
// }
// else
this.language.get('NAV-BAR.MY-DMPS').pipe(takeUntil(this._destroyed)).subscribe(x => {
this.breadCrumbs = observableOf([
{
parentComponentName: null,
label: x,
url: '/plans'
}]
);
})
// this.criteria.setCriteria(this.getDefaultCriteria());
this.criteria = this.getDefaultCriteria();
this.refresh();
// this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages));
}
if (this.grantId != null) {
if (grantLabel !== undefined) {
this.titlePrefix = 'for ' + grantLabel;
}
}
});
this.formGroup.get('like').valueChanges
.pipe(takeUntil(this._destroyed), debounceTime(500))
.subscribe(x => this.controlModified());
this.formGroup.get('order').valueChanges
.pipe(takeUntil(this._destroyed))
.subscribe(x => this.refresh());
}
public dashboardTour: GuidedTour = {
tourId: 'dmp-dataset-tour',
useOrb: true,
steps: [
{
selector: '.dmp-tour',
content: 'Step 1',
orientation: Orientation.Right,
isStepUnique: false
},
{
selector: '.dataset-tour',
content: 'Step 2',
orientation: Orientation.Right,
isStepUnique: false
}
]
};
public isAuthenticated(): boolean {
return !(!this.authService.current());
}
ngAfterContentChecked(): void {
this.scrollbar = this.hasScrollbar();
}
openTour() {
this.language.get('DMP-LISTING.TEXT-INFO').pipe(takeUntil(this._destroyed)).subscribe((x: string) => {
this.dashboardTour.steps[0].title = x + '\n\n' +
this.language.instant('DMP-LISTING.TEXT-INFO-QUESTION') + ' ' +
this.language.instant('DMP-LISTING.LINK-ZENODO') + ' ' +
this.language.instant('DMP-LISTING.GET-IDEA');
this.dashboardTour.steps[1].title = this.language.instant('DATASET-LISTING.TEXT-INFO') +
this.language.instant('DATASET-LISTING.LINK-PUBLIC-DATASETS') + ' ' +
this.language.instant('DATASET-LISTING.TEXT-INFO-REST') + '\n\n' +
this.language.instant('DATASET-LISTING.TEXT-INFO-PAR');
this.guidedTourService.startTour(this.dashboardTour);
});
}
public refresh(resetPages = false) {
// if (this._paginator.pageSize === undefined) this._paginator.pageSize = 10;
// if (resetPages) this._paginator.pageIndex = 0;
// const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
// let fields: Array<string> = new Array();
// if (this.sort && this.sort.active) { fields = this.sort.direction === 'asc' ? ['+' + this.sort.active] : ['-' + this.sort.active]; }
// fields.push('-modified');
const fields: Array<string> = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value];
this.startIndex = 0;
const request = new DataTableRequest<DmpCriteria>(this.startIndex, this.pageSize, { fields: fields });
this.setPublicCriteria();
request.criteria = this.criteria;
this.dmpService.getPaged(request, "listing").pipe(takeUntil(this._destroyed)).subscribe(result => {
if (!result) { return []; }
result.data.map(item => {
item['datasets'].map(dmp => {
dmp.url = 'datasets/edit/' + dmp.url;
dmp.all = 'datasets/dmp/' + item.id;
return dmp;
});
return item;
});
this.listingItems = result.data;
this.hasListingItems = true;
if (!this.isPublic && this.listingItems.length === 0 && !this.hasCriteria() && !this.hasLikeCriteria()) {
this.openTour();
}
this.totalCount = result.totalCount;
});
}
public loadMore() {
this.startIndex = this.startIndex + this.pageSize;
// const fields: Array<string> = ["-modified"];
const fields: Array<string> = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value];
const request = new DataTableRequest<DmpCriteria>(this.startIndex, this.pageSize, { fields: fields });
this.setPublicCriteria();
request.criteria = this.criteria;
this.dmpService.getPaged(request, "listing").pipe(takeUntil(this._destroyed)).subscribe(result => {
if (!result) { return []; }
result.data.map(item => {
item['datasets'].map(dmp => {
dmp.url = 'datasets/edit/' + dmp.url;
dmp.all = 'datasets/dmp/' + item.id;
return dmp;
});
return item;
});
// this.listingItems = this.listingItems.concat(result.data);
this.listingItems = this.mergeTwoSortedLists(this.listingItems, result.data, this.formGroup.get('order').value);
this.hasListingItems = true;
});
}
pageThisEvent(event) {
this.refresh();
}
hasCriteria(): boolean {
if (this.criteria.organisations && this.criteria.organisations.length > 0 ||
this.criteria.grants && this.criteria.grants.length > 0 ||
this.criteria.collaborators && this.criteria.collaborators.length > 0 ||
this.criteria.datasetTemplates && this.criteria.datasetTemplates.length > 0 ||
this.criteria.onlyPublic === true
) { return true; } else { return false; }
}
controlModified(): void {
// this.clearErrorModel();
// if (this.refreshCallback != null &&
// (this.formGroup.get('like').value == null || this.formGroup.get('like').value.length === 0 || this.formGroup.get('like').value.length > 2)
// ) {
// setTimeout(() => this.refreshCallback(true));
// }
this.criteria.like = this.formGroup.get("like").value;
this.startIndex = 0;
this.refresh();
}
// rowClicked(dmp: DmpListingModel) {
// this.router.navigate(['/plans/overview/' + dmp.id]);
// }
public closeCard(): void {
this.isVisible = false;
}
// addDataset(rowId: String) {
// this.router.navigate(['/datasets/new/' + rowId]);
// }
showDatasets(rowId: String, rowLabel: String) {
this.router.navigate(['/datasets/dmp/' + rowId, { dmpLabel: rowLabel }]);
}
viewVersions(rowId: String, rowLabel: String) {
this.router.navigate(['/plans/versions/' + rowId], { queryParams: { groupLabel: rowLabel } });
}
getDefaultCriteria(): DmpCriteria {
const defaultCriteria = new DmpCriteria();
if (this.isPublic) {
defaultCriteria.isPublic = true;
defaultCriteria.onlyPublic = true;
}
if (this.allVersions) {
defaultCriteria.allVersions = true;
}
return defaultCriteria;
}
openShareDialog(rowId: any, rowName: any) {
const dialogRef = this.dialog.open(DmpInvitationDialogComponent, {
autoFocus: false,
data: {
dmpId: rowId,
dmpName: rowName
}
});
}
fileSave(event) {
const dialogRef = this.dialog.open(DmpUploadDialogue, {
data: {
fileList: FileList,
success: Boolean,
dmpTitle: String
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result && result.success) {
this.dmpService.uploadXml(result.fileList[0], result.dmpTitle, result.dmpProfiles)
.pipe(takeUntil(this._destroyed))
.subscribe((complete) => this.onCallbackImportComplete(),
(error) => this.onCallbackImportFail(error.error));
}
});
}
private onCallbackImportComplete() {
this.uiNotificationService.snackBarNotification(this.language.instant('DMP-UPLOAD.UPLOAD-SUCCESS'), SnackBarNotificationLevel.Success);
this.router.navigate(['/reload']).then(() => this.isPublic ? this.router.navigate(['/explore-plans']) : this.router.navigate(['/plans']));
}
private onCallbackImportFail(error: any) {
this.uiNotificationService.snackBarNotification(error.message, SnackBarNotificationLevel.Error);
}
openFiltersDialog(): void {
const dialogRef = this.dialog.open(DmpCriteriaDialogComponent, {
width: '456px',
height: '100%',
id: 'filters',
restoreFocus: false,
data: {
showGrant: this.showGrant,
isPublic: this.isPublic,
criteria: this.criteria,
formGroup: this.criteriaFormGroup,
// criteria: this.grantId ? this.criteria : this.getDefaultCriteria(),
updateDataFn: this.updateDataFn.bind(this)
},
position: { right: '0px;' },
panelClass: 'dialog-side-panel',
// may remove NgDialogAnimationService package
// animation: {
// to: "left",
// incomingOptions: {
// keyframeAnimationOptions: { duration: 300, easing: "ease-in-out" }
// }
// }
});
dialogRef.afterClosed().subscribe(result => {
});
}
updateDataFn(criteria: DmpCriteriaComponent): void {
this.criteriaFormGroup = criteria.formGroup;
this.toDmpCriteria(criteria);
this.refresh();
}
toDmpCriteria(criteria: DmpCriteriaComponent): void {
let formGroup = criteria.formGroup;
this.criteria = {
like: formGroup.get('like').value,
grants: formGroup.get('grants').value,
role: formGroup.get('role').value
}
this.criteria.status = formGroup.get('status').value;
this.setPublicCriteria(formGroup);
if (formGroup.get('datasetTemplates').value)
this.criteria.datasetTemplates = formGroup.get('datasetTemplates').value.map(x => x.id);
if (formGroup.get('collaborators').value)
this.criteria.collaborators = formGroup.get('collaborators').value.map(x => x.id);
if (formGroup.get('organisations').value)
this.criteria.organisations = formGroup.get('organisations').value.map(x => x.id);
if (this.itemId) {
this.criteria.groupIds = [this.itemId];
this.criteria.allVersions = true;
}
this.criteria.grantStatus = formGroup.get('grantStatus').value;
}
setPublicCriteria(formGroup?: FormGroup): void {
if (!isNullOrUndefined(formGroup)) {
if (formGroup.get('status').value == 2) {
this.criteria.status = 1;
this.criteria.isPublic = true;
} else {
this.criteria.isPublic = false;
}
}
this.criteria.onlyPublic = this.isPublic;
if (this.isPublic) {
this.criteria.isPublic = true;
}
// } else {
// this.criteria.isPublic = false;
// }
}
hasScrollbar(): boolean {
return document.getElementById("main-page").scrollHeight > document.documentElement.clientHeight
}
private mergeTwoSortedLists(arr1: DmpListingModel[], arr2: DmpListingModel[], order: string): DmpListingModel[] {
let merged = [];
let index1 = 0;
let index2 = 0;
let current = 0;
while (current < (arr1.length + arr2.length)) {
let isArr1Depleted = index1 >= arr1.length;
let isArr2Depleted = index2 >= arr2.length;
if (order === 'modified') {
if (!isArr1Depleted && (isArr2Depleted || (new Date(arr1[index1].modifiedTime) > new Date(arr2[index2].modifiedTime)))) {
merged[current] = arr1[index1];
index1++;
} else {
merged[current] = arr2[index2];
index2++;
}
} else if (order === 'created') {
if (!isArr1Depleted && (isArr2Depleted || (new Date(arr1[index1].creationTime) > new Date(arr2[index2].creationTime)))) {
merged[current] = arr1[index1];
index1++;
} else {
merged[current] = arr2[index2];
index2++;
}
} else if (order === 'label') {
if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].label.localeCompare(arr2[index2].label)))) {
merged[current] = arr1[index1];
index1++;
} else {
merged[current] = arr2[index2];
index2++;
}
} else if (order === 'status') {
if (!isArr1Depleted && (isArr2Depleted || (arr1[index1].status < arr2[index2].status))) {
merged[current] = arr1[index1];
index1++;
} else {
merged[current] = arr2[index2];
index2++;
}
} else if (order === "publishedAt") {
if (!isArr1Depleted && (isArr2Depleted || (new Date(arr1[index1].publishedAt) > new Date(arr2[index2].publishedAt)))) {
merged[current] = arr1[index1];
index1++;
} else {
merged[current] = arr2[index2];
index2++;
}
}
current++;
}
return merged;
}
public setDashboardTourDmpText(): void {
this.dmpText = this.language.instant('DMP-LISTING.TEXT-INFO') + '\n\n' +
this.language.instant('DMP-LISTING.TEXT-INFO-QUESTION') + ' ' +
this.language.instant('DMP-LISTING.LINK-ZENODO') + ' ' +
this.language.instant('DMP-LISTING.GET-IDEA');
this.dashboardTour.steps[0].title = this.dmpText;
}
public setDashboardTourDatasetText(): void {
this.datasetText = this.language.instant('DATASET-LISTING.TEXT-INFO') +
this.language.instant('DATASET-LISTING.LINK-PUBLIC-DATASETS') + ' ' +
this.language.instant('DATASET-LISTING.TEXT-INFO-REST') + '\n\n' +
this.language.instant('DATASET-LISTING.TEXT-INFO-PAR');
this.dashboardTour.steps[1].title = this.datasetText;
}
public restartTour(): void {
this.setDashboardTourDmpText();
this.setDashboardTourDatasetText();
this.guidedTourService.startTour(this.dashboardTour);
}
public hasLikeCriteria(): boolean {
return this.criteria.like !== undefined && this.criteria.like !== null;
}
}
// export class DmpDataSource extends DataSource<DmpListingModel> {
// totalCount = 0;
// constructor(
// private _service: DmpService,
// private _paginator: MatPaginator,
// private _sort: MatSort,
// private _criteria: DmpCriteriaComponent,
// private itemId
// ) {
// super();
// }
// connect(): Observable<DmpListingModel[]> {
// const displayDataChanges = [
// this._paginator.page
// ];
// return Observable.merge(...displayDataChanges)
// .startWith(null)
// .switchMap(() => {
// const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
// let fields: Array<string> = new Array();
// if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; }
// const request = new DataTableRequest<DmpCriteria>(startIndex, this._paginator.pageSize, { fields: fields });
// request.criteria = this._criteria.formGroup.value;
// if (this.itemId) {
// request.criteria.groupIds = [this.itemId];
// request.criteria.allVersions = true;
// }
// return this._service.getPaged(request, "listing");
// })
// /*.catch((error: any) => {
// this._snackBar.openFromComponent(SnackBarNotificationComponent, {
// data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService },
// duration: 3000,
// extraClasses: ['snackbar-warning']
// });
// return Observable.of(null);
// })*/
// .map(result => {
// result.data = result.data;
// return result;
// })
// .map(result => {
// return result;
// })
// .map(result => {
// if (!result) { return []; }
// if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; }
// return result.data.map(item => {
// item['datasets'].map(dmp => {
// dmp.url = 'datasets/edit/' + dmp.url;
// dmp.all = 'datasets/dmp/' + item.id;
// return dmp;
// });
// return item;
// });
// });
// }
// disconnect() {
// }
// }