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.

86 lines (83 loc) 3.67 kB
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