@ministryofjustice/hmpps-digital-prison-reporting-frontend
Version:
The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.
86 lines (83 loc) • 3.67 kB
JavaScript
import { getFields, getDashboardFields, getFieldsWithFilters } from '../utils/definitionUtils.js';
import { buildFilterSchemaFromFields } from './buildFilterSchema.js';
import { extractFiltersFromBody, formBodyToQs } from '../utils/queryMappers.js';
import { joinQueryStrings } from '../utils/urlHelper.js';
import { getActiveJourneyValue } from '../utils/sessionHelper.js';
import { ReportType, LoadType } from '../types/UserReports.js';
/**
* Middleware to validate a report or dashboard filter request
*
* - creates a schema dynamically from the filter definitions
* - checks the form data against it
* - sets errors in req.flash if there are errors
* - and redirects back to current page
*
* @param {*} req
* @param {*} res
* @param {*} next
* @return {*}
*/
const validateFilters = ({ interactive, loadType = LoadType.ASYNC }) => (req, res, next) => {
const { type: reportType } = req.params;
const definition = res.locals.definition;
if (!definition) {
next(new Error('Definition missing from res.locals'));
}
else {
// Normalise the filters
const rawBody = req.body;
const normalisedFilters = rawBody && typeof rawBody === 'object' ? extractFiltersFromBody(rawBody) : {};
// Get the fields
const fields = reportType === ReportType.REPORT
? getFields(definition)
: getDashboardFields(definition);
// Get only the relevant applicable fields for the form type
const applicableFields = getFieldsWithFilters(fields).filter(field => {
const isInteractive = field.filter?.interactive === true;
return interactive ? isInteractive : !isInteractive;
});
// Build the schema based on the fields filters and check it
const schema = buildFilterSchemaFromFields(applicableFields);
const result = schema.safeParse(normalisedFilters);
if (result.success) {
// All good - go to request the report middleware
res.locals.validatedFilters = result.data;
next();
}
else {
const errors = result.error.issues.map(issue => ({
href: `#filters.${issue.path.join('.')}`,
text: issue.message,
}));
req.flash('DPR_ERRORS', JSON.stringify(errors));
let redirect = req.originalUrl;
if (interactive) {
const currentParams = buildRedirectParams(req, rawBody, loadType);
redirect = `${req.baseUrl}?${currentParams}`;
}
res.redirect(redirect);
}
}
};
/**
* Builds the redirect params from the form body
* - used for interactive report filters
*
* @param {Request} req
* @param {Record<string, unknown>} rawBody
* @param {LoadType} loadType
* @return {*}
*/
const buildRedirectParams = (req, rawBody, loadType) => {
const { tableId, id, reportId } = req.params;
// Create the qs from the form body
const filtersQs = formBodyToQs(rawBody);
// Get the current query string params
const sessionKey = loadType === LoadType.ASYNC ? { id, tableId, reportId } : { id, reportId };
const currentColumnsSearch = getActiveJourneyValue(req, sessionKey, 'currentReportColumnsSearch');
const currentSortSearch = getActiveJourneyValue(req, sessionKey, 'currentSortSearch');
const currentPageSizeSearch = getActiveJourneyValue(req, sessionKey, 'currentPageSizeSearch');
return joinQueryStrings(filtersQs, currentColumnsSearch, currentSortSearch, currentPageSizeSearch, 'preventDefault=true');
};
export { validateFilters };
//# sourceMappingURL=validateFilters.js.map