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.

139 lines (136 loc) 5.62 kB
import { setUnitOnValue, mapUnitToSymbol } from '../../../utils/Dashboards/VisualisationUnitHelper.js'; import { Buckets } from '../../_charts/chart/buckets/Buckets.js'; import DatasetHelper from '../../../utils/Dashboards/VisualisationDatasetHelper.js'; import ScorecardSchemas from './validate.js'; /* eslint-disable prefer-destructuring */ class ScorecardVisualisation { definition; id; measures; options; dataset; bucketsHelper; buckets = []; valueKey; titleColumn; responseData = []; ragColours = ['#cce2d8', '#fff7bf', '#f4cdc6']; trendSymbols = ['◼', '▲ Up', '▼ Down']; unit; withDefinition = (definition) => { this.definition = ScorecardSchemas.ScorecardSchema.parse(definition); this.init(); return this; }; withData = (responseData) => { this.responseData = responseData; this.dataset = this.getDataset(this.definition, this.responseData); this.initBuckets(this.responseData, this.valueKey); return this; }; init = () => { this.id = this.definition.id; this.measures = this.definition.columns.measures; this.options = this.definition.options; this.titleColumn = { display: this.definition.display, id: this.valueKey }; this.initFromMeasures(); }; initFromMeasures = () => { // Zod should throw an error on line 40 so should always pass if (this.measures[0] !== undefined) { this.valueKey = this.measures[0].id; this.unit = this.measures[0].unit; } }; initBuckets = (responseData, valueKey) => { if (this.options?.buckets || this.options?.useRagColour) { this.bucketsHelper = new Buckets(responseData, this.definition, valueKey, false, this.ragColours); this.buckets = this.bucketsHelper.getBuckets(); } }; getDataset = (definition, rawData) => { const scorecardDefinition = definition; const { columns } = scorecardDefinition; const dateColumn = DatasetHelper.getTimestampColumn(columns); // Latest most recent data const latestData = DatasetHelper.getLastestDataset(rawData, dateColumn); const latestDataSetRows = DatasetHelper.getDatasetRows(scorecardDefinition, latestData); let latestTs; const latestDateData = DatasetHelper.getDateValue(latestDataSetRows, dateColumn); if (latestDateData?.value) { latestTs = latestDateData.value; } const latestFiltered = DatasetHelper.filterRowsByDisplayColumns(scorecardDefinition, latestDataSetRows, true); // Earliest data const earliestData = DatasetHelper.getEarliestDataset(rawData, dateColumn); const earliestDataSetRows = DatasetHelper.getDatasetRows(scorecardDefinition, earliestData); let earliestTs; const earliestDateData = DatasetHelper.getDateValue(earliestDataSetRows, dateColumn); if (earliestDateData?.value) { earliestTs = earliestDateData.value; } const earliestfiltered = DatasetHelper.filterRowsByDisplayColumns(scorecardDefinition, earliestDataSetRows, true); return { earliest: earliestfiltered, earliestTs, latest: latestFiltered, latestTs, }; }; createScorecardData = ({ id, title, value, rag, valueFor, valueFrom, prevVal, groupTitle, unit, }) => { return { id, title, value: setUnitOnValue(value, mapUnitToSymbol(unit || this.unit), false), ...(rag && { rag }), valueFor, trend: this.createTrend(valueFor, valueFrom, value, prevVal), ...(groupTitle && { group: groupTitle, }), }; }; createTrend = (valueFor, valueFrom, latestValue, earliestValue, unit) => { let trendData; if (valueFrom !== valueFor) { const value = earliestValue ? Number(latestValue) - Number(earliestValue) : 0; const direction = this.trendSymbols[Math.sign(value)] || this.trendSymbols[2]; const diplayValue = setUnitOnValue(Math.abs(value), mapUnitToSymbol(unit || this.unit), false); trendData = { direction, value: diplayValue, from: valueFrom, }; } return trendData; }; setRagScore = (value, rag, buckets, bucketsHelper) => { let ragScore; if (!Number.isNaN(value) && buckets?.length && bucketsHelper) { ragScore = bucketsHelper.getBucketForValue(value, rag); } return ragScore; }; build = () => { const { latest, earliest, latestTs, earliestTs } = this.dataset; const scorecordArr = latest.map((datasetRow, index) => { const { raw: value, rag } = datasetRow[this.valueKey]; const prevVal = earliest[index][this.valueKey].raw; const valueFor = `${latestTs}`; const valueFrom = `${earliestTs}`; const title = this.titleColumn?.display; return this.createScorecardData({ id: this.id, title: title || '', value: value || '', rag: this.setRagScore(value, rag, this.buckets, this.bucketsHelper), prevVal, valueFor, valueFrom, }); }); return scorecordArr[0]; }; } export { ScorecardVisualisation, ScorecardVisualisation as default }; //# sourceMappingURL=Scorecard.js.map