import { SlickDataView, SlickGrid, SlickGroupTotals } from "slickgrid"; import { deleteDoubleQuotes, removeHtml } from "shared/lib/strings"; import { IColumn, IDownloadManager, ISlickRow, ISlickTable, } from "shared/model/types"; import { selectedRows } from "../../../lib"; /** Causes the circular dependencies issue */ const ignore = ["FormatterStatus", "FormatterNumber"]; // todo Use FORMATTER_NUMBER, FORMATTER_STATUS export class DownloadManager implements IDownloadManager { table: ISlickTable | null = null; download(table: ISlickTable, clientId: number, name: string) { if (!this.table) this.table = table; this.table = table; const grid = table.grid; if (!grid) return; const output = this.createCSV(table); const a = document.createElement("a"); a.href = "data:text/csv;charset=utf-8," + encodeURIComponent(output); a.target = "_blank"; a.download = `${clientId}-${name}-${table.id}.csv`; a.click(); } createCSV(table: ISlickTable): string { if (!this.table) this.table = table; const grid = table.grid; if (!grid) return ""; const title = this.getTitle(); const header = this.getCSVHeader(grid); const body = this.getCSVBody(grid); return `${title}${header}${body}`; } getTitle(): string { return ""; } getCSVHeader(grid: SlickGrid): string { const columns: IColumn[] = grid.getColumns(); const columnsForPrinting = columns.filter((el) => el.forPrint); const header = columnsForPrinting.reduce((acc: string, column) => { if (typeof column.name === "string") { const name = deleteDoubleQuotes(column.name); return acc.concat(`"${name}",`); } else { return acc.concat('" ",'); } }, ""); return this.addRowSeparator(header); } getCSVBody(grid: SlickGrid): string { const dataView: SlickDataView = grid.getData(); const columns: IColumn[] = grid.getColumns(); const columnsForPrinting = columns.filter((el) => el.forPrint); return selectedRows(grid).reduce((acc: string, rowIndex) => { const metaData = dataView.getItemMetadata(rowIndex); const row = dataView.getItem(rowIndex); const isGroupTitle = row.__group; const isGroupTotal = row.__groupTotals; let csvRow = ""; if (isGroupTitle) { const valueWithoutQuotes = deleteDoubleQuotes(removeHtml(row.title)); csvRow += `"${valueWithoutQuotes}",`; } else { for (let i = 0; i < columnsForPrinting.length; ++i) { const column = columnsForPrinting[i]; const field = column.field; const formatterSpecific = metaData?.columns?.[field]?.formatter; const formatter = column.printer || formatterSpecific || column.formatter; let value = row[field]; if (isGroupTotal) { const totalsFormatter = column.groupTotalsFormatter; value = totalsFormatter ? totalsFormatter( row as unknown as SlickGroupTotals, column, grid, ) : ""; } else { if (formatter && !ignore.includes(formatter.name)) { value = formatter(0, 0, value, column, row, grid); } } const valueWithoutQuotes = deleteDoubleQuotes(value); csvRow += `"${valueWithoutQuotes}",`; } } return this.addRowSeparator(`${acc}${csvRow}`); }, ""); } addRowSeparator(str: string): string { return `${str}\n`; } }