@ministryofjustice/hmpps-digital-prison-reporting-frontend
Version:
The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.
189 lines (186 loc) • 6.63 kB
JavaScript
import DatasetHelper, { getTimestampColumn, getDateValue } from '../../../utils/Dashboards/VisualisationDatasetHelper.js';
import ListSchemas from './validate.js';
import { apiDateToUi } from '../../../utils/dateHelper.js';
const createList = (listDefinition, dashboardData) => {
ListSchemas.ListSchema.parse(listDefinition);
const { columns, options } = listDefinition;
const { measures, keys } = columns;
const listOptions = options;
const columnsAsList = listOptions?.columnsAsList;
const showAllData = (!measures && !keys) || (!measures.length && !keys);
let datasetData = [...dashboardData];
if (listOptions?.showLatest ?? true) {
const dateColumn = DatasetHelper.getTimestampColumn(columns);
datasetData = DatasetHelper.getLastestDataset(datasetData, dateColumn);
}
let head;
let rows;
let ts;
if (showAllData) {
({ head, rows, ts } = createFullList(listDefinition, datasetData));
}
else if (columnsAsList) {
({ head, rows, ts } = createListFromColumns(listDefinition, datasetData));
}
else {
({ head, rows, ts } = creatListFromRows(listDefinition, datasetData));
}
if (rows.length && measures)
rows = sumColumns(rows, measures);
return {
table: {
head,
rows,
},
ts,
};
};
const createListFromColumns = (listDefinition, dashboardData) => {
const { columns } = listDefinition;
const { keys, measures } = columns;
const groupKey = DatasetHelper.getGroupKey(dashboardData, keys || []);
const dateColumn = getTimestampColumn(columns);
const dateData = getDateValue(dashboardData, dateColumn);
const ts = dateData?.value ? `${dateData.value}` : '';
const head = [];
head.push({
html: '<p class="govuk-visually-hidden">list values</p>',
});
dashboardData.forEach(row => {
head.push({
text: groupKey ? `${row[groupKey.id].raw}` : '',
});
});
const rows = [];
measures.forEach(measure => {
rows.push([{ text: measure.display }]);
});
measures.forEach((measure, index) => {
dashboardData.forEach(row => {
rows[index].push({ text: `${row[measure.id].raw}` });
});
});
return {
rows,
head,
ts,
};
};
/**
* Creates the table rows for a dashboard list visualisation
* - If no measures are passed in it will present the full data
*
* @param {DashboardDataResponse[]} data
* @param {components['schemas']['DashboardVisualisationColumnDefinition'][]} [measures]
* @return {*} {MoJTableRow[][]}
*/
const createTableRows = (data, measures) => {
if (!data || data.length === 0 || !data[0]) {
return [];
}
// Set the list data using the measure
if (measures && measures.length) {
return data.map(dataRow => {
const row = Array.from({ length: measures.length }, () => ({ text: '' }));
Object.keys(dataRow).forEach(key => {
const headIndex = measures.findIndex(m => m.id === key);
if (headIndex === -1) {
return;
}
const measure = measures[headIndex];
const raw = dataRow[key]?.raw;
if (raw == null) {
return;
}
let cellContent = String(raw);
const { type } = measure;
if (type === 'date' || type === 'timestamp') {
cellContent = apiDateToUi(cellContent) || cellContent;
}
const cell = measure.type === 'HTML' ? { html: cellContent } : { text: cellContent };
row[headIndex] = cell;
});
return row;
});
}
// Return the data unfiltered by measures
return data.map(dataRow => {
const row = Array(Object.keys(data[0]).length);
Object.keys(dataRow).forEach((key, index) => {
const text = dataRow[key].raw;
row.splice(index, 1, { text });
});
return row;
});
};
const creatListFromRows = (listDefinition, dashboardData) => {
const { columns } = listDefinition;
const { measures } = columns;
const head = measures.map(column => {
return { text: column.display || '' };
});
const dataSetRows = DatasetHelper.getDatasetRows(listDefinition, dashboardData);
const displayRows = DatasetHelper.filterRowsByDisplayColumns(listDefinition, dataSetRows);
const rows = createTableRows(displayRows, measures);
const dateColumn = getTimestampColumn(columns);
const dateData = getDateValue(dataSetRows, dateColumn);
const ts = dateData?.value ? `${dateData.value}` : '';
return {
head,
rows,
ts,
};
};
const createFullList = (listDefinition, dashboardData) => {
if (!dashboardData || dashboardData.length === 0 || !dashboardData[0]) {
return {
head: [],
rows: [],
ts: '',
};
}
const { columns } = listDefinition;
const firstRow = dashboardData[0];
const head = Object.keys(firstRow).map(key => {
return { text: key || '' };
});
const rows = createTableRows(dashboardData);
const dateColumn = getTimestampColumn(columns);
const latestData = DatasetHelper.getLastestDataset(dashboardData, dateColumn);
const dateData = getDateValue(latestData, dateColumn);
const ts = dateData?.value ? `${dateData.value}` : '';
return {
head,
rows,
ts,
};
};
const sumColumns = (rowsData, measures) => {
const sumColumnIndexes = measures.flatMap((col, idx) => (col.aggregate ? [idx] : []));
if (sumColumnIndexes.length) {
const sumRow = [{ html: `<strong>Total<strong>` }];
for (let index = 1; index < measures.length; index += 1) {
sumRow[index] = { text: '' };
}
rowsData.push(sumRow);
sumColumnIndexes.forEach(index => {
const total = rowsData.reduce((acc, row) => {
const rowIndex = row[index];
if (rowIndex && rowIndex.text) {
acc += Number(rowIndex.text);
}
return acc;
}, 0);
rowsData[rowsData.length - 1][index] = {
html: `<strong>${total}<strong>`,
};
});
}
return rowsData;
};
var DashboardListUtils = {
createList,
createTableRows,
};
export { createList, createTableRows, DashboardListUtils as default };
//# sourceMappingURL=utils.js.map