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.

279 lines (252 loc) 7.3 kB
import parseUrl from 'parseurl' import type { Request, Response } from 'express' import Dict = NodeJS.Dict import type { components } from '../../types/api' import type { DataTable } from '../DataTableBuilder/types' import type { ListWithWarnings } from '../../data/types' import type { Columns } from '../../components/_reports/report-columns-form/types' import type { Services } from '../../types/Services' import type { DownloadActionParams } from '../../components/_reports/report-actions/types' import { LoadType, ReportType, RequestStatus } from '../../types/UserReports' import ReportQuery from '../../types/ReportQuery' import PaginationUtils from '../../components/_reports/report-pagination/utils' import TotalsUtils from '../../components/_reports/report-totals/utils' import ColumnUtils from '../../components/_reports/report-columns-form/utils' import ReportActionsUtils from '../../components/_reports/report-actions/utils' import FiltersUtils from '../../components/_filters/utils' import LocalsHelper from '../localsHelper' import UserStoreItemBuilder from '../UserStoreItemBuilder' import DataTableBuilder from '../DataTableBuilder/DataTableBuilder' import { Template } from '../../types/Templates' const setActions = ( csrfToken: string, reportDefinition: components['schemas']['SingleVariantReportDefinition'], columns: Columns, url: string, canDownload: boolean, count: number, dataProductDefinitionsPath: string, currentUrl: string, currentQueryParams: string, ) => { const { name: reportName, variant, id: reportId } = reportDefinition const { name, id, printable } = variant const downloadConfig: DownloadActionParams = { enabled: count > 0, name, reportName, csrfToken, reportId, id, columns: columns.value, loadType: LoadType.SYNC, definitionPath: dataProductDefinitionsPath, canDownload, currentUrl, currentQueryParams, } return ReportActionsUtils.getActions({ download: downloadConfig, print: { enabled: printable, }, share: { reportName, name, url, }, copy: { url, }, }) } const setAsRecentlyViewed = async ( req: Request, services: Services, reportName: string, name: string, description: string, reportId: string, id: string, userId: string, ) => { const stateData = { type: ReportType.REPORT, reportId, id, reportName, description, name, } const recentlyViewedData = new UserStoreItemBuilder() .addReportData(stateData) .addStatus(RequestStatus.READY) .addTimestamp() .addReportUrls(req) .build() await services.recentlyViewedService.setRecentlyViewed(recentlyViewedData, userId) } const getReportData = async ({ services, req, token, reportId, id, }: { services: Services req: Request token: string reportId: string id: string }) => { const { dataProductDefinitionsPath } = req.query const reportDefinition = await services.reportingService.getDefinition( token, reportId, id, dataProductDefinitionsPath, ) const { variant } = reportDefinition const { resourceName, specification } = variant const reportQuery = new ReportQuery({ fields: specification.fields, template: specification.template as Template, queryParams: req.query, definitionsPath: <string>dataProductDefinitionsPath, }) return { reportData: await services.reportingService.getListWithWarnings(resourceName, token, reportQuery), reportDefinition, reportQuery, } } const getReport = async ({ req, res, services }: { req: Request; res: Response; services: Services }) => { const { token, csrfToken, userId } = LocalsHelper.getValues(res) const { reportId, id } = req.params const { dataProductDefinitionsPath } = req.query const { reportData, reportDefinition, reportQuery } = await getReportData({ services, req, token, reportId, id }) const count = await services.reportingService.getCount(reportDefinition.variant.resourceName, token, reportQuery) const canDownload = await services.downloadPermissionService.downloadEnabled(userId, reportId, id) const bookmarked = await services.bookmarkService.isBookmarked(id, reportId, userId) const renderData = await getRenderData({ req, reportDefinition, reportQuery, reportData, count, csrfToken, canDownload, }) if (Object.keys(renderData).length) { setAsRecentlyViewed( req, services, reportId, id, renderData.reportName, renderData.name, renderData.description, userId, ) } return { renderData: { ...renderData, csrfToken, loadType: LoadType.SYNC, reportId, id, bookmarked, dataProductDefinitionsPath, }, } } const getReportRenderData = async ( req: Request, count: number, specification: components['schemas']['Specification'], reportQuery: ReportQuery, data: Dict<string>[], ) => { const url = parseUrl(req) const fullUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}` const pagination = PaginationUtils.getPaginationData(url, count) const dataTable: DataTable = new DataTableBuilder(specification.fields) .withHeaderSortOptions(reportQuery) .buildTable(data) const totals = TotalsUtils.getTotals( pagination.pageSize, pagination.currentPage, pagination.totalRows, dataTable.rowCount, ) const filterData = await FiltersUtils.getFilters({ fields: specification.fields, req, }) const columns = ColumnUtils.getColumns(specification, reportQuery.columns) return { dataTable: [dataTable], totals, filterData, columns, pagination, reportUrl: url.pathname.replace('/download-disabled', '').replace('/download-disabled?', ''), reportSearch: url.search, encodedSearch: url.search ? encodeURIComponent(url.search) : undefined, fullUrl, } } const getRenderData = async ({ req, reportDefinition, reportQuery, reportData, count, csrfToken, canDownload, }: { req: Request reportDefinition: components['schemas']['SingleVariantReportDefinition'] reportQuery: ReportQuery reportData: ListWithWarnings csrfToken: string count: number canDownload: boolean }) => { const { dataProductDefinitionsPath } = req.query const { name: reportName, description: reportDescription } = reportDefinition const { specification, name, description, classification, printable } = reportDefinition.variant const { data } = reportData const reportRenderData = await getReportRenderData(req, count, specification, reportQuery, data) const actions = setActions( csrfToken, reportDefinition, reportRenderData.columns, `${req.protocol}://${req.get('host')}${req.originalUrl}`, canDownload, count, <string>dataProductDefinitionsPath, reportRenderData.reportUrl, reportRenderData.reportSearch, ) return { ...reportRenderData, reportName, name, description: description || reportDescription, count, type: ReportType.REPORT, classification, printable, actions, warnings: reportData.warnings, } } export default { getRenderData, getReport, getReportData, getReportRenderData, setActions, }