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.

161 lines (135 loc) 5.09 kB
import type { ParsedQs } from 'qs' import { FilteredListRequest } from './index' import Dict = NodeJS.Dict import { components } from './api' import { clearFilterValue } from '../utils/urlHelper' import ColumnUtils from '../components/_reports/report-columns-form/utils' import { Template } from './Templates' export const DEFAULT_FILTERS_PREFIX = 'filters.' export default class ReportQuery implements FilteredListRequest { selectedPage: number pageSize: number sortColumn?: string columns: Array<string> sortedAsc: boolean filters: Dict<string> filtersPrefix: string dataProductDefinitionsPath?: string constructor({ fields, template, queryParams, definitionsPath, filtersPrefix = DEFAULT_FILTERS_PREFIX, }: { fields: components['schemas']['FieldDefinition'][] template?: Template queryParams: ParsedQs definitionsPath?: string filtersPrefix?: string }) { this.selectedPage = queryParams.selectedPage ? Number(queryParams.selectedPage) : 1 this.pageSize = queryParams.pageSize && template ? Number(queryParams.pageSize) : this.getDefaultPageSize(template as Template) this.sortColumn = queryParams.sortColumn ? queryParams.sortColumn.toString() : this.getDefaultSortColumn(fields) this.sortedAsc = queryParams.sortedAsc !== 'false' this.dataProductDefinitionsPath = definitionsPath ?? (queryParams.dataProductDefinitionsPath ? queryParams.dataProductDefinitionsPath.toString() : null) this.filtersPrefix = filtersPrefix if (queryParams.columns) { const columns = typeof queryParams.columns === 'string' ? queryParams.columns.split(',') : (queryParams.columns as string[]) this.columns = ColumnUtils.ensureMandatoryColumns(fields, columns) } else { this.columns = fields.filter((f) => f.visible).map((f) => f.name) } let min: string let max: string const dateField: components['schemas']['FieldDefinition'] = fields.find((f) => { return ( (f.type === 'date' && f.filter && f.filter.type === 'daterange') || (f.type === 'date' && f.filter && f.filter.type === 'date') ) }) if (dateField) ({ min, max } = dateField.filter) this.filters = {} Object.keys(queryParams) .filter((key) => key.startsWith(this.filtersPrefix)) .filter((key) => queryParams[key]) .forEach((key) => { const filter = key.replace(this.filtersPrefix, '') let value = queryParams[key].toString() if (filter.includes('.start') && min) { if (new Date(value) < new Date(min)) value = min } if (filter.includes('.end') && max) { if (new Date(value) > new Date(max)) value = max } if (value !== 'no-filter') { this.filters[filter] = value } }) if (dateField && dateField.filter.type === 'daterange') { if ( min && Object.keys(queryParams).some((key) => key.includes(this.filtersPrefix)) && Object.keys(queryParams).every((key) => !key.includes('.start')) ) { this.filters[`${dateField.name}.start`] = min } if ( max && Object.keys(queryParams).some((key) => key.includes(this.filtersPrefix)) && Object.keys(queryParams).every((key) => !key.includes('.end')) ) { this.filters[`${dateField.name}.end`] = max } } if (dateField && dateField.filter.type === 'date') { if ( min && Object.keys(queryParams).some((key) => key.includes(this.filtersPrefix)) && Object.keys(queryParams).every((key) => !key.includes(dateField.name)) ) { this.filters[`${dateField.name}.start`] = min } } } private getDefaultSortColumn(fields: components['schemas']['FieldDefinition'][]) { const defaultSortColumn = fields.find((f) => f.defaultsort) return defaultSortColumn ? defaultSortColumn.name : fields.find((f) => f.sortable)?.name } toRecordWithFilterPrefix(removeClearedFilters = false): Record<string, string | Array<string>> { const record: Record<string, string | Array<string>> = { selectedPage: this.selectedPage.toString(), pageSize: this.pageSize.toString(), sortColumn: this.sortColumn, sortedAsc: this.sortedAsc.toString(), columns: this.columns, } if (this.dataProductDefinitionsPath) { record.dataProductDefinitionsPath = this.dataProductDefinitionsPath } Object.keys(this.filters).forEach((filterName) => { const value = this.filters[filterName] if (!removeClearedFilters || value !== clearFilterValue) { record[`${this.filtersPrefix}${filterName}`] = value } }) return record } private getDefaultPageSize(template: Template) { const maxResultsSize = 50000 const standardPage = 20 switch (template) { case 'list-section': case 'summary-section': case 'row-section-child': case 'parent-child': return maxResultsSize default: return standardPage } } }