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