@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
JavaScript
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