@defra/forms-engine-plugin 5.0.0-alpha.3 → 5.0.0-alpha.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.public/37c964ca545c240f010a.mjs +2 -0
- package/.public/37c964ca545c240f010a.mjs.LICENSE.txt +4 -0
- package/.public/assets-manifest.json +3 -0
- package/.public/javascripts/application.min.js +1 -1
- package/.public/javascripts/application.min.js.LICENSE.txt +7 -0
- package/.public/javascripts/application.min.js.map +1 -1
- package/.public/javascripts/shared.min.js +1 -1
- package/.public/javascripts/shared.min.js.LICENSE.txt +9 -0
- package/.public/javascripts/shared.min.js.map +1 -1
- package/.public/javascripts/vendor/@defra.min.js +1 -1
- package/.public/javascripts/vendor/@defra.min.js.map +1 -1
- package/.public/javascripts/vendor/maplibre-gl.min.js +1 -1
- package/.public/javascripts/vendor/maplibre-gl.min.js.LICENSE.txt +3 -3
- package/.public/javascripts/vendor/maplibre-gl.min.js.map +1 -1
- package/.public/stylesheets/application.min.css +1 -1
- package/.public/stylesheets/application.min.css.map +1 -1
- package/.server/client/javascripts/file-upload.js +6 -3
- package/.server/client/javascripts/file-upload.js.map +1 -1
- package/.server/client/javascripts/geospatial-map.d.ts +159 -5
- package/.server/client/javascripts/geospatial-map.js +161 -81
- package/.server/client/javascripts/geospatial-map.js.map +1 -1
- package/.server/client/javascripts/geospatial-map.test.js +152 -0
- package/.server/client/javascripts/geospatial-map.test.js.map +1 -0
- package/.server/client/javascripts/govuk.js +2 -1
- package/.server/client/javascripts/govuk.js.map +1 -1
- package/.server/client/javascripts/location-map.d.ts +44 -0
- package/.server/client/javascripts/location-map.js +55 -6
- package/.server/client/javascripts/location-map.js.map +1 -1
- package/.server/client/javascripts/map-constants.d.ts +3 -0
- package/.server/client/javascripts/map-constants.js +4 -0
- package/.server/client/javascripts/map-constants.js.map +1 -0
- package/.server/client/javascripts/map.d.ts +17 -4
- package/.server/client/javascripts/map.js +59 -6
- package/.server/client/javascripts/map.js.map +1 -1
- package/.server/client/javascripts/maps.d.ts +5 -0
- package/.server/client/javascripts/maps.js +6 -0
- package/.server/client/javascripts/maps.js.map +1 -0
- package/.server/client/javascripts/shared.d.ts +1 -4
- package/.server/client/javascripts/shared.js +1 -4
- package/.server/client/javascripts/shared.js.map +1 -1
- package/.server/client/javascripts/sssi-dataset.d.ts +18 -20
- package/.server/client/javascripts/sssi-dataset.js +37 -39
- package/.server/client/javascripts/sssi-dataset.js.map +1 -1
- package/.server/client/stylesheets/maps.scss +4 -0
- package/.server/client/stylesheets/shared.scss +1 -5
- package/.server/server/constants.d.ts +2 -0
- package/.server/server/constants.js +2 -0
- package/.server/server/constants.js.map +1 -1
- package/.server/server/forms/components.json +8 -0
- package/.server/server/forms/register-as-a-unicorn-breeder.yaml +4 -0
- package/.server/server/plugins/engine/__stubs__/definitions.d.ts +29 -0
- package/.server/server/plugins/engine/__stubs__/definitions.js +125 -0
- package/.server/server/plugins/engine/__stubs__/definitions.js.map +1 -0
- package/.server/server/plugins/engine/components/AutocompleteField.d.ts +8 -3
- package/.server/server/plugins/engine/components/AutocompleteField.js +17 -0
- package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
- package/.server/server/plugins/engine/components/CheckboxesField.d.ts +23 -2
- package/.server/server/plugins/engine/components/CheckboxesField.js +30 -5
- package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
- package/.server/server/plugins/engine/components/ComponentBase.d.ts +2 -1
- package/.server/server/plugins/engine/components/ComponentBase.js +2 -0
- package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
- package/.server/server/plugins/engine/components/ComponentCollection.js +12 -7
- package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
- package/.server/server/plugins/engine/components/DatePartsField.d.ts +6 -3
- package/.server/server/plugins/engine/components/DatePartsField.js +12 -7
- package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
- package/.server/server/plugins/engine/components/DeclarationField.d.ts +6 -3
- package/.server/server/plugins/engine/components/DeclarationField.js +6 -4
- package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
- package/.server/server/plugins/engine/components/Details.d.ts +1 -0
- package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +33 -2
- package/.server/server/plugins/engine/components/EastingNorthingField.js +110 -54
- package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
- package/.server/server/plugins/engine/components/EmailAddressField.d.ts +4 -1
- package/.server/server/plugins/engine/components/EmailAddressField.js +2 -1
- package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
- package/.server/server/plugins/engine/components/FileUploadField.d.ts +23 -2
- package/.server/server/plugins/engine/components/FileUploadField.js +35 -3
- package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
- package/.server/server/plugins/engine/components/FormComponent.d.ts +5 -1
- package/.server/server/plugins/engine/components/FormComponent.js +5 -2
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/GeospatialField.d.ts +23 -0
- package/.server/server/plugins/engine/components/GeospatialField.js +33 -9
- package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
- package/.server/server/plugins/engine/components/Html.d.ts +1 -0
- package/.server/server/plugins/engine/components/InsetText.d.ts +1 -0
- package/.server/server/plugins/engine/components/LatLongField.d.ts +32 -2
- package/.server/server/plugins/engine/components/LatLongField.js +85 -48
- package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
- package/.server/server/plugins/engine/components/List.d.ts +1 -0
- package/.server/server/plugins/engine/components/ListFormComponent.d.ts +3 -2
- package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +8 -2
- package/.server/server/plugins/engine/components/LocationFieldBase.js +31 -7
- package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
- package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +12 -3
- package/.server/server/plugins/engine/components/LocationFieldHelpers.js +21 -13
- package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
- package/.server/server/plugins/engine/components/Markdown.d.ts +1 -0
- package/.server/server/plugins/engine/components/Markdown.js +1 -1
- package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
- package/.server/server/plugins/engine/components/MonthYearField.d.ts +5 -2
- package/.server/server/plugins/engine/components/MonthYearField.js +13 -9
- package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
- package/.server/server/plugins/engine/components/MultilineTextField.d.ts +1 -0
- package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
- package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +4 -3
- package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
- package/.server/server/plugins/engine/components/NotificationBanner.d.ts +1 -0
- package/.server/server/plugins/engine/components/NumberField.d.ts +5 -0
- package/.server/server/plugins/engine/components/NumberField.js +22 -0
- package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
- package/.server/server/plugins/engine/components/OsGridRefField.d.ts +103 -1
- package/.server/server/plugins/engine/components/OsGridRefField.js +13 -3
- package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
- package/.server/server/plugins/engine/components/PaymentField.d.ts +2 -0
- package/.server/server/plugins/engine/components/PaymentField.js +9 -5
- package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
- package/.server/server/plugins/engine/components/SelectField.d.ts +1 -0
- package/.server/server/plugins/engine/components/SelectionControlField.d.ts +1 -0
- package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +1 -0
- package/.server/server/plugins/engine/components/TrackingField.d.ts +21 -0
- package/.server/server/plugins/engine/components/TrackingField.js +46 -0
- package/.server/server/plugins/engine/components/TrackingField.js.map +1 -0
- package/.server/server/plugins/engine/components/UkAddressField.d.ts +1 -0
- package/.server/server/plugins/engine/components/UkAddressField.js +23 -8
- package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
- package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -2
- package/.server/server/plugins/engine/components/YesNoField.js +22 -8
- package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
- package/.server/server/plugins/engine/components/helpers/components.js +6 -3
- package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +8 -1
- package/.server/server/plugins/engine/components/helpers/geospatial.js +58 -17
- package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/index.d.ts +21 -1
- package/.server/server/plugins/engine/components/helpers/index.js +45 -1
- package/.server/server/plugins/engine/components/helpers/index.js.map +1 -1
- package/.server/server/plugins/engine/components/index.d.ts +1 -0
- package/.server/server/plugins/engine/components/index.js +1 -0
- package/.server/server/plugins/engine/components/index.js.map +1 -1
- package/.server/server/plugins/engine/components/types.d.ts +1 -0
- package/.server/server/plugins/engine/components/types.js.map +1 -1
- package/.server/server/plugins/engine/errors.d.ts +49 -0
- package/.server/server/plugins/engine/errors.js +75 -0
- package/.server/server/plugins/engine/errors.js.map +1 -0
- package/.server/server/plugins/engine/form-availability.d.ts +3 -2
- package/.server/server/plugins/engine/form-availability.js +3 -2
- package/.server/server/plugins/engine/form-availability.js.map +1 -1
- package/.server/server/plugins/engine/form-context.js +2 -2
- package/.server/server/plugins/engine/form-context.js.map +1 -1
- package/.server/server/plugins/engine/helpers.d.ts +23 -2
- package/.server/server/plugins/engine/helpers.js +44 -5
- package/.server/server/plugins/engine/helpers.js.map +1 -1
- package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +4 -1
- package/.server/server/plugins/engine/i18n/buildValidationMessages.js +31 -7
- package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -1
- package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +4 -4
- package/.server/server/plugins/engine/i18n/createFormTranslator.js +27 -5
- package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -1
- package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +1 -1
- package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +9 -0
- package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -1
- package/.server/server/plugins/engine/i18n/form.d.ts +13 -0
- package/.server/server/plugins/engine/i18n/form.js +35 -0
- package/.server/server/plugins/engine/i18n/form.js.map +1 -0
- package/.server/server/plugins/engine/i18n/languages.d.ts +10 -0
- package/.server/server/plugins/engine/i18n/languages.js +19 -0
- package/.server/server/plugins/engine/i18n/languages.js.map +1 -0
- package/.server/server/plugins/engine/i18n/translations/cy.json +176 -7
- package/.server/server/plugins/engine/i18n/translations/en-GB.json +110 -6
- package/.server/server/plugins/engine/i18n/types.d.ts +2 -0
- package/.server/server/plugins/engine/i18n/types.js.map +1 -1
- package/.server/server/plugins/engine/index.d.ts +4 -0
- package/.server/server/plugins/engine/index.js +4 -0
- package/.server/server/plugins/engine/index.js.map +1 -1
- package/.server/server/plugins/engine/models/FormModel.d.ts +0 -4
- package/.server/server/plugins/engine/models/FormModel.js +35 -23
- package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
- package/.server/server/plugins/engine/models/SummaryViewModel.js +9 -4
- package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
- package/.server/server/plugins/engine/models/types.d.ts +28 -1
- package/.server/server/plugins/engine/models/types.js.map +1 -1
- package/.server/server/plugins/engine/models/unavailable-view-model.d.ts +11 -2
- package/.server/server/plugins/engine/models/unavailable-view-model.js +23 -4
- package/.server/server/plugins/engine/models/unavailable-view-model.js.map +1 -1
- package/.server/server/plugins/engine/options.js +2 -1
- package/.server/server/plugins/engine/options.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +14 -6
- package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +2 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js +2 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +7 -1
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +56 -10
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +2 -2
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +3 -4
- package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +10 -4
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/helpers/pages.js +2 -1
- package/.server/server/plugins/engine/pageControllers/helpers/pages.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +35 -2
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js +100 -3
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.js +24 -3
- package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
- package/.server/server/plugins/engine/plugin.js +3 -0
- package/.server/server/plugins/engine/plugin.js.map +1 -1
- package/.server/server/plugins/engine/referenceNumbers.d.ts +1 -0
- package/.server/server/plugins/engine/referenceNumbers.js +1 -0
- package/.server/server/plugins/engine/referenceNumbers.js.map +1 -1
- package/.server/server/plugins/engine/routes/index.js +9 -4
- package/.server/server/plugins/engine/routes/index.js.map +1 -1
- package/.server/server/plugins/engine/types/enums.d.ts +3 -3
- package/.server/server/plugins/engine/types/enums.js +5 -4
- package/.server/server/plugins/engine/types/enums.js.map +1 -1
- package/.server/server/plugins/engine/types/schema.js +15 -4
- package/.server/server/plugins/engine/types/schema.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +24 -2
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/plugins/engine/unavailable-response.js +5 -2
- package/.server/server/plugins/engine/unavailable-response.js.map +1 -1
- package/.server/server/plugins/engine/views/components/_location-field-base.html +4 -2
- package/.server/server/plugins/engine/views/components/fileuploadfield.html +1 -1
- package/.server/server/plugins/engine/views/components/geospatialfield.html +1 -0
- package/.server/server/plugins/engine/views/components/osgridreffield.html +4 -1
- package/.server/server/plugins/engine/views/components/trackingfield.html +3 -0
- package/.server/server/plugins/engine/views/components/ukaddressfield.html +1 -1
- package/.server/server/plugins/engine/views/file-upload.html +1 -1
- package/.server/server/plugins/engine/views/summary.html +1 -0
- package/.server/server/plugins/engine/views/unavailable.html +14 -11
- package/.server/server/plugins/map/routes/index.d.ts +4 -0
- package/.server/server/plugins/map/routes/index.js +12 -4
- package/.server/server/plugins/map/routes/index.js.map +1 -1
- package/.server/server/plugins/map/routes/index.test.js +7 -0
- package/.server/server/plugins/map/routes/index.test.js.map +1 -0
- package/.server/server/plugins/map/routes/vts/README.md +38 -0
- package/.server/server/plugins/map/routes/vts/countries-5dp.geojson +4 -0
- package/.server/server/plugins/map/routes/vts/countries.geojson +10 -39283
- package/.server/server/plugins/map/types.d.ts +24 -2
- package/.server/server/plugins/map/types.js +9 -2
- package/.server/server/plugins/map/types.js.map +1 -1
- package/.server/server/plugins/nunjucks/enviroment.test.js +11 -4
- package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.d.ts +9 -0
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js +17 -0
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
- package/.server/server/plugins/nunjucks/filters/index.d.ts +1 -0
- package/.server/server/plugins/nunjucks/filters/index.js +1 -0
- package/.server/server/plugins/nunjucks/filters/index.js.map +1 -1
- package/.server/server/plugins/payment/helper.d.ts +11 -1
- package/.server/server/plugins/payment/helper.js +18 -2
- package/.server/server/plugins/payment/helper.js.map +1 -1
- package/.server/server/plugins/payment/helper.test.js +2 -1
- package/.server/server/plugins/payment/helper.test.js.map +1 -1
- package/.server/server/plugins/payment/service.d.ts +2 -1
- package/.server/server/plugins/payment/service.js +5 -2
- package/.server/server/plugins/payment/service.js.map +1 -1
- package/.server/server/plugins/payment/service.test.js +7 -3
- package/.server/server/plugins/payment/service.test.js.map +1 -1
- package/.server/server/plugins/payment/types.d.ts +4 -0
- package/.server/server/plugins/payment/types.js +1 -0
- package/.server/server/plugins/payment/types.js.map +1 -1
- package/.server/server/plugins/postcode-lookup/models/index.d.ts +249 -3
- package/.server/server/plugins/postcode-lookup/models/index.js +103 -36
- package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
- package/.server/server/plugins/postcode-lookup/routes/index.d.ts +15 -1
- package/.server/server/plugins/postcode-lookup/routes/index.js +64 -18
- package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
- package/.server/server/plugins/postcode-lookup/routes/index.test.js +84 -0
- package/.server/server/plugins/postcode-lookup/routes/index.test.js.map +1 -0
- package/.server/server/plugins/postcode-lookup/types.d.ts +12 -0
- package/.server/server/plugins/postcode-lookup/types.js +6 -1
- package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
- package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
- package/.server/server/utils/type-utils.d.ts +1 -2
- package/.server/server/utils/type-utils.js +0 -3
- package/.server/server/utils/type-utils.js.map +1 -1
- package/.server/server/utils/utils.d.ts +6 -0
- package/.server/server/utils/utils.js +18 -1
- package/.server/server/utils/utils.js.map +1 -1
- package/.server/server/utils/utils.test.js +21 -1
- package/.server/server/utils/utils.test.js.map +1 -1
- package/.server/typings/geodesy/index.d.js +2 -0
- package/.server/typings/geodesy/index.d.js.map +1 -0
- package/.server/typings/hapi/index.d.js.map +1 -1
- package/package.json +24 -9
- package/src/client/javascripts/file-upload.js +11 -3
- package/src/client/javascripts/geospatial-map.js +181 -86
- package/src/client/javascripts/govuk.js +2 -0
- package/src/client/javascripts/location-map.js +62 -6
- package/src/client/javascripts/map-constants.js +3 -0
- package/src/client/javascripts/map.js +66 -9
- package/src/client/javascripts/maps.js +5 -0
- package/src/client/javascripts/shared.js +1 -4
- package/src/client/javascripts/sssi-dataset.js +39 -41
- package/src/client/stylesheets/maps.scss +4 -0
- package/src/client/stylesheets/shared.scss +1 -5
- package/src/server/constants.js +2 -0
- package/src/server/forms/components.json +8 -0
- package/src/server/forms/register-as-a-unicorn-breeder.yaml +4 -0
- package/src/server/plugins/engine/__stubs__/definitions.ts +155 -0
- package/src/server/plugins/engine/components/AutocompleteField.ts +20 -0
- package/src/server/plugins/engine/components/CheckboxesField.ts +41 -8
- package/src/server/plugins/engine/components/ComponentBase.ts +6 -4
- package/src/server/plugins/engine/components/ComponentCollection.ts +17 -15
- package/src/server/plugins/engine/components/DatePartsField.ts +20 -9
- package/src/server/plugins/engine/components/DeclarationField.ts +10 -10
- package/src/server/plugins/engine/components/EastingNorthingField.ts +185 -89
- package/src/server/plugins/engine/components/EmailAddressField.ts +2 -1
- package/src/server/plugins/engine/components/FileUploadField.ts +46 -5
- package/src/server/plugins/engine/components/FormComponent.ts +6 -5
- package/src/server/plugins/engine/components/GeospatialField.ts +47 -9
- package/src/server/plugins/engine/components/LatLongField.ts +128 -58
- package/src/server/plugins/engine/components/ListFormComponent.ts +4 -4
- package/src/server/plugins/engine/components/LocationFieldBase.ts +41 -8
- package/src/server/plugins/engine/components/LocationFieldHelpers.ts +28 -14
- package/src/server/plugins/engine/components/Markdown.ts +2 -3
- package/src/server/plugins/engine/components/MonthYearField.ts +20 -15
- package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +9 -3
- package/src/server/plugins/engine/components/NumberField.ts +24 -0
- package/src/server/plugins/engine/components/OsGridRefField.ts +22 -3
- package/src/server/plugins/engine/components/PaymentField.ts +9 -4
- package/src/server/plugins/engine/components/TrackingField.ts +64 -0
- package/src/server/plugins/engine/components/UkAddressField.ts +30 -7
- package/src/server/plugins/engine/components/YesNoField.ts +27 -9
- package/src/server/plugins/engine/components/helpers/components.ts +8 -3
- package/src/server/plugins/engine/components/helpers/geospatial.ts +87 -24
- package/src/server/plugins/engine/components/helpers/index.ts +64 -1
- package/src/server/plugins/engine/components/index.ts +1 -0
- package/src/server/plugins/engine/components/types.ts +1 -0
- package/src/server/plugins/engine/errors.ts +78 -0
- package/src/server/plugins/engine/form-availability.ts +8 -2
- package/src/server/plugins/engine/form-context.ts +4 -2
- package/src/server/plugins/engine/helpers.ts +52 -5
- package/src/server/plugins/engine/i18n/buildValidationMessages.ts +16 -8
- package/src/server/plugins/engine/i18n/createFormTranslator.ts +43 -12
- package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +7 -1
- package/src/server/plugins/engine/i18n/form.ts +54 -0
- package/src/server/plugins/engine/i18n/languages.ts +19 -0
- package/src/server/plugins/engine/i18n/translations/cy.json +176 -7
- package/src/server/plugins/engine/i18n/translations/en-GB.json +110 -6
- package/src/server/plugins/engine/i18n/types.ts +2 -0
- package/src/server/plugins/engine/index.ts +7 -0
- package/src/server/plugins/engine/models/FormModel.ts +46 -23
- package/src/server/plugins/engine/models/SummaryViewModel.ts +6 -5
- package/src/server/plugins/engine/models/types.ts +31 -0
- package/src/server/plugins/engine/models/unavailable-view-model.ts +26 -5
- package/src/server/plugins/engine/options.js +2 -1
- package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +18 -7
- package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -1
- package/src/server/plugins/engine/outputFormatters/machine/v2.ts +3 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +60 -9
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +2 -2
- package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +2 -2
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +15 -4
- package/src/server/plugins/engine/pageControllers/helpers/pages.ts +2 -1
- package/src/server/plugins/engine/pageControllers/helpers/submission.ts +143 -4
- package/src/server/plugins/engine/pageControllers/validationOptions.ts +29 -4
- package/src/server/plugins/engine/plugin.ts +6 -0
- package/src/server/plugins/engine/referenceNumbers.ts +2 -0
- package/src/server/plugins/engine/routes/index.ts +9 -3
- package/src/server/plugins/engine/types/enums.ts +4 -3
- package/src/server/plugins/engine/types/schema.ts +22 -5
- package/src/server/plugins/engine/types.ts +28 -1
- package/src/server/plugins/engine/unavailable-response.ts +6 -2
- package/src/server/plugins/engine/views/components/_location-field-base.html +4 -2
- package/src/server/plugins/engine/views/components/fileuploadfield.html +1 -1
- package/src/server/plugins/engine/views/components/geospatialfield.html +1 -0
- package/src/server/plugins/engine/views/components/osgridreffield.html +4 -1
- package/src/server/plugins/engine/views/components/trackingfield.html +3 -0
- package/src/server/plugins/engine/views/components/ukaddressfield.html +1 -1
- package/src/server/plugins/engine/views/file-upload.html +1 -1
- package/src/server/plugins/engine/views/summary.html +1 -0
- package/src/server/plugins/engine/views/unavailable.html +14 -11
- package/src/server/plugins/map/routes/index.js +29 -4
- package/src/server/plugins/map/routes/vts/README.md +38 -0
- package/src/server/plugins/map/routes/vts/countries-5dp.geojson +4 -0
- package/src/server/plugins/map/routes/vts/countries.geojson +10 -39283
- package/src/server/plugins/map/types.js +9 -2
- package/src/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
- package/src/server/plugins/nunjucks/filters/index.js +1 -0
- package/src/server/plugins/payment/helper.js +22 -2
- package/src/server/plugins/payment/service.js +6 -2
- package/src/server/plugins/payment/types.js +1 -0
- package/src/server/plugins/postcode-lookup/models/index.js +91 -46
- package/src/server/plugins/postcode-lookup/routes/index.js +96 -24
- package/src/server/plugins/postcode-lookup/types.js +6 -1
- package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
- package/src/server/utils/type-utils.ts +1 -11
- package/src/server/utils/utils.js +19 -1
- package/src/typings/geodesy/index.d.ts +18 -0
- package/src/typings/hapi/index.d.ts +2 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type ConditionEvaluationOutcome,
|
|
2
3
|
type ConditionWrapper,
|
|
3
4
|
type FormComponentsDef,
|
|
4
5
|
type Section
|
|
@@ -16,9 +17,39 @@ import {
|
|
|
16
17
|
type FormSubmissionError
|
|
17
18
|
} from '../types.js'
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* The result of evaluating a condition, keeping a failed evaluation distinct
|
|
22
|
+
* from one that legitimately returned `false`.
|
|
23
|
+
* @see {@link ExecutableCondition.evaluate}
|
|
24
|
+
*/
|
|
25
|
+
export interface ConditionEvaluation {
|
|
26
|
+
outcome: ConditionEvaluationOutcome
|
|
27
|
+
error?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A form condition paired with the parsed expression and callbacks needed to
|
|
32
|
+
* run it against a form submission state
|
|
33
|
+
* Created by `FormModel.makeCondition`
|
|
34
|
+
*/
|
|
19
35
|
export type ExecutableCondition = ConditionWrapper & {
|
|
36
|
+
/**
|
|
37
|
+
* Parsed expression for the condition's {@link ConditionWrapper.value},
|
|
38
|
+
* evaluated against a context built from the submission state
|
|
39
|
+
*/
|
|
20
40
|
expr: Expression
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Evaluates the condition, used for page routing and component visibility
|
|
44
|
+
* A failed evaluation is reported as `false`
|
|
45
|
+
*/
|
|
21
46
|
fn: (evaluationState: FormState) => boolean
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* As `fn`, but reports whether evaluation failed rather than defaulting a
|
|
50
|
+
* failure to `false`. Used to record condition outcomes on submission.
|
|
51
|
+
*/
|
|
52
|
+
evaluate: (evaluationState: FormState) => ConditionEvaluation
|
|
22
53
|
}
|
|
23
54
|
|
|
24
55
|
/**
|
|
@@ -1,19 +1,40 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type FormDefinition,
|
|
3
|
+
type FormMetadata,
|
|
4
|
+
type FormMetadataContact
|
|
5
|
+
} from '@defra/forms-model'
|
|
6
|
+
|
|
7
|
+
import { createFormTranslator } from '../i18n/createFormTranslator.js'
|
|
8
|
+
import { getAvailableLanguages } from '../i18n/languages.js'
|
|
9
|
+
import { type Translator } from '../types/index.js'
|
|
2
10
|
|
|
3
11
|
export interface UnavailableViewModel {
|
|
4
12
|
pageTitle: string
|
|
5
13
|
formTitle: string
|
|
6
14
|
organisationName: string
|
|
7
15
|
contact?: FormMetadataContact
|
|
16
|
+
context: { translator: Translator }
|
|
17
|
+
language: string
|
|
18
|
+
languages: { code: string; name: string }[]
|
|
8
19
|
}
|
|
9
20
|
|
|
10
21
|
export function unavailableViewModel(
|
|
11
|
-
metadata: FormMetadata
|
|
22
|
+
metadata: FormMetadata,
|
|
23
|
+
definition: FormDefinition | undefined,
|
|
24
|
+
language: string
|
|
12
25
|
): UnavailableViewModel {
|
|
26
|
+
const translator = createFormTranslator(metadata, definition, language)
|
|
27
|
+
const { t, tForm } = translator
|
|
13
28
|
return {
|
|
14
|
-
pageTitle: '
|
|
15
|
-
formTitle: metadata.title,
|
|
29
|
+
pageTitle: t('pages.formUnavailable.title'),
|
|
30
|
+
formTitle: tForm('title') || metadata.title,
|
|
16
31
|
organisationName: metadata.organisation,
|
|
17
|
-
contact: metadata.contact
|
|
32
|
+
contact: metadata.contact,
|
|
33
|
+
context: { translator },
|
|
34
|
+
language,
|
|
35
|
+
// Always get Welsh and English
|
|
36
|
+
languages: getAvailableLanguages({
|
|
37
|
+
metadata: { translations: { cy: {} } }
|
|
38
|
+
} as unknown as FormDefinition)
|
|
18
39
|
}
|
|
19
40
|
}
|
|
@@ -26,7 +26,8 @@ const pluginRegistrationOptionsSchema = Joi.object({
|
|
|
26
26
|
saveAndExit: Joi.function().optional(),
|
|
27
27
|
ordnanceSurveyApiKey: Joi.string().optional(),
|
|
28
28
|
ordnanceSurveyApiSecret: Joi.string().optional(),
|
|
29
|
-
getLanguage: Joi.function().optional()
|
|
29
|
+
getLanguage: Joi.function().optional(),
|
|
30
|
+
generateReferenceNumber: Joi.function().optional()
|
|
30
31
|
})
|
|
31
32
|
|
|
32
33
|
/**
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Engine,
|
|
2
3
|
type FormMetadata,
|
|
3
4
|
type SubmitResponsePayload
|
|
4
5
|
} from '@defra/forms-model'
|
|
5
6
|
|
|
7
|
+
import { EN_GB } from '../../../../constants.js'
|
|
6
8
|
import {
|
|
7
9
|
getFormVersion,
|
|
8
10
|
type checkFormStatus
|
|
@@ -10,6 +12,7 @@ import {
|
|
|
10
12
|
import { type FormModel } from '../../models/FormModel.js'
|
|
11
13
|
import { type DetailItem } from '../../models/types.js'
|
|
12
14
|
import { categoriseData } from '../machine/v2.js'
|
|
15
|
+
import { buildConditionEvaluations } from '../../pageControllers/helpers/submission.js'
|
|
13
16
|
import { FormAdapterSubmissionSchemaVersion } from '../../types/enums.js'
|
|
14
17
|
import {
|
|
15
18
|
type FormAdapterSubmissionMessageData,
|
|
@@ -42,18 +45,14 @@ export function format(
|
|
|
42
45
|
formSlug: formMetadata?.slug ?? '',
|
|
43
46
|
status: formStatus.state,
|
|
44
47
|
isPreview: formStatus.isPreview,
|
|
45
|
-
notificationEmail: formMetadata?.notificationEmail ?? ''
|
|
48
|
+
notificationEmail: formMetadata?.notificationEmail ?? '',
|
|
49
|
+
language: context.translator?.language ?? EN_GB
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
if (versionMetadata) {
|
|
49
53
|
meta.versionMetadata = versionMetadata
|
|
50
54
|
}
|
|
51
55
|
|
|
52
|
-
const definitionLanguage = model.def.metadata?.language
|
|
53
|
-
if (typeof definitionLanguage === 'string') {
|
|
54
|
-
meta.language = definitionLanguage
|
|
55
|
-
}
|
|
56
|
-
|
|
57
56
|
const main = Object.fromEntries(
|
|
58
57
|
Object.entries(v2Main).map(([key, value]) => {
|
|
59
58
|
if (value === undefined) {
|
|
@@ -76,7 +75,19 @@ export function format(
|
|
|
76
75
|
const payload: FormAdapterSubmissionMessagePayload = {
|
|
77
76
|
meta,
|
|
78
77
|
data,
|
|
79
|
-
result
|
|
78
|
+
result,
|
|
79
|
+
|
|
80
|
+
// Recorded here because only the engine holds the walked evaluation state
|
|
81
|
+
// the conditions were judged against; forms-notify-listener receives the
|
|
82
|
+
// flat submitted answers and resolves the outputs that qualify from these
|
|
83
|
+
// outcomes alone. Condition ids are only stable in V2, so a V1 definition
|
|
84
|
+
// has nothing to report - the property is still emitted, because its
|
|
85
|
+
// absence is what marks a message as predating this and sends the listener
|
|
86
|
+
// down its legacy path.
|
|
87
|
+
conditionEvaluations:
|
|
88
|
+
model.engine === Engine.V2
|
|
89
|
+
? buildConditionEvaluations(model, context)
|
|
90
|
+
: []
|
|
80
91
|
}
|
|
81
92
|
|
|
82
93
|
return JSON.stringify(payload)
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
import { addDays, format as dateFormat } from 'date-fns'
|
|
6
6
|
|
|
7
7
|
import { config } from '../../../../../config/index.js'
|
|
8
|
+
import { EN_GB } from '../../../../constants.js'
|
|
8
9
|
import { getAnswer } from '../../components/helpers/components.js'
|
|
9
10
|
import { escapeMarkdown } from '../../components/helpers/index.js'
|
|
10
11
|
import { PaymentField } from '../../components/index.js'
|
|
@@ -116,7 +117,7 @@ function appendPaymentSection(paymentItems: DetailItem[], lines: string[]) {
|
|
|
116
117
|
|
|
117
118
|
const formattedAmount = formatCurrency(paymentState.amount)
|
|
118
119
|
const dateOfPayment = paymentState.preAuth?.createdAt
|
|
119
|
-
? formatPaymentDate(paymentState.preAuth.createdAt)
|
|
120
|
+
? formatPaymentDate(paymentState.preAuth.createdAt, EN_GB)
|
|
120
121
|
: ''
|
|
121
122
|
|
|
122
123
|
lines.push(
|
|
@@ -28,6 +28,7 @@ interface PaymentOutput {
|
|
|
28
28
|
reference: string
|
|
29
29
|
amount: number
|
|
30
30
|
description: string
|
|
31
|
+
descriptionInEng?: string
|
|
31
32
|
createdAt: string
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -93,6 +94,7 @@ export function format(
|
|
|
93
94
|
* reference: 'REF-123',
|
|
94
95
|
* amount: 10.00,
|
|
95
96
|
* description: 'Application fee',
|
|
97
|
+
* descriptionInEng: 'Applicaiton fee',
|
|
96
98
|
* createdAt: '2025-01-23T10:30:00.000Z'
|
|
97
99
|
* }
|
|
98
100
|
* }
|
|
@@ -204,6 +206,7 @@ function extractPayment(
|
|
|
204
206
|
reference: paymentState.reference,
|
|
205
207
|
amount: paymentState.amount,
|
|
206
208
|
description: paymentState.description,
|
|
209
|
+
descriptionInEng: item.field.def.options.description,
|
|
207
210
|
createdAt: paymentState.preAuth?.createdAt ?? ''
|
|
208
211
|
}
|
|
209
212
|
}
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
type FormRequestPayload,
|
|
43
43
|
type FormResponseToolkit
|
|
44
44
|
} from '../../../routes/types.js'
|
|
45
|
+
import { joinWithOr } from '../../../utils/utils.js'
|
|
45
46
|
|
|
46
47
|
const MAX_UPLOADS = 25
|
|
47
48
|
const CDP_UPLOAD_TIMEOUT_MS = 60000 // 1 minute
|
|
@@ -188,17 +189,19 @@ export class FileUploadPageController extends QuestionPageController {
|
|
|
188
189
|
|
|
189
190
|
const { filename } = fileToRemove.status.form.file
|
|
190
191
|
|
|
191
|
-
const
|
|
192
|
+
const translator = this.getTranslator(request)
|
|
193
|
+
const { t } = translator
|
|
192
194
|
|
|
193
195
|
return h.view(this.fileDeleteViewName, {
|
|
194
196
|
...viewModel,
|
|
195
197
|
context,
|
|
196
198
|
backLink: this.getBackLink(request, context, t),
|
|
197
|
-
pageTitle:
|
|
199
|
+
pageTitle: t('pages.fileUpload.removeFileTitle'),
|
|
198
200
|
itemTitle: filename,
|
|
199
|
-
confirmation: { text: '
|
|
200
|
-
buttonConfirm: { text: '
|
|
201
|
-
buttonCancel: { text: '
|
|
201
|
+
confirmation: { text: t('pages.fileUpload.removeFileBody') },
|
|
202
|
+
buttonConfirm: { text: t('pages.fileUpload.removeFileButton') },
|
|
203
|
+
buttonCancel: { text: t('pages.fileUpload.cancel') },
|
|
204
|
+
t
|
|
202
205
|
} satisfies ItemDeletePageViewModel)
|
|
203
206
|
}
|
|
204
207
|
}
|
|
@@ -224,7 +227,7 @@ export class FileUploadPageController extends QuestionPageController {
|
|
|
224
227
|
}
|
|
225
228
|
}
|
|
226
229
|
|
|
227
|
-
getErrors(details?: ValidationErrorItem[]) {
|
|
230
|
+
getErrors(details?: ValidationErrorItem[], language?: string) {
|
|
228
231
|
const { fileUpload } = this
|
|
229
232
|
|
|
230
233
|
if (details) {
|
|
@@ -237,7 +240,7 @@ export class FileUploadPageController extends QuestionPageController {
|
|
|
237
240
|
if (!isUploadError || isUploadRootError) {
|
|
238
241
|
// The error is for the root of the upload or another
|
|
239
242
|
// field on the page so defer to the getError helper
|
|
240
|
-
errors.push(getError(error))
|
|
243
|
+
errors.push(getError(language, error))
|
|
241
244
|
} else {
|
|
242
245
|
const { context, path, type } = error
|
|
243
246
|
|
|
@@ -266,6 +269,7 @@ export class FileUploadPageController extends QuestionPageController {
|
|
|
266
269
|
): FeaturedFormPageViewModel {
|
|
267
270
|
const { fileUpload } = this
|
|
268
271
|
const { state } = context
|
|
272
|
+
const { t } = translator
|
|
269
273
|
|
|
270
274
|
const upload = this.getUploadFromState(state)
|
|
271
275
|
|
|
@@ -277,6 +281,19 @@ export class FileUploadPageController extends QuestionPageController {
|
|
|
277
281
|
({ model }) => model.id === fileUpload.name
|
|
278
282
|
)
|
|
279
283
|
|
|
284
|
+
formComponent.model.upload = {
|
|
285
|
+
count: formComponent.model.upload?.count ?? 0,
|
|
286
|
+
summaryList: formComponent.model.upload?.summaryList ?? { rows: [] },
|
|
287
|
+
uploadingLabel: t('components.fileUploadField.uploading')
|
|
288
|
+
}
|
|
289
|
+
formComponent.model = {
|
|
290
|
+
...formComponent.model,
|
|
291
|
+
javascript: true,
|
|
292
|
+
chooseFilesButtonText: t('components.fileUploadField.chooseFile'),
|
|
293
|
+
dropInstructionText: t('components.fileUploadField.dropFile'),
|
|
294
|
+
noFileChosenText: t('components.fileUploadField.noFileChosen')
|
|
295
|
+
}
|
|
296
|
+
|
|
280
297
|
const index = components.indexOf(formComponent)
|
|
281
298
|
|
|
282
299
|
const proxyUrl = getProxyUrlForLocalDevelopment(upload?.uploadUrl)
|
|
@@ -290,7 +307,8 @@ export class FileUploadPageController extends QuestionPageController {
|
|
|
290
307
|
// Split out components before/after
|
|
291
308
|
componentsBefore: components.slice(0, index),
|
|
292
309
|
components: components.slice(index),
|
|
293
|
-
proxyUrl
|
|
310
|
+
proxyUrl,
|
|
311
|
+
t
|
|
294
312
|
}
|
|
295
313
|
}
|
|
296
314
|
|
|
@@ -441,6 +459,9 @@ export class FileUploadPageController extends QuestionPageController {
|
|
|
441
459
|
|
|
442
460
|
const allErrors: FormSubmissionError[] = []
|
|
443
461
|
|
|
462
|
+
const translator = this.getTranslator(request)
|
|
463
|
+
const { t } = translator
|
|
464
|
+
|
|
444
465
|
for (const file of uploadedFiles) {
|
|
445
466
|
if (file.fileStatus === FileStatus.complete) {
|
|
446
467
|
const perFileState: FileState = {
|
|
@@ -455,7 +476,14 @@ export class FileUploadPageController extends QuestionPageController {
|
|
|
455
476
|
// Collect the error for rejected/pending files.
|
|
456
477
|
const { fileUpload } = this
|
|
457
478
|
const name = fileUpload.name
|
|
458
|
-
const
|
|
479
|
+
const errorParams = this.expandErrorParams(
|
|
480
|
+
file.errorParams,
|
|
481
|
+
t('common.or')
|
|
482
|
+
)
|
|
483
|
+
const text = t(
|
|
484
|
+
`pages.fileUpload.${file.errorCode ?? 'FILE_ERROR_UNKNOWN'}`,
|
|
485
|
+
errorParams
|
|
486
|
+
)
|
|
459
487
|
allErrors.push({ path: [name], href: `#${name}`, name, text })
|
|
460
488
|
}
|
|
461
489
|
}
|
|
@@ -472,6 +500,29 @@ export class FileUploadPageController extends QuestionPageController {
|
|
|
472
500
|
}
|
|
473
501
|
}
|
|
474
502
|
|
|
503
|
+
/**
|
|
504
|
+
* Process the error parameters so any arrays get expanded (joined), ready to be passed into the error message
|
|
505
|
+
* @param errorParams - received from the file upload (may be a number, a string, or a string array)
|
|
506
|
+
* @param finalSeparator - 'or' in English, and 'neu' in Welsh
|
|
507
|
+
*/
|
|
508
|
+
private expandErrorParams(
|
|
509
|
+
errorParams: Record<string, number | string | string[]> | undefined,
|
|
510
|
+
finalSeparator: string
|
|
511
|
+
) {
|
|
512
|
+
if (!errorParams) {
|
|
513
|
+
return {}
|
|
514
|
+
}
|
|
515
|
+
const expanded = {} as Record<string, number | string>
|
|
516
|
+
for (const [key, value] of Object.entries(errorParams)) {
|
|
517
|
+
if (Array.isArray(value)) {
|
|
518
|
+
expanded[key] = joinWithOr(value, finalSeparator)
|
|
519
|
+
} else {
|
|
520
|
+
expanded[key] = value
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return expanded
|
|
524
|
+
}
|
|
525
|
+
|
|
475
526
|
/**
|
|
476
527
|
* Checks the payload for a file getting removed
|
|
477
528
|
* and removes it from the upload files if found
|
|
@@ -364,8 +364,8 @@ export class QuestionPageController extends PageController {
|
|
|
364
364
|
return this.collection.getStateFromValidForm(payload)
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
getErrors(details?: ValidationErrorItem[]) {
|
|
368
|
-
return getErrors(details)
|
|
367
|
+
getErrors(details?: ValidationErrorItem[], language?: string) {
|
|
368
|
+
return getErrors(language, details)
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
async getState(request: AnyFormRequest) {
|
|
@@ -406,9 +406,9 @@ export class RepeatPageController extends QuestionPageController {
|
|
|
406
406
|
const { query } = request
|
|
407
407
|
const { isForceAccess, errors } = context
|
|
408
408
|
|
|
409
|
-
const { t } = translator
|
|
409
|
+
const { t, tPage } = translator
|
|
410
410
|
|
|
411
|
-
const
|
|
411
|
+
const title = tPage(this.pageDef, 'repeatTitle') || repeat.options.title
|
|
412
412
|
|
|
413
413
|
const summaryList: SummaryList = {
|
|
414
414
|
classes: 'govuk-summary-list--long-actions',
|
|
@@ -114,7 +114,7 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
114
114
|
viewModel.paymentDetails = this.buildPaymentDetails(
|
|
115
115
|
paymentField,
|
|
116
116
|
paymentState,
|
|
117
|
-
|
|
117
|
+
translator
|
|
118
118
|
)
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -151,8 +151,9 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
151
151
|
paymentState: NonNullable<
|
|
152
152
|
ReturnType<PaymentField['getPaymentStateFromState']>
|
|
153
153
|
>,
|
|
154
|
-
|
|
154
|
+
translator: Translator
|
|
155
155
|
) {
|
|
156
|
+
const { t } = translator
|
|
156
157
|
const rows = [
|
|
157
158
|
{
|
|
158
159
|
key: { text: t('pages.summary.paymentFor') },
|
|
@@ -171,7 +172,12 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
171
172
|
if (paymentState.preAuth?.createdAt) {
|
|
172
173
|
rows.push({
|
|
173
174
|
key: { text: t('pages.summary.dateOfPayment') },
|
|
174
|
-
value: {
|
|
175
|
+
value: {
|
|
176
|
+
text: formatPaymentDate(
|
|
177
|
+
paymentState.preAuth.createdAt,
|
|
178
|
+
translator.language
|
|
179
|
+
)
|
|
180
|
+
}
|
|
175
181
|
})
|
|
176
182
|
}
|
|
177
183
|
|
|
@@ -557,7 +563,12 @@ function submitData(
|
|
|
557
563
|
retrievalKey,
|
|
558
564
|
referenceNumber,
|
|
559
565
|
main: buildMainRecords(items, translator),
|
|
560
|
-
repeaters: buildRepeaterRecords(items, translator)
|
|
566
|
+
repeaters: buildRepeaterRecords(items, translator),
|
|
567
|
+
// Only populate the language property if the form is multi-language enabled
|
|
568
|
+
// @ts-expect-error - dynamic language property
|
|
569
|
+
language: model.def.metadata?.translations?.cy
|
|
570
|
+
? translator.language
|
|
571
|
+
: undefined
|
|
561
572
|
}
|
|
562
573
|
return submit(payload)
|
|
563
574
|
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type Page
|
|
5
5
|
} from '@defra/forms-model'
|
|
6
6
|
|
|
7
|
+
import { UnknownPageControllerError } from '../../errors.js'
|
|
7
8
|
import { type FormModel } from '../../models/index.js'
|
|
8
9
|
import * as PageControllers from '../index.js'
|
|
9
10
|
|
|
@@ -66,7 +67,7 @@ export function createPage(model: FormModel, pageDef: Page) {
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
if (typeof controller === 'undefined') {
|
|
69
|
-
throw new
|
|
70
|
+
throw new UnknownPageControllerError(pageDef.controller)
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
return controller
|
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isConditionWrapperV2,
|
|
3
|
+
type ConditionDataV2,
|
|
4
|
+
type ConditionRefDataV2,
|
|
5
|
+
type ConditionWrapperV2,
|
|
6
|
+
type SubmitConditionEvaluation,
|
|
7
|
+
type SubmitConditionReference,
|
|
8
|
+
type SubmitPayload
|
|
9
|
+
} from '@defra/forms-model'
|
|
2
10
|
|
|
3
11
|
import { GeospatialField } from '../../components/GeospatialField.js'
|
|
4
12
|
import { PaymentField } from '../../components/PaymentField.js'
|
|
5
13
|
import { getAnswer } from '../../components/helpers/components.js'
|
|
6
14
|
import { type Translator } from '../../i18n/types.js'
|
|
15
|
+
import { type FormModel } from '../../models/FormModel.js'
|
|
7
16
|
import {
|
|
8
17
|
type DetailItem,
|
|
9
18
|
type DetailItemField
|
|
10
19
|
} from '../../models/types.js'
|
|
20
|
+
import {
|
|
21
|
+
type FormContext,
|
|
22
|
+
type FormState,
|
|
23
|
+
type FormStateValue
|
|
24
|
+
} from '../../types.js'
|
|
11
25
|
import {
|
|
12
26
|
formatCurrency,
|
|
13
27
|
formatPaymentDate
|
|
@@ -36,7 +50,7 @@ export function buildMainRecords(
|
|
|
36
50
|
|
|
37
51
|
for (const item of fieldItems) {
|
|
38
52
|
if (item.field instanceof PaymentField) {
|
|
39
|
-
records.push(...buildPaymentRecords(item))
|
|
53
|
+
records.push(...buildPaymentRecords(item, translator))
|
|
40
54
|
} else if (item.field instanceof GeospatialField) {
|
|
41
55
|
// Stringify of GeoJSON is done here rather than inside `getContextValueFromState`
|
|
42
56
|
// so we don't incur the overhead of JSON.stringify on every request when building context
|
|
@@ -67,7 +81,10 @@ export function buildMainRecords(
|
|
|
67
81
|
*
|
|
68
82
|
* Returns an empty array if no payment state exists.
|
|
69
83
|
*/
|
|
70
|
-
export function buildPaymentRecords(
|
|
84
|
+
export function buildPaymentRecords(
|
|
85
|
+
item: DetailItemField,
|
|
86
|
+
translator: Translator
|
|
87
|
+
): SubmitRecord[] {
|
|
71
88
|
const paymentState = (item.field as PaymentField).getPaymentStateFromState(
|
|
72
89
|
item.state
|
|
73
90
|
)
|
|
@@ -96,7 +113,7 @@ export function buildPaymentRecords(item: DetailItemField): SubmitRecord[] {
|
|
|
96
113
|
name: `${item.name}_paymentDate`,
|
|
97
114
|
title: 'Payment date',
|
|
98
115
|
value: paymentState.preAuth?.createdAt
|
|
99
|
-
? formatPaymentDate(paymentState.preAuth.createdAt)
|
|
116
|
+
? formatPaymentDate(paymentState.preAuth.createdAt, translator.language)
|
|
100
117
|
: ''
|
|
101
118
|
}
|
|
102
119
|
]
|
|
@@ -138,3 +155,125 @@ export function buildRepeaterRecords(
|
|
|
138
155
|
)
|
|
139
156
|
}))
|
|
140
157
|
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Records the outcome of every condition in the form definition, evaluated
|
|
161
|
+
* against the answers as they stand at the point of submission.
|
|
162
|
+
*
|
|
163
|
+
* Evaluated here rather than by the consumer because only the engine holds
|
|
164
|
+
* the context to evaluate against: `evaluationState` is built by walking the
|
|
165
|
+
* form from its start page along the path taken, applying page conditions as
|
|
166
|
+
* it goes. A consumer receives the flat submitted answers, not that walked
|
|
167
|
+
* state, and reproducing the walk in a second codebase would leave two
|
|
168
|
+
* implementations of the same logic free to diverge.
|
|
169
|
+
*
|
|
170
|
+
* Each record carries the components the condition depends on and whether each
|
|
171
|
+
* was answered. An unanswered question still yields a boolean - negative
|
|
172
|
+
* operators such as "is not" return `true` against the seeded `null` - so the
|
|
173
|
+
* outcome alone cannot be read as evidence that the user gave that answer.
|
|
174
|
+
*
|
|
175
|
+
* V2 definitions only. `conditionId` is the V2 condition id, and the
|
|
176
|
+
* references are resolved from the component ids V2 conditions carry - V1
|
|
177
|
+
* conditions reference components by name, and V1 components need not have
|
|
178
|
+
* an id at all.
|
|
179
|
+
*/
|
|
180
|
+
export function buildConditionEvaluations(
|
|
181
|
+
model: FormModel,
|
|
182
|
+
context: FormContext
|
|
183
|
+
): SubmitConditionEvaluation[] {
|
|
184
|
+
const { evaluationState } = context
|
|
185
|
+
|
|
186
|
+
return model.def.conditions
|
|
187
|
+
.filter(isConditionWrapperV2)
|
|
188
|
+
.flatMap((conditionDef) => {
|
|
189
|
+
const condition = model.conditions[conditionDef.id]
|
|
190
|
+
|
|
191
|
+
if (!condition) {
|
|
192
|
+
return []
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const { outcome } = condition.evaluate(evaluationState)
|
|
196
|
+
|
|
197
|
+
const references = collectReferences(model, conditionDef, evaluationState)
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
conditionId: conditionDef.id,
|
|
201
|
+
outcome,
|
|
202
|
+
references: [...references.values()]
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Whether a component held an answer at the point a condition was evaluated.
|
|
209
|
+
*
|
|
210
|
+
* The engine seeds every component in `evaluationState` with `null` before the
|
|
211
|
+
* page walk begins, so an unanswered question is present but empty rather than
|
|
212
|
+
* absent.
|
|
213
|
+
* @see {@link FormModel.initialiseContext}
|
|
214
|
+
*/
|
|
215
|
+
export function isAnswered(value: FormStateValue | undefined) {
|
|
216
|
+
if (value === undefined || value === null) {
|
|
217
|
+
return false
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (Array.isArray(value)) {
|
|
221
|
+
return value.length > 0
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return value !== ''
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function isConditionDataV2(
|
|
228
|
+
item: ConditionDataV2 | ConditionRefDataV2
|
|
229
|
+
): item is ConditionDataV2 {
|
|
230
|
+
return 'componentId' in item
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Recursive function that collects every component a condition depends on, following nested condition
|
|
235
|
+
* references. Results are keyed by component id so a component referenced more
|
|
236
|
+
* than once is reported once.
|
|
237
|
+
*/
|
|
238
|
+
function collectReferences(
|
|
239
|
+
model: FormModel,
|
|
240
|
+
conditionDef: ConditionWrapperV2,
|
|
241
|
+
evaluationState: FormState,
|
|
242
|
+
references: Map<string, SubmitConditionReference> = new Map<
|
|
243
|
+
string,
|
|
244
|
+
SubmitConditionReference
|
|
245
|
+
>(),
|
|
246
|
+
visited: Set<string> = new Set<string>()
|
|
247
|
+
) {
|
|
248
|
+
if (visited.has(conditionDef.id)) {
|
|
249
|
+
return references
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
visited.add(conditionDef.id)
|
|
253
|
+
|
|
254
|
+
for (const item of conditionDef.items) {
|
|
255
|
+
if (isConditionDataV2(item)) {
|
|
256
|
+
const component = model.getComponentById(item.componentId)
|
|
257
|
+
|
|
258
|
+
// A condition referencing a component that no longer exists cannot be
|
|
259
|
+
// resolved to a name, so there is nothing meaningful to report for it
|
|
260
|
+
if (component) {
|
|
261
|
+
references.set(item.componentId, {
|
|
262
|
+
componentId: item.componentId,
|
|
263
|
+
componentName: component.name,
|
|
264
|
+
answered: isAnswered(evaluationState[component.name])
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
continue
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const referenced = model.getConditionById(item.conditionId)
|
|
272
|
+
|
|
273
|
+
if (referenced) {
|
|
274
|
+
collectReferences(model, referenced, evaluationState, references, visited)
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return references
|
|
279
|
+
}
|
|
@@ -26,7 +26,7 @@ export const opts = {
|
|
|
26
26
|
* import messageTemplate directly and get the English version.
|
|
27
27
|
*/
|
|
28
28
|
export const messageTemplate: ValidationMessages = buildValidationMessages(
|
|
29
|
-
(key) => t(key, 'en-GB')
|
|
29
|
+
(key, options) => t(key, 'en-GB', options)
|
|
30
30
|
)
|
|
31
31
|
|
|
32
32
|
export const messages: LanguageMessagesExt = {
|
|
@@ -58,14 +58,28 @@ export const messages: LanguageMessagesExt = {
|
|
|
58
58
|
'date.min': messageTemplate.dateMin,
|
|
59
59
|
'date.max': messageTemplate.dateMax,
|
|
60
60
|
|
|
61
|
-
'
|
|
61
|
+
'array.min': messageTemplate.arrayMin,
|
|
62
|
+
'array.max': messageTemplate.arrayMax,
|
|
63
|
+
'array.length': messageTemplate.arrayLength,
|
|
64
|
+
|
|
65
|
+
'features.min': messageTemplate.featuresMin,
|
|
66
|
+
'features.max': messageTemplate.featuresMax,
|
|
67
|
+
'features.length': messageTemplate.featuresLength,
|
|
68
|
+
|
|
69
|
+
'files.min': messageTemplate.filesMin,
|
|
70
|
+
'files.max': messageTemplate.filesMax,
|
|
71
|
+
'filees.length': messageTemplate.filesLength,
|
|
72
|
+
|
|
73
|
+
'object.invalidjson': messageTemplate.format,
|
|
74
|
+
|
|
75
|
+
'phoneNumber.invalid': messageTemplate.format
|
|
62
76
|
}
|
|
63
77
|
|
|
64
78
|
export const messagesPre: LanguageMessages =
|
|
65
79
|
messages as unknown as LanguageMessages
|
|
66
80
|
|
|
67
81
|
export function buildLanguageMessages(
|
|
68
|
-
t: (key: string) => string
|
|
82
|
+
t: (key: string, options?: Record<string, unknown>) => string
|
|
69
83
|
): LanguageMessages {
|
|
70
84
|
const vm = buildValidationMessages(t)
|
|
71
85
|
return {
|
|
@@ -76,6 +90,7 @@ export function buildLanguageMessages(
|
|
|
76
90
|
'string.email': vm.format,
|
|
77
91
|
'string.pattern.base': vm.pattern,
|
|
78
92
|
'string.maxWords': vm.maxWords,
|
|
93
|
+
'string.unicode': vm.unicode,
|
|
79
94
|
'number.base': vm.number,
|
|
80
95
|
'number.precision': vm.numberPrecision,
|
|
81
96
|
'number.integer': vm.numberInteger,
|
|
@@ -91,7 +106,17 @@ export function buildLanguageMessages(
|
|
|
91
106
|
'date.format': vm.dateFormat,
|
|
92
107
|
'date.min': vm.dateMin,
|
|
93
108
|
'date.max': vm.dateMax,
|
|
94
|
-
'
|
|
109
|
+
'array.min': vm.arrayMin,
|
|
110
|
+
'array.max': vm.arrayMax,
|
|
111
|
+
'array.length': vm.arrayLength,
|
|
112
|
+
'features.min': vm.featuresMin,
|
|
113
|
+
'features.max': vm.featuresMax,
|
|
114
|
+
'features.length': vm.featuresLength,
|
|
115
|
+
'files.min': vm.filesMin,
|
|
116
|
+
'files.max': vm.filesMax,
|
|
117
|
+
'files.length': vm.filesLength,
|
|
118
|
+
'object.invalidjson': vm.format,
|
|
119
|
+
'phoneNumber.invalid': vm.format
|
|
95
120
|
} as unknown as LanguageMessages
|
|
96
121
|
}
|
|
97
122
|
|