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.

131 lines (116 loc) 3.85 kB
import { Response, Request } from 'express' import { json2csv, Json2CsvOptions } from 'json-2-csv' import { KeysList } from 'json-2-csv/lib/types' import { Services } from '../types/Services' import Dict = NodeJS.Dict import { LoadType } from '../types/UserReports' import SyncReportUtils from './report/syncReportUtils' import { components } from '../types/api' import LocalsHelper from './localsHelper' const convertToCsv = (reportData: Dict<string>[], options: Json2CsvOptions) => { const csvData = json2csv(reportData, options) return csvData } const getKeys = ( reportData: Dict<string>[], reportDefinition: components['schemas']['SingleVariantReportDefinition'], ): KeysList => { const { fields } = reportDefinition.variant.specification const keys: KeysList = [] Object.keys(reportData[0]).forEach((key) => { const field = fields.find((f) => f.name === key) keys.push({ field: key, title: field.display, }) }) return keys } const applyColumnsAndSort = (data: Dict<string>[], columns: string[]) => { return data.map((row) => { return Object.keys(row) .filter((key) => columns.includes(key)) .reduce((obj: Dict<string>, key) => { // eslint-disable-next-line no-param-reassign obj[key] = row[key] return obj }, {}) }) } const removeHtmlTags = ( reportData: Dict<string>[], reportDefinition: components['schemas']['SingleVariantReportDefinition'], ) => { // Find HMTL field + name const { fields } = reportDefinition.variant.specification const htmlField = fields.find((field) => { return field.type === 'HTML' }) if (htmlField) { // remove wrapping HTML tags from value const { name } = htmlField reportData.map((d) => { const innerText = /target="_blank">(.*?)<\/a>/g.exec(d[name]) // eslint-disable-next-line prefer-destructuring, no-param-reassign d[name] = innerText[1] return d }) } return reportData } export default { async downloadReport({ req, services, res, redirect, loadType, }: { req: Request services: Services res: Response redirect: string loadType?: LoadType }) { const { userId, token } = LocalsHelper.getValues(res) const { reportId, id, tableId, dataProductDefinitionsPath, reportName, name, cols: columns } = req.body req.query = LocalsHelper.setDdpPathToReqQuery(req, dataProductDefinitionsPath) const canDownload = await services.downloadPermissionService.downloadEnabled(userId, reportId, id) if (!canDownload) { res.redirect(redirect) } else { const reportDefinition = await services.reportingService.getDefinition( token, reportId, id, dataProductDefinitionsPath, ) let reportData if (loadType === LoadType.SYNC) { const { reportData: listWithWarnings } = await SyncReportUtils.getReportData({ services, req, token, reportId, id, }) reportData = listWithWarnings.data } else { const pageSize = await services.reportingService.getAsyncCount(token, tableId) reportData = await services.reportingService.getAsyncReport(token, reportId, id, tableId, { dataProductDefinitionsPath, pageSize, }) } if (columns) { reportData = applyColumnsAndSort(reportData, JSON.parse(columns)) } reportData = removeHtmlTags(reportData, reportDefinition) const keys: KeysList = getKeys(reportData, reportDefinition) const csvData = convertToCsv(reportData, { keys }) res.setHeader('Content-Type', 'application/json') res.setHeader('Content-disposition', `attachment; filename=${reportName}-${name}-${new Date().toISOString()}.csv`) res.end(csvData) } }, }