argos/dmp-frontend/src/app/ui/admin/description-template/listing/description-template-listin...

427 lines
16 KiB
TypeScript

import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router } from '@angular/router';
import { IsActive } from '@app/core/common/enum/is-active.enum';
import { DescriptionTemplate } from '@app/core/model/description-template/description-template';
import { AuthService } from '@app/core/services/auth/auth.service';
import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { FileUtils } from '@app/core/services/utilities/file-utils.service';
import { QueryParamsService } from '@app/core/services/utilities/query-params.service';
import { BaseListingComponent } from '@common/base/base-listing-component';
import { PipeService } from '@common/formatting/pipe.service';
import { DataTableDateTimeFormatPipe } from '@common/formatting/pipes/date-time-format.pipe';
import { QueryResult } from '@common/model/query-result';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
import { ColumnDefinition, ColumnsChangedEvent, HybridListingComponent, PageLoadEvent } from '@common/modules/hybrid-listing/hybrid-listing.component';
import { Guid } from '@common/types/guid';
import { TranslateService } from '@ngx-translate/core';
import * as FileSaver from 'file-saver';
import { Observable } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof';
import { ImportDescriptionTemplateDialogComponent } from './import-description-template/import-description-template.dialog.component';
import { DescriptionTemplateService } from '@app/core/services/description-template/description-template.service';
import { DescriptionTemplateStatus } from '@app/core/common/enum/description-template-status';
import { DescriptionTemplateLookup } from '@app/core/query/description-template.lookup';
import { IsActiveTypePipe } from '@common/formatting/pipes/is-active-type.pipe';
import { DescriptionTemplateVersionStatus } from '@app/core/common/enum/description-template-version-status';
@Component({
selector: 'app-description-template-listing-component',
templateUrl: './description-template-listing.component.html',
styleUrls: ['./description-template-listing.component.scss']
})
export class DescriptionTemplateListingComponent extends BaseListingComponent<DescriptionTemplate, DescriptionTemplateLookup> implements OnInit {
publish = false;
userSettingsKey = { key: 'DescriptionTemplateListingUserSettings' };
propertiesAvailableForOrder: ColumnDefinition[];
descriptionTemplateStatuses = DescriptionTemplateStatus;
mode;
@ViewChild('descriptionTemplateStatus', { static: true }) descriptionTemplateStatus?: TemplateRef<any>;
@ViewChild('actions', { static: true }) actions?: TemplateRef<any>;
@ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent;
private readonly lookupFields: string[] = [
nameof<DescriptionTemplate>(x => x.id),
nameof<DescriptionTemplate>(x => x.label),
nameof<DescriptionTemplate>(x => x.description),
nameof<DescriptionTemplate>(x => x.status),
nameof<DescriptionTemplate>(x => x.version),
nameof<DescriptionTemplate>(x => x.groupId),
nameof<DescriptionTemplate>(x => x.updatedAt),
nameof<DescriptionTemplate>(x => x.createdAt),
nameof<DescriptionTemplate>(x => x.hash),
nameof<DescriptionTemplate>(x => x.belongsToCurrentTenant),
nameof<DescriptionTemplate>(x => x.isActive)
];
rowIdentity = x => x.id;
constructor(
protected router: Router,
protected route: ActivatedRoute,
protected uiNotificationService: UiNotificationService,
protected httpErrorHandlingService: HttpErrorHandlingService,
protected queryParamsService: QueryParamsService,
private descriptionTemplateService: DescriptionTemplateService,
public authService: AuthService,
private matomoService: MatomoService,
private pipeService: PipeService,
public enumUtils: EnumUtils,
private language: TranslateService,
private dialog: MatDialog,
private fileUtils: FileUtils
) {
super(router, route, uiNotificationService, httpErrorHandlingService, queryParamsService);
// Lookup setup
// Default lookup values are defined in the user settings class.
this.mode = this.route.snapshot?.data['mode'];
this.lookup = this.initializeLookup();
}
ngOnInit() {
this.matomoService.trackPageView('Admin: DMP Templates');
super.ngOnInit();
}
protected initializeLookup(): DescriptionTemplateLookup {
const lookup = new DescriptionTemplateLookup();
lookup.metadata = { countAll: true };
lookup.page = { offset: 0, size: this.ITEMS_PER_PAGE };
lookup.isActive = [IsActive.Active];
lookup.order = { items: [this.toDescSortField(nameof<DescriptionTemplate>(x => x.createdAt))] };
if (this.mode && this.mode == 'versions-listing') {
lookup.groupIds = [Guid.parse(this.route.snapshot.paramMap.get('groupid'))];
lookup.versionStatuses = null;
}else{
lookup.versionStatuses = [DescriptionTemplateVersionStatus.Current, DescriptionTemplateVersionStatus.NotFinalized];
}
this.updateOrderUiFields(lookup.order);
lookup.project = {
fields: this.lookupFields
};
return lookup;
}
protected setupColumns() {
this.gridColumns.push(...[{
prop: nameof<DescriptionTemplate>(x => x.label),
sortable: true,
languageName: 'DESCRIPTION-TEMPLATE-LISTING.FIELDS.NAME'
},
{
prop: nameof<DescriptionTemplate>(x => x.description),
sortable: true,
languageName: 'DESCRIPTION-TEMPLATE-LISTING.FIELDS.DESCRIPTION'
},
{
prop: nameof<DescriptionTemplate>(x => x.status),
sortable: true,
languageName: 'DESCRIPTION-TEMPLATE-LISTING.FIELDS.STATUS',
cellTemplate: this.descriptionTemplateStatus
},
{
prop: nameof<DescriptionTemplate>(x => x.version),
sortable: true,
languageName: 'DESCRIPTION-TEMPLATE-LISTING.FIELDS.VERSION'
},
{
prop: nameof<DescriptionTemplate>(x => x.createdAt),
sortable: true,
languageName: 'DESCRIPTION-TEMPLATE-LISTING.FIELDS.CREATED-AT',
pipe: this.pipeService.getPipe<DataTableDateTimeFormatPipe>(DataTableDateTimeFormatPipe).withFormat('short')
},
{
prop: nameof<DescriptionTemplate>(x => x.updatedAt),
sortable: true,
languageName: 'DESCRIPTION-TEMPLATE-LISTING.FIELDS.UPDATED-AT',
pipe: this.pipeService.getPipe<DataTableDateTimeFormatPipe>(DataTableDateTimeFormatPipe).withFormat('short')
},
{
prop: nameof<DescriptionTemplate>(x => x.isActive),
sortable: true,
languageName: 'DESCRIPTION-TEMPLATE-LISTING.FIELDS.IS-ACTIVE',
pipe: this.pipeService.getPipe<IsActiveTypePipe>(IsActiveTypePipe)
},
{
alwaysShown: true,
cellTemplate: this.actions,
maxWidth: 120
}
]);
this.propertiesAvailableForOrder = this.gridColumns.filter(x => x.sortable);
}
//
// Listing Component functions
//
onColumnsChanged(event: ColumnsChangedEvent) {
super.onColumnsChanged(event);
this.onColumnsChangedInternal(event.properties.map(x => x.toString()));
}
private onColumnsChangedInternal(columns: string[]) {
// Here are defined the projection fields that always requested from the api.
const fields = new Set(this.lookupFields);
this.gridColumns.map(x => x.prop)
.filter(x => !columns?.includes(x as string))
.forEach(item => {
fields.delete(item as string)
});
this.lookup.project = { fields: [...fields] };
this.onPageLoad({ offset: 0 } as PageLoadEvent);
}
protected loadListing(): Observable<QueryResult<DescriptionTemplate>> {
return this.descriptionTemplateService.query(this.lookup);
}
public delete(id: Guid) {
if (id) {
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
data: {
isDeleteConfirmation: true,
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')
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
this.descriptionTemplateService.delete(id).pipe(takeUntil(this._destroyed))
.subscribe(
complete => this.onCallbackSuccess(),
error => this.onCallbackError(error)
);
}
});
}
}
onCallbackSuccess(): void {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DELETE'), SnackBarNotificationLevel.Success);
this.refresh();
}
export(id: Guid): void {
this.descriptionTemplateService.downloadXML(id)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], { type: 'application/xml' });
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
});
}
import(): void {
const dialogRef = this.dialog.open(ImportDescriptionTemplateDialogComponent, {
restoreFocus: false,
data: {
message: this.language.instant('DESCRIPTION-TEMPLATE-LISTING.IMPORT.UPLOAD-XML-FILE-TITLE'),
confirmButton: this.language.instant('DESCRIPTION-TEMPLATE-LISTING.IMPORT.UPLOAD-XML'),
cancelButton: this.language.instant('DESCRIPTION-TEMPLATE-LISTING.IMPORT.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.descriptionTemplateService.uploadFile(data.file, data.name)
.pipe(takeUntil(this._destroyed))
.subscribe(_ => {
this.uiNotificationService.snackBarNotification(this.language.instant('DESCRIPTION-TEMPLATE-LISTING.MESSAGES.TEMPLATE-UPLOAD-SUCCESS'), SnackBarNotificationLevel.Success);
this.refresh();
},
error => {
this.uiNotificationService.snackBarNotification(error.message, SnackBarNotificationLevel.Error);
});
}
});
}
}
// ngOnInit() {
// refresh() {
// this.dataSource = new DatasetDataSource(this.descriptionTemplateService, this._paginator, this.sort, this.criteria);
// }
// clone(id: string) {
// this.router.navigate(['description-templates/clone/' + id]);
// }
// rowClick(rowId: String) {
// this.router.navigate(['description-templates/' + rowId]);
// }
// downloadXML(descriptionTemplateId: string): void {
// this.descriptionTemplateService.downloadXML(descriptionTemplateId)
// .pipe(takeUntil(this._destroyed))
// .subscribe(response => {
// const blob = new Blob([response.body], { type: 'application/xml' });
// const filename = this.fileUtils.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
// FileSaver.saveAs(blob, filename);
// });
// }
// deleteTemplate(id: string) {
// if (id) {
// this.dialog.open(ConfirmationDialogComponent, {
// data: {
// isDeleteConfirmation: true,
// confirmButton: this.languageService.instant('DESCRIPTION-TEMPLATE-EDITOR.CONFIRM-DELETE-DIALOG.CONFIRM-BUTTON'),
// cancelButton: this.languageService.instant("DESCRIPTION-TEMPLATE-EDITOR.CONFIRM-DELETE-DIALOG.CANCEL-BUTTON"),
// message: this.languageService.instant("DESCRIPTION-TEMPLATE-EDITOR.CONFIRM-DELETE-DIALOG.MESSAGE")
// }
// })
// .afterClosed()
// .subscribe(
// confirmed => {
// if (confirmed) {
// this.descriptionTemplateService.delete(id)
// .pipe(takeUntil(this._destroyed))
// .subscribe(
// complete => {
// this.uiNotificationService.snackBarNotification(this.languageService.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DESCRIPTION-TEMPLATE-DELETE'), SnackBarNotificationLevel.Success);
// this.refresh();
// },
// error => {
// this.onCallbackError(error);
// if (error.error.statusCode == 674) {
// this.uiNotificationService.snackBarNotification(this.languageService.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DESCRIPTION-TEMPLATE-DELETE'), SnackBarNotificationLevel.Error);
// } else {
// this.uiNotificationService.snackBarNotification(this.languageService.instant(error.message), SnackBarNotificationLevel.Error);
// }
// }
// );
// }
// }
// )
// }
// }
// onCallbackError(errorResponse: HttpErrorResponse) {
// this.uiNotificationService.snackBarNotification(errorResponse.message, SnackBarNotificationLevel.Warning);
// }
// getDefaultCriteria(): DescriptionTemplateCriteria {
// const defaultCriteria = new DescriptionTemplateCriteria();
// return defaultCriteria;
// }
// // makeItPublic(id: String) {
// // debugger;
// // this.datasetService.makeDatasetPublic(id).pipe(takeUntil(this._destroyed)).subscribe();
// // }
// parseStatus(value: number): string {
// const stringVal = value.toString()
// try {
// return this.statuses.find(status => status.value === stringVal).viewValue;
// } catch {
// return stringVal;
// }
// }
// openDialog(): void {
// const dialogRef = this.dialog.open(DialodConfirmationUploadDescriptionTemplates, {
// restoreFocus: false,
// data: {
// message: this.languageService.instant('DESCRIPTION-TEMPLATE-LISTING.IMPORT.UPLOAD-XML-FILE-TITLE'),
// confirmButton: this.languageService.instant('DESCRIPTION-TEMPLATE-LISTING.IMPORT.UPLOAD-XML'),
// cancelButton: this.languageService.instant('DESCRIPTION-TEMPLATE-LISTING.IMPORT.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.descriptionTemplateService.uploadFile(data.file, data.name)
// .pipe(takeUntil(this._destroyed))
// .subscribe(_ => {
// this.uiNotificationService.snackBarNotification(this.languageService.instant('DESCRIPTION-TEMPLATE-LISTING.MESSAGES.TEMPLATE-UPLOAD-SUCCESS'), SnackBarNotificationLevel.Success);
// this.refresh();
// },
// error => {
// this.uiNotificationService.snackBarNotification(error.message, SnackBarNotificationLevel.Error);
// });
// }
// });
// }
// getStatusClass(status: number): string {
// if (status === 1) {//finalized
// return 'status-chip-finalized'
// }
// if (status === 0) {
// return 'status-chip-draft';
// }
// return '';
// }
// }
// export class DatasetDataSource extends DataSource<DescriptionTemplateListing> {
// totalCount = 0;
// constructor(
// private _service: descriptionTemplateService,
// private _paginator: MatPaginator,
// private _sort: MatSort,
// private _criteria: DescriptionTemplateCriteriaComponent
// ) {
// super();
// }
// connect(): Observable<DescriptionTemplateListing[]> {
// 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<string> = new Array();
// if (this._sort.active) { fields = this._sort.direction === 'asc' ? ['+' + this._sort.active] : ['-' + this._sort.active]; }
// const request = new DataTableRequest<DescriptionTemplateCriteria>(startIndex, this._paginator.pageSize, { fields: fields });
// request.criteria = this._criteria.criteria;
// return this._service.getPagedBlueprint(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; }
// return result.data;
// }));
// }
// disconnect() {
// // No-op
// }