From 4d623390ee80f65ebe16b4a251afe2cc05300a21 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 1 Nov 2024 09:47:44 +0000 Subject: [PATCH] have table output real data --- src/middleware/dataview.middleware.js | 158 +++++++++++++++++++++----- 1 file changed, 129 insertions(+), 29 deletions(-) diff --git a/src/middleware/dataview.middleware.js b/src/middleware/dataview.middleware.js index 8dd103b4..0d243018 100644 --- a/src/middleware/dataview.middleware.js +++ b/src/middleware/dataview.middleware.js @@ -1,37 +1,126 @@ +import logger from '../utils/logger.js' import { fetchDatasetInfo, fetchLatestResource, fetchLpaDatasetIssues, fetchOrgInfo, isResourceAccessible, isResourceIdInParams, takeResourceIdFromParams } from './common.middleware.js' import { fetchResourceStatus } from './datasetTaskList.middleware.js' -import { fetchIf, renderTemplate } from './middleware.builders.js' +import { fetchIf, fetchMany, fetchOne, FetchOptions, renderTemplate } from './middleware.builders.js' + +export const fetchSpecification = fetchOne({ + query: ({ req }) => `select * from specification WHERE specification = '${req.dataset.collection}'`, + result: 'specification' +}) + +export const pullOutDatasetSpecification = (req, res, next) => { + const { specification } = req + let collectionSpecifications + try { + collectionSpecifications = JSON.parse(specification.json) + } catch (error) { + logger.error('Invalid JSON in specification.json', { error }) + return next(new Error('Invalid specification format')) + } + const datasetSpecification = collectionSpecifications.find((spec) => spec.dataset === req.dataset.dataset) + req.specification = datasetSpecification + next() +} + +export const fetchEntities = fetchMany({ + query: ({ req, params }) => `SELECT * FROM entity WHERE organisation_entity = ${req.orgInfo.entity}`, + dataset: FetchOptions.fromParams, + result: 'entities' +}) + +export const extractJsonFieldFromEntities = (req, res, next) => { + const { entities } = req + + req.entities = entities.map(entity => { + const jsonField = entity.json + if (!jsonField || jsonField === '') { + logger.info(`common.middleware/extractJsonField: No json field for entity ${entity.toString()}`) + return entity + } + entity.json = undefined + try { + const parsedJson = JSON.parse(jsonField) + entity = { ...entity, ...parsedJson } + } catch (err) { + logger.warn(`common.middleware/extractJsonField: Error parsing JSON for entity ${entity.toString()}: ${err.message}`) + } + return entity + }) + + next() +} + +export const replaceUnderscoreInEntities = (req, res, next) => { + req.entities = req.entities.map((entity) => { + return Object.keys(entity).reduce((acc, key) => { + const newKey = key.replace(/_/g, '-') + acc[newKey] = entity[key] + return acc + }, {}) + }) + + next() +} + +export const fetchFieldMappings = fetchMany({ + query: () => 'select * from transform', + result: 'fieldMappings' +}) + +export const addDatabaseFieldToSpecification = (req, res, next) => { + const { specification, fieldMappings } = req + + req.specification.fields = specification.fields.flatMap(fieldObj => { + if (['GeoX', 'GeoY'].includes(fieldObj.field)) { // special case for brownfield land + return { datasetField: 'point', ...fieldObj } + } + + const fieldMappingsForField = fieldMappings.filter(mapping => mapping.field === fieldObj.field) + + const datasetFields = fieldMappingsForField.map(mapping => mapping.replacement_field).filter(Boolean) + + if (datasetFields.length === 0) { + // no dataset fields found, add the field anyway with datasetField set to the same value as fieldObj.field + return { datasetField: fieldObj.field, ...fieldObj } + } + + // sometimes a field maps to more than one dataset field, so we need to account for that + const specificationEntriesWithDatasetFields = datasetFields.map(datasetField => ({ datasetField, ...fieldObj })) + return specificationEntriesWithDatasetFields + }) + + next() +} + +export const replaceUnderscoreInSpecification = (req, res, next) => { + req.specification.fields = req.specification.fields.map((spec) => { + if (spec.datasetField) { + spec.datasetField = spec.datasetField.replace(/_/g, '-') + } + return spec + }) + + next() +} export const constructTableParams = (req, res, next) => { - req.tableParams = { - columns: [ - 'column 1', - 'column 2', - 'column 3' - ], - fields: [ - 'column 1', - 'column 2', - 'column 3' - ], - rows: [ - { - columns: { - 'column 1': { - value: 'value 1' - }, - 'column 2': { - html: 'html 1' - }, - 'column 3': { - value: 'value 2', - error: { - message: 'error 1' - } - } - } + const { entities, specification } = req + + const columns = specification.fields.map(field => field.field) + const fields = specification.fields.map(field => field.datasetField) + const rows = entities.map(entity => ({ + columns: Object.fromEntries(fields.map(field => { + const value = { + value: entity[field] } - ] + return [field, value] + })) + })) + + req.tableParams = { + columns, + fields, + rows } next() @@ -62,6 +151,17 @@ export default [ fetchIf(isResourceIdInParams, fetchLatestResource, takeResourceIdFromParams), fetchIf(isResourceAccessible, fetchLpaDatasetIssues), + fetchEntities, + extractJsonFieldFromEntities, + replaceUnderscoreInEntities, + + fetchSpecification, + pullOutDatasetSpecification, + replaceUnderscoreInSpecification, + + fetchFieldMappings, + addDatabaseFieldToSpecification, + constructTableParams, prepareTemplatePramas, getGetDataview