import type { IWebApiClient, WebClientApiMethod } from '../../common/IWebClient'; import type { DataTableExportConfig, TableColumn } from './datatable'; import { toNative } from 'vue-facing-decorator'; import PowerduckState from '../../app/powerduck-state'; import TsxComponent, { Component } from '../../app/vuetsx'; import { ExcelJsProvider } from '../../common/excel/excel-js-provider'; import { PortalUtils } from '../../common/utils/utils'; import LoadingIndicator from '../loading-indicator'; import Modal from '../modal/modal'; import ModalBody from '../modal/modal-body'; import NotificationProvider from '../ui/notification'; interface TableExportModalBindingArgs { } interface TableExportModalArgs { columns: TableColumn[]; rows: any[]; apiClient: IWebApiClient; apiMethod: WebClientApiMethod; apiArgs?: any; exportConfig: DataTableExportConfig; paginationOffset?: number; paginationLength: number; totalFilteredCount: number; } const enum TableExportPhase { RecordsetSelection = 0, Loading = 1, } @Component class TableExportModalComponent extends TsxComponent implements TableExportModalBindingArgs { columns: TableColumn[] = null; phase: TableExportPhase = null; rows: any[] = null; excelJsLoaded: boolean = false; dataLoaded: boolean = false; totalFilteredCount: number = null; downloadedCount: number = null; show(args: TableExportModalArgs) { this.columns = args.columns; this.rows = args.rows; this.phase = TableExportPhase.RecordsetSelection; this.excelJsLoaded = ExcelJsProvider.excelJsInstance() != null; this.dataLoaded = (this.rows || []).length >= args.totalFilteredCount; this.totalFilteredCount = args.totalFilteredCount; (this.$refs.tableExportDialog as typeof Modal.prototype).show(); if (!this.excelJsLoaded) { ExcelJsProvider.getExcelJs().then((excelJs) => { this.excelJsLoaded = true; this.exportExcel(); }).catch((err) => { NotificationProvider.showErrorMessage(err); this.hideExportModal(); }); } if (!this.dataLoaded) { this.rows = []; this.downloadedCount = 0; this.downloadDataChunk( args.apiClient, args.apiMethod, args.apiArgs, 0, args.paginationLength, args.exportConfig, ); this.exportExcel(); } this.exportExcel(); } downloadDataChunk( apiClient: IWebApiClient, apiMethod: WebClientApiMethod, ajaxArgs: any, steps: number, paginationLength: number, exportConfig?: DataTableExportConfig, ): void { const STEP_COUNT = 1000; ajaxArgs.PaginationPosition = steps + 1; ajaxArgs.PaginationLength = STEP_COUNT; if (exportConfig != null) { if (exportConfig.limitName != null) { ajaxArgs[exportConfig.limitName] = STEP_COUNT; } if (exportConfig.pageName != null) { ajaxArgs[exportConfig.pageName] = steps + 1; } } apiClient[apiMethod](ajaxArgs).then((data: any) => { const attrName = exportConfig != null && exportConfig.attrName != null ? exportConfig.attrName : 'Rows'; const rows = data[attrName]; rows.forEach((row) => { this.rows.push(row); }); this.downloadedCount += rows.length; if (rows.length < STEP_COUNT) { this.totalFilteredCount = this.downloadedCount; this.dataLoaded = true; this.exportExcel(); } else { this.downloadDataChunk( apiClient, apiMethod, ajaxArgs, steps + 1, paginationLength, exportConfig, ); } }).catch(() => { NotificationProvider.showErrorMessage(PowerduckState.getResourceValue('errorFetchingData')); this.hideExportModal(); }); } hideExportModal() { (this.$refs.tableExportDialog as typeof Modal.prototype).hide(); } exportExcel() { if (this.dataLoaded && this.excelJsLoaded) { const colArr = []; this.columns.forEach((item) => { if (item.exportInclude != false) { colArr.push({ header: item.caption, width: 25, }); } }); const workbook = new (ExcelJsProvider.excelJsInstance()).Workbook(); // eslint-disable-next-line no-restricted-syntax workbook.created = new Date(); // eslint-disable-next-line no-restricted-syntax workbook.modified = new Date(); // eslint-disable-next-line no-restricted-syntax workbook.lastPrinted = new Date(); const worksheet = workbook.addWorksheet('Export'); worksheet.columns = colArr; worksheet.views = [{ state: 'frozen', xSplit: 0, ySplit: 1 }]; const firstRow = worksheet.getRow(1); firstRow.font = { name: 'Arial', family: 4, size: 10, bold: true, color: { argb: '00000000' }, bgColor: { argb: '80EF1C1C' } }; firstRow.alignment = { vertical: 'middle', horizontal: 'center' }; firstRow.height = 20; firstRow._cells.forEach((cell) => { cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'cccccc' }, }; }); this.rows.forEach((row) => { const rowExportData = []; this.columns.forEach((col) => { if (col.exportInclude != false) { if (col.exportValue != null) { rowExportData.push(col.exportValue(row)); } else if (col.customValue != null) { rowExportData.push(col.customValue(row)); } else { rowExportData.push(row[col.id]); } } }); const addedRow = worksheet.addRow(rowExportData); addedRow.eachCell((cell) => { if (cell.value instanceof Date) { cell.numFmt = 'dd/mm/yyyy hh:mm:ss'; } }); }); workbook.xlsx.writeBuffer().then((data: any) => { const blob = new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); PortalUtils.downloadBlob( blob, 'export.xlsx', () => { setTimeout(() => { this.hideExportModal(); }, 300); }, ); }).catch((err) => { console.error(err); }); } } getCompletePercent() { return `${Math.round((this.downloadedCount / this.totalFilteredCount) * 100)} %`; } render(h) { return (

{this.getCompletePercent()}

); } } const TableExportModal = toNative(TableExportModalComponent); export default TableExportModal;