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.

170 lines (167 loc) 7.16 kB
import { ReportType, LoadType } from '../../types/UserReports.js'; import { FilterType } from '../_filters/filter-input/enum.js'; import { ReportQuery } from '../../types/ReportQuery.js'; import DefinitionUtils from '../../utils/definitionUtils.js'; import { ErrorHandler } from '../../utils/ErrorHandler/ErrorHandler.js'; import localsHelper from '../../utils/localsHelper.js'; import { createDashboardSections } from './dashboard-section/utils.js'; import DataPresentation from './DataPresentation.js'; class Dashboard extends DataPresentation { sections; dashboardData; parentChildData = []; partialDate; dashboardFeatureFlags; constructor(services, res, req, definition, loadType, requestData) { super(services, res, req, definition, loadType, ReportType.DASHBOARD, requestData); this.dashboardFeatureFlags = res.app.locals['featureFlags'].flags; } build = async () => { const reportMeta = this.buildReportMeta(ReportType.DASHBOARD); this.buildDashboardDetails(); await this.buildFilters(); await this.buildSavedDefaultsConfig(); this.buildAppliedFilters(); this.buildReportQuery(); await this.getData(); if (this.expired) { return { expired: this.expired, }; } this.buildSections(); await this.buildActions(ReportType.DASHBOARD); return { dashboardData: { ...reportMeta, ...this.reportDetails, sections: this.sections, filters: this.filterData, appliedFilters: this.appliedFilters, ...this.savedDefaultsConfig, ...this.actions, ...(this.extractedRequestData && this.extractedRequestData), }, }; }; /** * Gets all the report data * */ getData = async () => { try { await this.getDashboardData(); } catch (error) { const dprError = new ErrorHandler(error).formatError(); if (dprError.status === 404) { this.expired = true; } else { throw error; } } }; /** * Gets the dashboard data */ getDashboardData = async () => { this.dashboardData = this.loadType === LoadType.SYNC ? await this.getSyncData() : await this.getAsyncData(); await this.setParentChildData(); }; getAsyncData = async () => { const dashboardQueryRecord = this.reportQuery.toRecordWithFilterPrefix(true); const dashboardResultData = await this.services.dashboardService.getAsyncDashboard(this.token, this.reportId, this.id, this.tableId, dashboardQueryRecord); return Array.isArray(dashboardResultData) ? dashboardResultData.flat().filter(Boolean) : []; }; getSyncData = async () => { const reportQueryRecord = this.reportQuery.toRecordWithFilterPrefix(true); const dashboardData = await this.services.dashboardService.getSyncDashboard(this.token, this.id, this.reportId, reportQueryRecord); return Array.isArray(dashboardData) ? dashboardData.flat().filter(Boolean) : []; }; setParentChildData = async () => { // Get the child data, if applicable const childVariants = this.definition?.childVariants; this.parentChildData = !childVariants ? [] : await this.getParentChildData(childVariants, this.services, this.token, this.req, this.res, this.requestData); }; /** * Gets the parent and child data for a parent child dashboard, returns in a single array with the parent data first, followed by the child data * NOTE: Only available for Async * */ getParentChildData = async (childVariants, services, token, req, res, requestData) => { const { definitionsPath: dataProductDefinitionsPath } = localsHelper.getValues(res); const { reportId } = req.params; const childExecutionData = requestData?.childExecutionData; if (!childExecutionData) { throw new Error('getParentChildData: No execution data found for child variants'); } const allChildData = await Promise.all(childVariants.map(async (childVariant) => { const query = new ReportQuery({ fields: this.fields || [], template: 'parent-child', queryParams: req.query, definitionsPath: dataProductDefinitionsPath, }).toRecordWithFilterPrefix(true); const childData = childExecutionData.find(e => e.variantId === childVariant.id); if (!childData || !childData.tableId) { throw new Error('getParentChildData: No matching child execution data found'); } const { tableId: childTableId } = childData; const childDashboard = await services.dashboardService.getAsyncDashboard(token, reportId, childVariant.id, childTableId, query); return { id: childVariant.id, data: childDashboard.flat().filter(Boolean), }; })); const parentData = { id: this.definition.id, data: this.dashboardData }; return [parentData, ...allChildData]; }; /** * Gets the relevant report details from the report definition * */ buildDashboardDetails = async () => { const { definitionsPath } = localsHelper.getValues(this.res); const reportDefinition = this.res.locals['reportDefinitionSummary'] ?? (await DefinitionUtils.getReportSummary(this.reportId, this.services.reportingService, this.token, definitionsPath)); const { name, description } = this.definition; this.reportDetails = { reportName: reportDefinition.name, name, description: description || reportDefinition.description || '', printable: false, fields: this.fields ?? [], }; }; buildSections = () => { this.sections = createDashboardSections(this.definition, this.dashboardData, this.parentChildData, this.reportQuery.toRecordWithFilterPrefix(true), this.dashboardFeatureFlags, this.partialDate); }; buildPartialDate = () => { let partialDate; const granularDateRangeFilter = (this.filterData.find(f => f.type === FilterType.granularDateRange.toLowerCase())); if (granularDateRangeFilter) { partialDate = granularDateRangeFilter.value.partialDate; } this.partialDate = partialDate; }; /** * Builds the report query */ buildReportQuery = () => { const { definitionsPath } = localsHelper.getValues(this.res); const queryParams = { ...this.getCurrentQuery(), }; this.reportQuery = new ReportQuery({ fields: this.fields ?? [], queryParams, definitionsPath, reportType: ReportType.DASHBOARD, }); }; } export { Dashboard as default }; //# sourceMappingURL=Dashboard.js.map