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.

441 lines (436 loc) 14.7 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var types = require('./types.js'); var localsHelper = require('../../utils/localsHelper.js'); var UserReports = require('../../types/UserReports.js'); var utils$1 = require('./my-reports-list-item/utils.js'); var logger = require('../../utils/logger.js'); var getReportStatus = require('../../utils/ReportStatus/getReportStatus.js'); var captureError = require('../../utils/captureError.js'); var utils$3 = require('./my-reports-list-item/my-reports-list-item-actions/utils.js'); var utils$2 = require('../truncate/utils.js'); /** * Initialises the "My Reports" component data * * @param {Request} req * @param {Response} res * @param {Services} services * @return {*} {DprMyReport} */ const initMyReports = async (req, res, services, options) => { const { bookmarkingEnabled, subscriptionsEnabled } = localsHelper.default.getValues(res); await checkExpiredAndGetReports(res, services); const messages = setMessages(res); return { ...(subscriptionsEnabled && { subscriptions: await initSubscribed(req, res, options) }), ...(bookmarkingEnabled && { bookmarks: await initBookmarks(res, req, services) }), requested: await initRequested(req, res, options), viewed: await initViewed(req, res, options), ...(messages && { messages }), }; }; /** * Sets the messages if any * * @param {Response} res * @return {*} {MyReportsMessages} */ const setMessages = (res) => { const subscriptionMessages = { subscribedMessage: res.locals['subscribedMessage'] || [], unsubscribedMessage: res.locals['unsubscribedMessage'] || [], }; const { removedReports } = res.locals; return { subscriptionMessages, removedReports, }; }; const checkExpiredAndGetReports = async (res, services) => { const { requestedReports, recentlyViewedReports } = localsHelper.default.getValues(res); if (getReportStatus.shouldRunExpiryCheck(res.req.session)) { try { const refreshedReports = await getReportStatus.expireFinishedReports({ requestedReports, recentlyViewedReports, services, res, }); res.locals['requestedReports'] = refreshedReports.requestedReports; res.locals['recentlyViewedReports'] = refreshedReports.recentlyViewedReports; getReportStatus.recordExpiryCheck(res.req.session); } catch (error) { logger.default.error(error); } } return { requestedReports, recentlyViewedReports, }; }; /** * Init bookmarks list * * @param {Request} req * @param {Response} res * @param {Services} services * @return {*} {DprMyReportListConfig} */ const initBookmarks = async (res, req, services, options) => { const totalItems = await buildBookmarkListItems(res, req, services); const totals = buildTotals(res, totalItems, types.ListType.BOOKMARKS, options); const items = cutItemsToSize(totalItems, options); return { title: 'Bookmarks', listType: types.ListType.BOOKMARKS, headings: buildHeadings(types.ListType.BOOKMARKS), items, totals, }; }; /** * Init Requested Reports list * * @param {Request} req * @param {Response} res * @return {*} */ const initRequested = async (req, res, options) => { const { csrfToken } = localsHelper.default.getValues(res); const totalItems = await buildListItems(req, res, types.ListType.REQUESTED); const totals = buildTotals(res, totalItems, types.ListType.REQUESTED, options); const items = cutItemsToSize(totalItems, options); return { title: 'Requested reports', listType: types.ListType.REQUESTED, csrfToken, headings: buildHeadings(types.ListType.REQUESTED), items, totals, }; }; /** * Init Viewed reports list * * @param {Request} req * @param {Response} res * @return {*} */ const initViewed = async (req, res, options) => { const { csrfToken } = localsHelper.default.getValues(res); const totalItems = await buildListItems(req, res, types.ListType.VIEWED); const totals = buildTotals(res, totalItems, types.ListType.VIEWED, options); const items = cutItemsToSize(totalItems, options); return { title: 'Recently viewed', listType: types.ListType.VIEWED, csrfToken, headings: buildHeadings(types.ListType.VIEWED), items, totals, }; }; const initSubscribed = async (req, res, options) => { const { csrfToken } = localsHelper.default.getValues(res); const totalItems = await buildListItems(req, res, types.ListType.SUBSCRIPTIONS); const totals = buildTotals(res, totalItems, types.ListType.SUBSCRIPTIONS, options); const items = cutItemsToSize(totalItems, options); return { title: 'Subscriptions', listType: types.ListType.SUBSCRIPTIONS, csrfToken, headings: buildHeadings(types.ListType.SUBSCRIPTIONS), items, totals, }; }; // ---------------------------------------------- // LIST ITEMS // ----------------------------------------------- /** * Builds the requested & views list items * * @param {Request} req * @param {Response} res * @param {ListType} listType * @return {*} {DprMyReportItem[]} */ const buildListItems = async (req, res, listType) => { const listData = await getDataForList(res, listType); if (!listData) { return []; } return listData.map((data) => { const status = data.status; return utils$1.buildMyReportListRow(data, status, req, res, listType); }); }; const cutItemsToSize = (items, options) => { return options?.maxRows ? items.slice(0, options.maxRows) : items; }; /** * Builds the list totals * * @param {Response} res * @param {DprMyReportItem[]} items * @param {ListType} listType * @param {(MyReportsOptions | undefined)} [options] * @return {*} {MyReportsListTotals} */ const buildTotals = (res, items, listType, options) => { if (!options?.maxRows) { return { total: items.length, shown: items.length, }; } const { maxRows } = options; const total = items.length; const shown = items.length > maxRows ? maxRows : items.length; let href; if (maxRows < total) { const { requestedListPath, recentlyViewedListPath, bookmarkListPath } = localsHelper.getRouteLocals(res); switch (listType) { case types.ListType.BOOKMARKS: href = `${bookmarkListPath}/list`; break; case types.ListType.REQUESTED: href = `${requestedListPath}/list`; break; case types.ListType.VIEWED: href = `${recentlyViewedListPath}/list`; break; default: href = `${requestedListPath}/list`; break; } } return { total: items.length, shown, href, maxRows, }; }; /** * Builds the bookmark list items * * @param {Response} res * @param {Services} services * @return {*} {Promise<DprMyReportItem[]>} */ const buildBookmarkListItems = async (res, req, services) => { const { bookmarks } = localsHelper.default.getValues(res); // loop it if (!bookmarks) { return []; } // gather data for loop. const mappedBookmarks = await mapBookmarks(bookmarks, services, res); return mappedBookmarks.map(bookmark => { const { name, reportName, type, description } = bookmark; return { title: { productName: name, reportName, reportType: type, }, description: utils$2.renderTruncateAsHtml({ stringValue: description, classes: 'govuk-body-s', charLength: 50 }), actions: buildBookmarkActionsCell(bookmark, res, req), }; }); }; /** * Map bookmarks to display data * * @param {BookmarkStoreData[]} bookmarks * @param {Services} services * @param {Response} res * @return {*} */ const mapBookmarks = async (bookmarks, services, res) => { const { token, definitionsPath } = localsHelper.default.getValues(res); const mapped = await Promise.all(bookmarks.map(async (bm) => { try { const resolved = await resolveBookmarkDefinition(bm, services, token, definitionsPath); return { id: resolved.sourceId, reportId: bm.reportId, name: resolved.name, reportName: resolved.reportName, type: resolved.reportType, description: resolved.description, loadType: resolved.loadType, }; } catch (error) { const meta = { reportId: bm.reportId, id: bm.variantId || bm.id, }; captureError.captureDprError(error, `Unable to get info for bookmark`, meta); return null; } })); return mapped.filter((bm) => bm !== null); }; /** * Resolves the bookmark definition for the bookmark * * @param {BookmarkStoreData} bm * @param {Services} services * @param {string} token * @param {string} definitionsPath * @return {*} */ const resolveBookmarkDefinition = async (bm, services, token, definitionsPath) => { const { id, reportId, type, variantId } = bm; const sourceId = variantId || id; const summary = await services.reportingService.getDefinitionSummary(token, reportId, definitionsPath); if (!type || type === UserReports.ReportType.REPORT) { const definition = await services.reportingService.getDefinition(token, reportId, sourceId, definitionsPath); const defSummary = summary.variants.find(v => v.id === sourceId); return { sourceId, reportType: UserReports.ReportType.REPORT, reportName: definition.variant.name, name: definition.name, description: definition.variant.description || definition.description || '', loadType: defSummary?.loadType ? defSummary.loadType : UserReports.LoadType.ASYNC, }; } const definition = await services.dashboardService.getDefinition(token, reportId, sourceId, definitionsPath); const defSummary = summary.dashboards?.find(d => d.id === sourceId); return { sourceId, reportType: type, reportName: definition?.name || '', name: summary?.name || '', description: definition?.description || summary?.description || '', loadType: defSummary?.loadType ? defSummary.loadType : UserReports.LoadType.ASYNC, }; }; /** * Builds the bookmark actions cell * * @param {*} data * @param {Response} res * @return {*} {DprMyReportActions} */ const buildBookmarkActionsCell = (data, res, req) => { const { load, request } = utils$3.buildLoadRequestAction(res, req, data); const bookmark = buildBookmarkRemoveAction(res, data); return { ...(load && { load }), ...(request && { request }), bookmark, }; }; /** * Build the bookmark link config * * @param {Response} res * @param {MappedBookmarks} data * @return {*} */ const buildBookmarkRemoveAction = (res, data) => { const { reportId, id, type: reportType } = data; const { csrfToken } = localsHelper.default.getValues(res); const { bookmarkActionEndpoint } = localsHelper.default.getRouteLocals(res); return { reportId, id, reportType, csrfToken, bookmarkActionEndpoint, linkType: 'remove', linkText: 'Remove bookmark', }; }; /** * Gets the relevant data to build the list * * @param {Response} res * @param {ListType} listType * @return {*} {(StoredReportData[] | undefined)} */ const getDataForList = async (res, listType) => { const { requestedReports, recentlyViewedReports, subscriptions } = localsHelper.default.getValues(res); switch (listType) { case types.ListType.REQUESTED: // Only show reports in the list that have not been viewed return requestedReports.filter(report => { return report.timestamp ? !report.timestamp.lastViewed : false; }); case types.ListType.VIEWED: // Only show READY or EXPIRED reports return recentlyViewedReports.filter(report => { return Boolean(report.status === UserReports.RequestStatus.READY || Boolean(report.executionId?.length && report.status === UserReports.RequestStatus.EXPIRED)); }); case types.ListType.SUBSCRIPTIONS: return subscriptions; default: return undefined; } }; // ---------------------------------------------- // HEADINGS // ----------------------------------------------- /** * Builds the headings * * @param {ListType} listType * @return {*} {DprMyReportHeading[]} */ const buildHeadings = (listType) => { return ALL_HEADINGS.filter(heading => heading.showIn.includes(listType)); }; const ALL_HEADINGS = [ { key: 'title', name: 'Product', classes: 'dpr-my-reports__cell--title', showIn: [types.ListType.BOOKMARKS, types.ListType.REQUESTED, types.ListType.VIEWED, types.ListType.SUBSCRIPTIONS], }, { key: 'description', name: 'Description', classes: 'dpr-my-reports__cell--description', showIn: [types.ListType.BOOKMARKS, types.ListType.SUBSCRIPTIONS], }, { key: 'filters', name: 'Filters', classes: 'dpr-my-reports__cell--filters', showIn: [types.ListType.REQUESTED, types.ListType.VIEWED], }, { key: 'status', name: 'Status', classes: 'dpr-my-reports__cell--status', showIn: [types.ListType.REQUESTED, types.ListType.VIEWED], }, { key: 'schedule', name: 'Schedule', classes: 'dpr-my-reports__cell--status', showIn: [types.ListType.SUBSCRIPTIONS], }, { key: 'actions', name: 'Actions', classes: 'dpr-my-reports__cell--actions', showIn: [types.ListType.BOOKMARKS, types.ListType.REQUESTED, types.ListType.VIEWED, types.ListType.SUBSCRIPTIONS], }, ]; var utils = { initMyReports, }; exports.default = utils; exports.initMyReports = initMyReports; exports.initRequested = initRequested; exports.initSubscribed = initSubscribed; exports.initViewed = initViewed; //# sourceMappingURL=utils.js.map