UNPKG

@ministryofjustice/hmpps-digital-prison-reporting-frontend

Version:

The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.

256 lines (255 loc) 9.86 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const urlHelper_1 = __importDefault(require("../urlHelper")); const DateMapper_1 = __importDefault(require("../DateMapper/DateMapper")); class DataTableBuilder { constructor(fields, sortData = false) { this.columns = []; this.reportSummaries = {}; // Sortable headers only this.reportQuery = null; this.currentQueryParams = null; this.dateMapper = new DateMapper_1.default(); this.fields = fields; this.sortData = sortData; } mapDate(isoDate) { if (!isoDate) return ''; return this.dateMapper.toDateString(isoDate, 'local-datetime-short-year'); } mapBoolean(value) { if (!value) return ''; return value.substring(0, 1).toUpperCase() + value.substring(1).toLowerCase(); } mapRow(rowData, extraClasses = '', overrideFields = []) { return this.fields .filter((f) => this.columns.includes(f.name)) .map((f) => { const overrideField = overrideFields.find((o) => o.name === f.name); const field = overrideField !== null && overrideField !== void 0 ? overrideField : f; return this.mapCell(field, rowData, extraClasses); }); } mapCell(field, rowData, extraClasses = '') { const text = this.mapCellValue(field, rowData[field.name]); let fieldFormat = 'string'; let classes = extraClasses; if (field.wordWrap) { classes += ` data-table-cell-wrap-${field.wordWrap.toLowerCase()}`; } if (field.header) { classes += ' govuk-table__header'; } if (field.type === 'double' || field.type === 'long') { fieldFormat = 'numeric'; } const isHtml = field.type === 'HTML'; const cell = { fieldName: field.name, ...(isHtml ? { html: text } : { text }), format: fieldFormat, classes: classes.trim(), }; return cell; } mapCellValue(field, cellData) { if (field.calculated) { return cellData; } switch (field.type) { case 'boolean': return this.mapBoolean(cellData); case 'date': case 'time': return this.mapDate(cellData); default: return cellData; } } mapHeader(disableSort = false, extraClasses = null) { return this.fields .filter((field) => this.columns.includes(field.name)) .map((f) => { if (this.reportQuery && !disableSort) { if (f.sortable) { let sortDirection = 'none'; let url = (0, urlHelper_1.default)(this.currentQueryParams, { sortColumn: f.name, sortedAsc: 'true', }); if (f.name === this.reportQuery.sortColumn) { sortDirection = this.reportQuery.sortedAsc ? 'ascending' : 'descending'; if (this.reportQuery.sortedAsc) { url = (0, urlHelper_1.default)(this.currentQueryParams, { sortColumn: f.name, sortedAsc: 'false', }); } } return { html: `<a ` + `data-column="${f.name}" ` + `class="data-table-header-button data-table-header-button-sort-${sortDirection}" ` + `href="${url}"` + `>${f.display}</a>`, classes: extraClasses, }; } } return { text: f.display, classes: extraClasses, }; }); } mapData(data) { const mappedHeaderSummary = this.mapSummary('table-header'); const mappedTableData = this.mergeCells(data.map((rowData) => this.mapRow(rowData))); const mappedFooterSummary = this.mapSummary('table-footer'); return mappedHeaderSummary.concat(mappedTableData).concat(mappedFooterSummary); } mergeCells(rows) { const mergeFieldNames = this.fields.filter((f) => f.mergeRows).map((f) => f.name); if (mergeFieldNames.length === 0) { return rows; } const occurrences = {}; mergeFieldNames.forEach((f) => { occurrences[f] = rows.reduce((accumulator, currentRow) => { var _a, _b; const currentCell = this.getCellByFieldName(currentRow, f); const cellValue = (_a = currentCell.text) !== null && _a !== void 0 ? _a : currentCell.html; return { ...accumulator, [cellValue]: ((_b = accumulator[cellValue]) !== null && _b !== void 0 ? _b : 0) + 1, }; }, {}); }); return rows.map((row) => { let mergedRow = [...row]; mergeFieldNames.forEach((mergeFieldName) => { var _a; const currentRowCell = this.getCellByFieldName(row, mergeFieldName); const cellValue = (_a = currentRowCell.text) !== null && _a !== void 0 ? _a : currentRowCell.html; const occurrencesOfValue = occurrences[mergeFieldName][cellValue]; switch (occurrencesOfValue) { case -1: mergedRow = mergedRow.filter((c) => c.fieldName !== mergeFieldName); break; case 1: break; default: currentRowCell.rowspan = occurrencesOfValue; occurrences[mergeFieldName][cellValue] = -1; } }); return mergedRow; }); } getCellByFieldName(row, fieldName) { return row.find((c) => c.fieldName === fieldName); } mapSummary(template) { if (this.reportSummaries[template]) { return this.reportSummaries[template].flatMap((reportSummary) => reportSummary.data.map((rowData) => this.mapRow(rowData, `dpr-report-summary-cell dpr-report-summary-cell-${template}`, reportSummary.fields))); } return []; } sort(data) { return this.appendSortKeyToData(data) .sort(this.sortKeyComparison()) .map((d) => ({ ...d, })); } sortKeyComparison() { return (a, b) => { const aValue = a.sortKey; const bValue = b.sortKey; if (aValue === bValue) { return 0; } if (aValue < bValue) { return -1; } return 1; }; } appendSortKeyToData(data, fields = null) { const sortFields = fields || this.fields; return data.map((rowData) => { const sortKey = this.getSortKey(rowData, sortFields); return { ...rowData, sortKey, }; }); } mapNamesToFields(names) { return names.map((s) => this.fields.find((f) => f.name === s)); } getSortKey(rowData, sortFields) { return sortFields .map((f) => { const value = rowData[f.name]; if (value === null) { return 'zzzzzzzz'; } if (this.dateMapper.isDate(value)) { return this.dateMapper.toDateString(value, 'iso'); } return this.mapCellValue(f, value); }) .join('-') .toLowerCase(); } convertDataTableToHtml(dataTable) { const headers = dataTable.head.map((h) => { var _a; return `<th scope='col' class='govuk-table__header'>${(_a = h.html) !== null && _a !== void 0 ? _a : h.text}</th>`; }); const rows = dataTable.rows.map((r) => `<tr class='govuk-table__row'>${r .map((c) => { var _a; return `<td class='govuk-table__cell govuk-table__cell--${c.format} ${c.classes}'>${(_a = c.html) !== null && _a !== void 0 ? _a : c.text}</td>`; }) .join('')}</tr>`); return ("<table class='govuk-table'>" + `<thead class='govuk-table__head'>${headers.join('')}</thead>` + `<tbody class='govuk-table__body'>${rows.join('')}</tbody>` + '</table>'); } withHeaderOptions({ reportQuery, columns, interactive, }) { if (interactive) { return this.withHeaderSortOptions(reportQuery); } return this.withNoHeaderOptions(columns); } withHeaderSortOptions(reportQuery) { this.reportQuery = reportQuery; this.columns = reportQuery.columns; this.currentQueryParams = this.reportQuery.toRecordWithFilterPrefix(); return this; } withNoHeaderOptions(columns) { this.columns = columns; return this; } buildTable(data) { const mappedData = this.mapData(this.sortData ? this.sort(data) : data); return { head: this.mapHeader(), rows: mappedData, rowCount: data.length, colCount: this.columns.length, }; } withSummaries(reportSummaries) { this.reportSummaries = reportSummaries; return this; } withSortedData(sortData = true) { this.sortData = sortData; return this; } } exports.default = DataTableBuilder;