diff --git a/lib/importer/govuk-prototype-kit.config.json b/lib/importer/govuk-prototype-kit.config.json index 61077c6..178daf4 100644 --- a/lib/importer/govuk-prototype-kit.config.json +++ b/lib/importer/govuk-prototype-kit.config.json @@ -81,6 +81,14 @@ { "macroName": "importerRangeSelector", "importFrom": "importer/macros/range_selector.njk" + }, + { + "macroName": "importerMappingWarningList", + "importFrom": "importer/macros/mapping_warning_list.njk" + }, + { + "macroName": "importerMappingErrorList", + "importFrom": "importer/macros/mapping_error_list.njk" } ] -} +} \ No newline at end of file diff --git a/lib/importer/index.js b/lib/importer/index.js index 49d2108..3ebe7a6 100644 --- a/lib/importer/index.js +++ b/lib/importer/index.js @@ -9,6 +9,8 @@ const os = require('node:os'); const IMPORTER_SESSION_KEY = "importer.session" const IMPORTER_ERROR_KEY = "importer.error" +const MAPPING_ERROR_KEY = "mapping.errors" +const MAPPING_WARNING_KEY = "mapping.warnings" //-------------------------------------------------------------------- // The endpoints used to receive POST requests from importer macros, @@ -30,28 +32,40 @@ exports.Initialise = (config, router, prototypeKit) => { // one created by us. config.uploadPath ??= path.join(os.tmpdir(), 'reg-dyn-importer'); ; + //-------------------------------------------------------------------- // Removes any previous importer error from the session. When we set // an error we redirect to the referer and we expect that page to show // the error. Calling this in each POST endpoint ensures that we don't // remember errors after they have been shown, //-------------------------------------------------------------------- - const cleanRequest = (request) => { + router.all("*", (request, res, next) => { delete request.session.data[IMPORTER_ERROR_KEY] - } + delete request.session.data[MAPPING_ERROR_KEY] + delete request.session.data[MAPPING_WARNING_KEY] + next(); + }); + //-------------------------------------------------------------------- // Make the route functions available in the templates. These functions // allow users to find the path that they should use to submit data, // and also allows them to specify which url to redirect to after - // the POST data has been processed. + // the POST data has been processed. Where an extra error url is provided + // it will be used if the POST request does not succeed (e.g. when + // mapping the data this can be used to redirect to the review page + // to view warnings) //-------------------------------------------------------------------- for ([key, value] of IMPORTER_ROUTE_MAP) { const k = key; const v = value; - prototypeKit.views.addFunction(k, (next)=>{ - return `${v}?next=${encodeURIComponent(next)}`; + prototypeKit.views.addFunction(k, (next, errorPage=null)=>{ + let url = `${v}?next=${encodeURIComponent(next)}`; + if (errorPage) { + url = url + `&error=${encodeURIComponent(errorPage)}` + } + return url }, {}) } @@ -84,6 +98,27 @@ exports.Initialise = (config, router, prototypeKit) => { return false; }, {}) + + //-------------------------------------------------------------------- + // Returns warnings or errors arising from applying a mapping. + //-------------------------------------------------------------------- + prototypeKit.views.addFunction("importerMappingErrors", (data) => { + if (data[MAPPING_ERROR_KEY]) { + return data[MAPPING_ERROR_KEY] + } + + return false; + }, {}) + + prototypeKit.views.addFunction("importerMappingWarnings", (data) => { + if (data[MAPPING_WARNING_KEY]) { + return data[MAPPING_WARNING_KEY] + } + + return false; + }, {}) + + //-------------------------------------------------------------------- // Allows a template to obtain `count` rows from the start of the data // range. @@ -169,8 +204,13 @@ exports.Initialise = (config, router, prototypeKit) => { // Redirects the current request to the 'next' URL after decoding the // encoded URI. //-------------------------------------------------------------------- - const redirectOnwards = (request, response) => { - response.redirect(decodeURIComponent(request.query.next)); + const redirectOnwards = (request, response, failed=false) => { + console.log(request.query) + if (failed && request.query.error) { + response.redirect(decodeURIComponent(request.query.error)); + } else { + response.redirect(decodeURIComponent(request.query.next)); + } } //-------------------------------------------------------------------- @@ -181,7 +221,6 @@ exports.Initialise = (config, router, prototypeKit) => { // time we run through the process. //-------------------------------------------------------------------- router.all(IMPORTER_ROUTE_MAP.get("importerStartPath"),(request, response) => { - cleanRequest(request); redirectOnwards(request, response); }); @@ -192,8 +231,6 @@ exports.Initialise = (config, router, prototypeKit) => { const uploader = getUploader(config); router.post(IMPORTER_ROUTE_MAP.get("importerUploadPath"), uploader.single("file"), (request, response) => { - cleanRequest(request); - let createResponse = session_lib.CreateSession(config, request); if (createResponse.error) { @@ -320,6 +357,24 @@ exports.Initialise = (config, router, prototypeKit) => { } session.mapping = request.body; + if (Object.values(session.mapping).every((v) => v=='') ) { + request.session.data[IMPORTER_ERROR_KEY] = "No columns were mapped to the expected fields" + if (!request.query.error) { + response.redirect(request.get('Referrer')) + } else { + redirectOnwards(request, response, failed=true); + } + return; + } + + const mapResults = sheets_lib.MapData(session); + if (mapResults.warningCount >= 0 || mapResults.errorCount >= 0) { + request.session.data[MAPPING_ERROR_KEY] = ["a test error"] + request.session.data[MAPPING_WARNING_KEY] = ["a test warning", "another warning"] + + redirectOnwards(request, response, failed=true); + return + } // Ensure the session is persisted. Currently in session, eventually another way request.session.data[IMPORTER_SESSION_KEY] = session; diff --git a/lib/importer/nunjucks/importer/macros/field_mapper.njk b/lib/importer/nunjucks/importer/macros/field_mapper.njk index 8d2b494..e0f9d42 100644 --- a/lib/importer/nunjucks/importer/macros/field_mapper.njk +++ b/lib/importer/nunjucks/importer/macros/field_mapper.njk @@ -17,13 +17,25 @@ {% macro importerFieldMapper(data, caption='', columnTitle='Column', examplesTitle='Example values', fieldsTitle='Fields') %} {% set fields = data['importer.session']['fields'] %} {% set headings = importerGetHeaders(data) %} - {% set error = headings.error %} + {% set error = importerError(data) %} - {% if error %} -
- {% endif %} + + {% if error %} +