@ministryofjustice/hmpps-digital-prison-reporting-frontend
Version:
The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.
223 lines (205 loc) • 5.94 kB
text/typescript
import { NextFunction, Request, RequestHandler, Response } from 'express'
import ReportQuery from '../../types/ReportQuery'
import {
ListDataSources,
RenderListWithDataInput,
RenderListWithDefinitionInput,
CreateRequestHandlerInput,
} from './types'
import ReportingClient from '../../data/reportingClient'
import { ListWithWarnings, Warnings } from '../../data/types'
import { components } from '../../types/api'
import Dict = NodeJS.Dict
import ReportActionsUtils from '../_reports/report-actions/utils'
import { Template } from '../../types/Templates'
import SyncReportUtils from '../../utils/report/syncReportUtils'
import FiltersUtils from '../_filters/utils'
import { ReportType } from '../../types/UserReports'
function isListWithWarnings(data: Dict<string>[] | ListWithWarnings): data is ListWithWarnings {
return (data as ListWithWarnings).data !== undefined
}
export async function renderList(
listData: ListDataSources,
variantDefinition: components['schemas']['VariantDefinition'],
reportQuery: ReportQuery,
request: Request,
response: Response,
next: NextFunction,
title: string,
layoutTemplate: string,
otherOptions?: NodeJS.Dict<object>,
reportName?: string,
) {
await Promise.all([listData.data, listData.count])
.then(async (resolvedData) => {
let data
let warnings: Warnings = {}
const { specification, classification, printable, description, name: variantName } = variantDefinition
const { template } = specification
const count = resolvedData[1]
if (isListWithWarnings(resolvedData[0])) {
// eslint-disable-next-line prefer-destructuring
data = resolvedData[0].data
warnings = resolvedData[0].warnings
} else {
// eslint-disable-next-line prefer-destructuring
data = resolvedData[0]
}
const reportRenderData = await SyncReportUtils.getReportRenderData(
request,
count,
specification,
reportQuery,
data,
)
const actions = ReportActionsUtils.getActions({
print: {
enabled: variantDefinition.printable,
},
share: {
reportName,
name: variantDefinition.name,
url: reportRenderData.fullUrl,
},
copy: {
url: reportRenderData.fullUrl,
},
})
const renderData = {
renderData: {
...reportRenderData,
reportName,
name: title || variantName,
description,
count,
classification,
printable,
actions,
template,
warnings,
type: ReportType.REPORT,
...otherOptions,
},
layoutTemplate,
}
response.render(`dpr/components/report-list/list`, renderData)
})
.catch((err) => next(err))
}
export const renderListWithDefinition = async ({
title,
definitionName,
variantName,
request,
response,
next,
otherOptions,
layoutTemplate,
token,
apiUrl,
apiTimeout,
definitionsPath,
}: RenderListWithDefinitionInput) => {
const reportingClient = new ReportingClient({
url: apiUrl,
agent: {
timeout: apiTimeout,
},
})
const { dataProductDefinitionsPath } = request.query
const reportDef = <string>dataProductDefinitionsPath || definitionsPath
try {
const reportDefinition = await reportingClient.getDefinition(token, definitionName, variantName, reportDef)
const reportName: string = reportDefinition.name
const variantDefinition = reportDefinition.variant
const reportQuery = new ReportQuery({
fields: variantDefinition.specification.fields,
template: variantDefinition.specification.template as Template,
queryParams: request.query,
definitionsPath: reportDef,
})
if (!FiltersUtils.redirectWithDefaultFilters(reportQuery, variantDefinition, response, request)) {
const getListData: ListDataSources = {
data: reportingClient.getListWithWarnings(variantDefinition.resourceName, token, reportQuery),
count: reportingClient.getCount(variantDefinition.resourceName, token, reportQuery),
}
await renderList(
getListData,
variantDefinition,
reportQuery,
request,
response,
next,
`${variantDefinition.name}`,
layoutTemplate,
otherOptions,
title || `${reportName}`,
)
}
} catch (error) {
next(error)
}
}
export default {
renderListWithData: async ({
title,
reportName,
variantDefinition,
request,
response,
next,
getListDataSources,
otherOptions,
layoutTemplate,
}: RenderListWithDataInput) => {
const { specification } = variantDefinition
const reportQuery = new ReportQuery({
fields: specification.fields,
template: specification.template as Template,
queryParams: request.query,
definitionsPath: <string>request.query.dataProductDefinitionsPath,
})
const listData = getListDataSources(reportQuery)
await renderList(
listData,
variantDefinition,
reportQuery,
request,
response,
next,
title,
layoutTemplate,
otherOptions,
reportName,
)
},
createReportListRequestHandler: ({
title,
definitionName,
variantName,
apiUrl,
apiTimeout,
otherOptions,
layoutTemplate,
tokenProvider,
definitionsPath,
}: CreateRequestHandlerInput): RequestHandler => {
return (request: Request, response: Response, next: NextFunction) => {
renderListWithDefinition({
title,
definitionName,
variantName,
request,
response,
next,
otherOptions,
layoutTemplate,
token: tokenProvider(request, response, next),
apiUrl,
apiTimeout,
definitionsPath,
})
}
},
renderListWithDefinition,
}