import { DataSource } from '@angular/cdk/table'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Component, OnInit, ViewChild } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { MatPaginator, PageEvent } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { DatasetStatus } from '@app/core/common/enum/dataset-status'; import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; import { DatasetListingModel } from '@app/core/model/dataset/dataset-listing'; import { DmpModel } from '@app/core/model/dmp/dmp'; import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; import { DmpService } from '@app/core/services/dmp/dmp.service'; import { MatomoService } from '@app/core/services/matomo/matomo-service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { DatasetProfileCriteriaComponent } from '@app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component'; import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; import { BaseComponent } from '@common/base/base.component'; import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; import { TranslateService } from '@ngx-translate/core'; import * as FileSaver from 'file-saver'; import { merge as observableMerge, Observable, of as observableOf } from 'rxjs'; import { map, startWith, switchMap, takeUntil } from 'rxjs/operators'; import { DialogConfirmationUploadDatasetProfiles } from './criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; @Component({ selector: 'app-dataset-profile-listing-component', templateUrl: 'dataset-profile-listing.component.html', styleUrls: ['./dataset-profile-listing.component.scss'] }) export class DatasetProfileListingComponent extends BaseComponent implements OnInit { @ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator; @ViewChild(MatSort, { static: true }) sort: MatSort; @ViewChild(DatasetProfileCriteriaComponent, { static: true }) criteria: DatasetProfileCriteriaComponent; breadCrumbs: Observable; dataSource: DatasetDataSource | null; displayedColumns: String[] = ['label', 'description', 'created', 'status', 'actions']; pageEvent: PageEvent; titlePrefix: String; dmpId: String; itemId: string; datasetStatusEnum = DatasetStatus; constructor( private datasetService: DatasetProfileService, private router: Router, private route: ActivatedRoute, private dmpService: DmpService, private language: TranslateService, private uiNotificationService: UiNotificationService, private httpClient: HttpClient, private matomoService: MatomoService, private dialog: MatDialog, private datasetProfileService: DatasetProfileService, ) { super(); } ngOnInit() { this.matomoService.trackPageView('Admin: Dataset Templates'); this.route.params .pipe(takeUntil(this._destroyed)) .subscribe((params: Params) => { if (params['dmpId']) { this.dmpId = params['dmpId']; if (this.dmpId != null) { this.setDmpTitle(this.dmpId); } this.criteria.setCriteria(this.getDefaultCriteria()); this.refresh(); this.criteria.setRefreshCallback(() => this.refresh()); // this.breadCrumbs = Observable.of([{ // parentComponentName: null, // label: this.language.instant('NAV-BAR.DATASET-TEMPLATES'), // url: 'plans/edit/' + this.dmpId // }]); } else { this.itemId = params['groupId']; if (this.itemId) { const datasetProfileLabel = this.route.snapshot.queryParams.groupLabel; } this.criteria.setCriteria(this.getDefaultCriteria()); this.refresh(); this.criteria.setRefreshCallback(() => this.refresh()); this.breadCrumbs = observableOf([{ parentComponentName: null, label: this.language.instant('NAV-BAR.DATASET-TEMPLATES'), url: '/dataset-profiles' }]); } }); } setDmpTitle(dmpId: String) { this.dmpService.getSingle(dmpId).pipe(map(data => data as DmpModel)) .pipe(takeUntil(this._destroyed)) .subscribe(data => { this.titlePrefix = data.label; } ); } refresh() { this.dataSource = new DatasetDataSource(this.datasetService, this._paginator, this.sort, this.criteria, this.itemId); this._paginator.pageIndex = 0; } rowClick(rowId: String) { this.router.navigate(['dataset-profiles/' + rowId]); } getDefaultCriteria(): DatasetProfileCriteria { const defaultCriteria = new DatasetProfileCriteria(); return defaultCriteria; } clone(id: string) { this.router.navigate(['dataset-profiles/clone/' + id]); } newVersion(id: string, label: string) { this.router.navigate(['dataset-profiles/newversion/' + id]); } newVersionFromFile(id: string, label: string): void { const dialogRef = this.dialog.open(DialogConfirmationUploadDatasetProfiles, { width: '500px', restoreFocus: false, data: { message: this.language.instant('DATASET-WIZARD.NEW-VERSION-FROM-FILE.NEW-VERSION-XML-FILE-TITLE', {datasetName: label}), confirmButton: this.language.instant('DATASET-WIZARD.NEW-VERSION-FROM-FILE.NEW-VERSION-XML'), cancelButton: this.language.instant('DATASET-WIZARD.NEW-VERSION-FROM-FILE.NEW-VERSION-XML-FILE-CANCEL'), name: "", file: FileList, sucsess: false } }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(data => { if (data && data.sucsess && data.name != null && data.file != null) { this.datasetService.uploadFile(data.file, data.name, id) .pipe(takeUntil(this._destroyed)) .subscribe(_=>{ this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-WIZARD.NEW-VERSION-FROM-FILE.NEW-VERSION-XML-SUCCESSFUL'), SnackBarNotificationLevel.Success); this.refresh(); }, error=>{ this.uiNotificationService.snackBarNotification(error.message, SnackBarNotificationLevel.Error); } ); } }); } viewVersions(rowId, rowLabel) { this.router.navigate(['/dataset-profiles/versions/' + rowId], { queryParams: { groupLabel: rowLabel } }); } downloadXML(datasetProfileId: string): void { this.datasetProfileService.downloadXML(datasetProfileId) .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); }); } 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; } deleteTemplate(id: string){ if(id){ const dialogRef = this.dialog.open(ConfirmationDialogComponent, { restoreFocus: false, data: { message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), isDeleteConfirmation: true } }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { if (result) { //this.form.get('status').setValue(DatasetProfileEnum.DELETED); this.datasetProfileService.delete(id, null) .pipe(takeUntil(this._destroyed)) .subscribe( complete => { this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Success); this.refresh(); }, error => { this.onCallbackError(error); if (error.error.statusCode == 674) { this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Error); } else { this.uiNotificationService.snackBarNotification(this.language.instant(error.message), SnackBarNotificationLevel.Error); } } ); } }); } } onCallbackError(errorResponse: HttpErrorResponse) { this.uiNotificationService.snackBarNotification(errorResponse.message, SnackBarNotificationLevel.Warning); } // makeItPublic(id: String) { // debugger; // this.datasetService.makeDatasetPublic(id).pipe(takeUntil(this._destroyed)).subscribe(); // } openDialog(): void { const dialogRef = this.dialog.open(DialogConfirmationUploadDatasetProfiles, { width: '500px', restoreFocus: false, data: { message: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML-FILE-TITLE'), confirmButton: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML'), cancelButton: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML-FILE-CANCEL'), name: "", file: FileList, sucsess: false } }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(data => { if (data && data.sucsess && data.name != null && data.file != null) { this.datasetService.uploadFile(data.file, data.name) .pipe(takeUntil(this._destroyed)) .subscribe(_=>{ this.uiNotificationService.snackBarNotification('Template successfully uploaded', SnackBarNotificationLevel.Success); this.refresh(); }, error=>{ this.uiNotificationService.snackBarNotification(error.message, SnackBarNotificationLevel.Error); } ); } }); } /** * gets as a a pameter a number representing the status and returns the class that is applied * to status-chip */ getStatusClass(status: DatasetStatus):string{ if(status == DatasetStatus.Finalized){ return 'status-chip-finalized' } return 'status-chip-draft'; } } export class DatasetDataSource extends DataSource { totalCount = 0; constructor( private _service: DatasetProfileService, private _paginator: MatPaginator, private _sort: MatSort, private _criteria: DatasetProfileCriteriaComponent, private itemId ) { super(); } connect(): Observable { const displayDataChanges = [ this._paginator.page //this._sort.matSortChange ]; return observableMerge(...displayDataChanges).pipe( 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.criteria; request.criteria.finalized = false; if (this.itemId) { request.criteria.groupIds = [this.itemId]; request.criteria.allVersions = true; } return this._service.getPaged(request); }), /*.catch((error: any) => { this._snackBar.openFromComponent(SnackBarNotificationComponent, { data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService }, duration: 3000, extraClasses: ['snackbar-warning'] }); //this._criteria.criteria.onCallbackError(error); return Observable.of(null); })*/ map(result => { return result; }), map(result => { if (!result) { return []; } // if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } this.totalCount = result.totalCount; return result.data; })); } disconnect() { // No-op } }