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 = 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 = 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 = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; this.startIndex = 0; const request = new DataTableRequest(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 = ["-modified"]; const fields: Array = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; const request = new DataTableRequest(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 { // totalCount = 0; // constructor( // private _service: DmpService, // private _paginator: MatPaginator, // private _sort: MatSort, // private _criteria: DmpCriteriaComponent, // private itemId // ) { // super(); // } // connect(): Observable { // const displayDataChanges = [ // this._paginator.page // ]; // return Observable.merge(...displayDataChanges) // .startWith(null) // .switchMap(() => { // 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 }); // 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() { // } // }