@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,7 +1,13 @@
|
|
|
1
1
|
import { type ComponentDef } from '@defra/forms-model'
|
|
2
|
-
import joi, {
|
|
2
|
+
import joi, {
|
|
3
|
+
type JoiExpression,
|
|
4
|
+
type LanguageMessages,
|
|
5
|
+
type ReferenceOptions
|
|
6
|
+
} from 'joi'
|
|
3
7
|
import lowerFirst from 'lodash/lowerFirst.js'
|
|
4
8
|
|
|
9
|
+
import { type Translator } from '../../i18n/types.js'
|
|
10
|
+
|
|
5
11
|
/**
|
|
6
12
|
* Prevent Markdown formatting
|
|
7
13
|
* @see {@link https://pandoc.org/chunkedhtml-demo/8.11-backslash-escapes.html}
|
|
@@ -66,3 +72,60 @@ export const lowerFirstExpressionOptions = {
|
|
|
66
72
|
*/
|
|
67
73
|
export const createLowerFirstExpression = (template: string): JoiExpression =>
|
|
68
74
|
joi.expression(template, lowerFirstExpressionOptions) as JoiExpression
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Joi's own LanguageMessages type only allows string values, but
|
|
78
|
+
* buildValidationMessages() returns JoiExpression for templated messages,
|
|
79
|
+
* which Joi accepts at runtime. This type covers both.
|
|
80
|
+
*/
|
|
81
|
+
type TranslatedValidationMessages = Record<string, string | JoiExpression>
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Keep the form author's custom validation message for any key they set,
|
|
85
|
+
* so translated defaults only fill in the keys the author left blank.
|
|
86
|
+
* A single customValidationMessage covers every key in the schema.
|
|
87
|
+
*/
|
|
88
|
+
export function withCustomValidationOverrides(
|
|
89
|
+
defaults: TranslatedValidationMessages,
|
|
90
|
+
customValidationMessage?: string,
|
|
91
|
+
customValidationMessages?: LanguageMessages
|
|
92
|
+
): LanguageMessages {
|
|
93
|
+
const messages: TranslatedValidationMessages = {}
|
|
94
|
+
|
|
95
|
+
// A global override for all messages is the value for all scenarios
|
|
96
|
+
if (customValidationMessage) {
|
|
97
|
+
for (const key of Object.keys(defaults)) {
|
|
98
|
+
messages[key] = customValidationMessage
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return messages as LanguageMessages
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// A default only fills a key that the user has not configured
|
|
105
|
+
const authorKeys = Object.keys(customValidationMessages ?? {})
|
|
106
|
+
|
|
107
|
+
for (const [key, message] of Object.entries(defaults)) {
|
|
108
|
+
if (!authorKeys.includes(key)) {
|
|
109
|
+
messages[key] = message
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return messages as LanguageMessages
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Translate a component label, in precedence order of errorDescription, then shortDesciption, then title
|
|
118
|
+
* @param {ComponentDef} component
|
|
119
|
+
* @param {Translator} translator
|
|
120
|
+
*/
|
|
121
|
+
export function getTranslatedLabel(
|
|
122
|
+
component: ComponentDef,
|
|
123
|
+
translator: Translator
|
|
124
|
+
) {
|
|
125
|
+
const { tComponent } = translator
|
|
126
|
+
const translatedLabel =
|
|
127
|
+
tComponent(component, 'errorDescription') ||
|
|
128
|
+
tComponent(component, 'shortDescription') ||
|
|
129
|
+
tComponent(component, 'title')
|
|
130
|
+
return translatedLabel
|
|
131
|
+
}
|
|
@@ -30,5 +30,6 @@ export { OsGridRefField } from './OsGridRefField.js'
|
|
|
30
30
|
export { NationalGridFieldNumberField } from './NationalGridFieldNumberField.js'
|
|
31
31
|
export { LatLongField } from './LatLongField.js'
|
|
32
32
|
export { HiddenField } from './HiddenField.js'
|
|
33
|
+
export { TrackingField } from './TrackingField.js'
|
|
33
34
|
export { PaymentField } from './PaymentField.js'
|
|
34
35
|
export { GeospatialField } from './GeospatialField.js'
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type ValidationError } from 'joi'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base class for errors caused by an invalid form definition — whether it
|
|
5
|
+
* fails schema validation or passes the schema but cannot be used by the
|
|
6
|
+
* engine. Never thrown directly — throw a subclass. Consumers (e.g.
|
|
7
|
+
* forms-runner error pages) detect the family with
|
|
8
|
+
* `instanceof InvalidFormDefinitionError`.
|
|
9
|
+
*
|
|
10
|
+
* When subclassing, remember that the message and the messages of any
|
|
11
|
+
* `cause` chain are shown to form authors on preview error pages. Only
|
|
12
|
+
* describe the problem with the form itself — never include sensitive
|
|
13
|
+
* details such as file paths, configuration values or secrets.
|
|
14
|
+
*/
|
|
15
|
+
export class InvalidFormDefinitionError extends Error {
|
|
16
|
+
constructor(message: string, options?: ErrorOptions) {
|
|
17
|
+
super(message, options)
|
|
18
|
+
this.name = 'InvalidFormDefinitionError'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Thrown when a condition in the definition cannot be compiled into an
|
|
24
|
+
* evaluatable expression (e.g. it references the wrong component or list).
|
|
25
|
+
*/
|
|
26
|
+
export class ConditionBuildError extends InvalidFormDefinitionError {
|
|
27
|
+
public readonly conditionName: string
|
|
28
|
+
|
|
29
|
+
constructor(conditionName: string, options?: ErrorOptions) {
|
|
30
|
+
super(`Failed to build condition '${conditionName}'`, options)
|
|
31
|
+
this.name = 'ConditionBuildError'
|
|
32
|
+
this.conditionName = conditionName
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Thrown when a page names a controller that is neither built in nor
|
|
38
|
+
* registered by the host application.
|
|
39
|
+
*/
|
|
40
|
+
export class UnknownPageControllerError extends InvalidFormDefinitionError {
|
|
41
|
+
public readonly controllerName: string
|
|
42
|
+
|
|
43
|
+
constructor(controllerName: string) {
|
|
44
|
+
super(`Page controller ${controllerName} does not exist`)
|
|
45
|
+
this.name = 'UnknownPageControllerError'
|
|
46
|
+
this.controllerName = controllerName
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Thrown when a component declares a type with no registered implementation.
|
|
52
|
+
*/
|
|
53
|
+
export class UnknownComponentTypeError extends InvalidFormDefinitionError {
|
|
54
|
+
public readonly componentType: string
|
|
55
|
+
|
|
56
|
+
constructor(componentType: string) {
|
|
57
|
+
super(`Component type ${componentType} does not exist`)
|
|
58
|
+
this.name = 'UnknownComponentTypeError'
|
|
59
|
+
this.componentType = componentType
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Thrown when a form definition fails Joi schema validation. The raw
|
|
65
|
+
* ValidationError is preserved as `cause` so consumers can reach the
|
|
66
|
+
* per-field details; the message carries Joi's own summary so log lines
|
|
67
|
+
* remain diagnostic for consumers that only read `error.message`.
|
|
68
|
+
*/
|
|
69
|
+
export class SchemaValidationError extends InvalidFormDefinitionError {
|
|
70
|
+
// Error types `cause` as unknown; this constructor only accepts a Joi
|
|
71
|
+
// ValidationError, so narrow the declaration for consumers (type-only).
|
|
72
|
+
declare cause: ValidationError
|
|
73
|
+
|
|
74
|
+
constructor(cause: ValidationError) {
|
|
75
|
+
super(`Invalid form definition: ${cause.message}`, { cause })
|
|
76
|
+
this.name = 'SchemaValidationError'
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
FormStatus,
|
|
3
|
+
type FormDefinition,
|
|
4
|
+
type FormMetadata
|
|
5
|
+
} from '@defra/forms-model'
|
|
2
6
|
import Boom from '@hapi/boom'
|
|
3
7
|
|
|
4
8
|
export interface OfflineBoomData {
|
|
5
9
|
offline: true
|
|
6
10
|
metadata: FormMetadata
|
|
11
|
+
definition: FormDefinition | undefined
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
/**
|
|
@@ -13,6 +18,7 @@ export interface OfflineBoomData {
|
|
|
13
18
|
*/
|
|
14
19
|
export function assertFormAvailable(
|
|
15
20
|
metadata: FormMetadata,
|
|
21
|
+
definition: FormDefinition | undefined,
|
|
16
22
|
formState: FormStatus,
|
|
17
23
|
isPreview: boolean
|
|
18
24
|
): void {
|
|
@@ -21,7 +27,7 @@ export function assertFormAvailable(
|
|
|
21
27
|
formState === FormStatus.Live &&
|
|
22
28
|
!isPreview
|
|
23
29
|
) {
|
|
24
|
-
const data: OfflineBoomData = { offline: true, metadata }
|
|
30
|
+
const data: OfflineBoomData = { offline: true, metadata, definition }
|
|
25
31
|
throw Boom.boomify(new Error(`Form ${metadata.slug} is offline`), {
|
|
26
32
|
statusCode: 503,
|
|
27
33
|
data
|
|
@@ -56,13 +56,14 @@ export async function getFormModel(
|
|
|
56
56
|
const formState = resolveState(state)
|
|
57
57
|
|
|
58
58
|
const metadata = await formsService.getFormMetadata(slug)
|
|
59
|
-
assertFormAvailable(metadata, formState, isPreview)
|
|
60
59
|
|
|
61
60
|
const definition = await formsService.getFormDefinition(
|
|
62
61
|
metadata.id,
|
|
63
62
|
formState
|
|
64
63
|
)
|
|
65
64
|
|
|
65
|
+
assertFormAvailable(metadata, definition, formState, isPreview)
|
|
66
|
+
|
|
66
67
|
if (!definition) {
|
|
67
68
|
throw Boom.notFound(
|
|
68
69
|
`No definition found for form metadata ${metadata.id} (${slug}) ${state}`
|
|
@@ -145,7 +146,6 @@ export async function resolveFormModel(
|
|
|
145
146
|
const metadata = await formsService.getFormMetadata(slug)
|
|
146
147
|
const formState = resolveState(state)
|
|
147
148
|
const isPreview = options.isPreview ?? isPreviewState(state, options)
|
|
148
|
-
assertFormAvailable(metadata, formState, isPreview)
|
|
149
149
|
const stateMetadata = metadata[formState]
|
|
150
150
|
|
|
151
151
|
if (!stateMetadata) {
|
|
@@ -199,6 +199,8 @@ export async function resolveFormModel(
|
|
|
199
199
|
cache.set(cacheKey, entry)
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
assertFormAvailable(metadata, entry.model.def, formState, isPreview)
|
|
203
|
+
|
|
202
204
|
return entry.model
|
|
203
205
|
}
|
|
204
206
|
|
|
@@ -8,13 +8,14 @@ import {
|
|
|
8
8
|
} from '@defra/forms-model'
|
|
9
9
|
import Boom from '@hapi/boom'
|
|
10
10
|
import { type ResponseToolkit, type Server } from '@hapi/hapi'
|
|
11
|
-
import { format, parseISO } from 'date-fns'
|
|
11
|
+
import { format, parseISO, type Locale } from 'date-fns'
|
|
12
|
+
import { cy, enGB } from 'date-fns/locale'
|
|
12
13
|
import { StatusCodes } from 'http-status-codes'
|
|
13
14
|
import { type Schema, type ValidationErrorItem } from 'joi'
|
|
14
15
|
import { Liquid } from 'liquidjs'
|
|
15
16
|
|
|
16
17
|
import { logger } from '../../common/helpers/logging/logger.js'
|
|
17
|
-
import { FORM_VERSION_METADATA_KEY } from '../../constants.js'
|
|
18
|
+
import { CY, EN_GB, FORM_VERSION_METADATA_KEY } from '../../constants.js'
|
|
18
19
|
import {
|
|
19
20
|
getAnswer,
|
|
20
21
|
type Field
|
|
@@ -300,19 +301,24 @@ export function checkEmailAddressForLiveFormSubmission(
|
|
|
300
301
|
|
|
301
302
|
/**
|
|
302
303
|
* Parses the errors from {@link Schema.validate} so they can be rendered by govuk-frontend templates
|
|
304
|
+
* @param language - the target language for translations
|
|
303
305
|
* @param [details] - provided by {@link Schema.validate}
|
|
304
306
|
*/
|
|
305
307
|
export function getErrors(
|
|
308
|
+
language: string | undefined,
|
|
306
309
|
details?: ValidationErrorItem[]
|
|
307
310
|
): FormSubmissionError[] | undefined {
|
|
308
311
|
if (!details?.length) {
|
|
309
312
|
return
|
|
310
313
|
}
|
|
311
314
|
|
|
312
|
-
return details.map(getError)
|
|
315
|
+
return details.map((detail) => getError(language, detail))
|
|
313
316
|
}
|
|
314
317
|
|
|
315
|
-
export function getError(
|
|
318
|
+
export function getError(
|
|
319
|
+
language: string | undefined,
|
|
320
|
+
detail: ValidationErrorItem
|
|
321
|
+
): FormSubmissionError {
|
|
316
322
|
const { context, message, path } = detail
|
|
317
323
|
|
|
318
324
|
const name = context?.key ?? ''
|
|
@@ -320,7 +326,10 @@ export function getError(detail: ValidationErrorItem): FormSubmissionError {
|
|
|
320
326
|
|
|
321
327
|
const text = message.replace(
|
|
322
328
|
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,
|
|
323
|
-
(text) =>
|
|
329
|
+
(text) =>
|
|
330
|
+
format(parseISO(text), 'd MMMM yyyy', {
|
|
331
|
+
locale: toLanguageLocale(language)
|
|
332
|
+
})
|
|
324
333
|
)
|
|
325
334
|
|
|
326
335
|
return {
|
|
@@ -410,3 +419,41 @@ export function getFormVersion(
|
|
|
410
419
|
| FormVersionMetadata
|
|
411
420
|
| undefined
|
|
412
421
|
}
|
|
422
|
+
|
|
423
|
+
const payLanguageCodes = {
|
|
424
|
+
[EN_GB]: 'en',
|
|
425
|
+
[CY]: 'cy'
|
|
426
|
+
} as Record<string, string>
|
|
427
|
+
|
|
428
|
+
const languageLocales = {
|
|
429
|
+
[EN_GB]: enGB,
|
|
430
|
+
[CY]: cy
|
|
431
|
+
} as Record<string, Locale>
|
|
432
|
+
|
|
433
|
+
const defaultLanguageCode = 'en'
|
|
434
|
+
const defaultLanguageLocale = enGB
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Converts a BCP 47 language tag to the ISO 639-1 code GOV.UK Pay accepts.
|
|
438
|
+
* Defaults to English if the language is not supported.
|
|
439
|
+
* @param { string | undefined } language - BCP 47 language code
|
|
440
|
+
* @returns {string} language code required by GOV.UK Pay
|
|
441
|
+
*/
|
|
442
|
+
export function toPayLanguageCode(language: string | undefined): string {
|
|
443
|
+
return payLanguageCodes[language ?? 'unknown'] ?? defaultLanguageCode
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Converts a BCP 47 language tag to the date-fns Locale (for date formatting).
|
|
448
|
+
* Defaults to English if the language is not supported.
|
|
449
|
+
* @param { string | undefined } language - BCP 47 language code
|
|
450
|
+
* @returns {Locale} language locale
|
|
451
|
+
*/
|
|
452
|
+
export function toLanguageLocale(language: string | undefined): Locale {
|
|
453
|
+
return languageLocales[language ?? 'unknown'] ?? defaultLanguageLocale
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* @import { FormsService } from '../../types.js'
|
|
458
|
+
* @import { Locale } from 'date-fns/locale'
|
|
459
|
+
*/
|
|
@@ -16,7 +16,9 @@ const opts = {
|
|
|
16
16
|
* because Joi cannot resolve custom functions from a plain string.
|
|
17
17
|
* Plain strings with only built-in tokens ({{#label}}, {{#limit}}) work without wrapping.
|
|
18
18
|
*/
|
|
19
|
-
export function buildValidationMessages(
|
|
19
|
+
export function buildValidationMessages(
|
|
20
|
+
t: (key: string, options?: Record<string, unknown>) => string
|
|
21
|
+
) {
|
|
20
22
|
return {
|
|
21
23
|
// Expressions — contain lowerFirst custom function
|
|
22
24
|
required: joi.expression(t('validation.required'), opts) as JoiExpression,
|
|
@@ -56,13 +58,19 @@ export function buildValidationMessages(t: (key: string) => string) {
|
|
|
56
58
|
dateMin: t('components.dateField.validation.dateMin'),
|
|
57
59
|
dateMax: t('components.dateField.validation.dateMax'),
|
|
58
60
|
|
|
59
|
-
unicode: 'validation.unicode',
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
unicode: t('validation.unicode'),
|
|
62
|
+
// These generic templates are shared across fields with differing limits, so a
|
|
63
|
+
// fixed singular count is used here — components needing accurate singular/plural
|
|
64
|
+
// text (e.g. FileUploadField) build their own per-instance messages instead.
|
|
65
|
+
arrayMin: t('validation.arrayMin', { count: 1 }),
|
|
66
|
+
arrayMax: t('validation.arrayMax', { count: 1 }),
|
|
67
|
+
arrayLength: t('validation.arrayLength', { count: 1 }),
|
|
68
|
+
featuresMin: t('validation.featuresMin', { count: 1 }),
|
|
69
|
+
featuresMax: t('validation.featuresMax', { count: 1 }),
|
|
70
|
+
featuresLength: t('validation.featuresLength', { count: 1 }),
|
|
71
|
+
filesMin: t('validation.filesMin', { count: 1 }),
|
|
72
|
+
filesMax: t('validation.filesMax', { count: 1 }),
|
|
73
|
+
filesLength: t('validation.filesLength', { count: 1 })
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
76
|
|
|
@@ -1,30 +1,40 @@
|
|
|
1
1
|
import {
|
|
2
2
|
yesNoListNoItemId,
|
|
3
3
|
yesNoListYesItemId,
|
|
4
|
-
type FormDefinition
|
|
4
|
+
type FormDefinition,
|
|
5
|
+
type FormMetadata
|
|
5
6
|
} from '@defra/forms-model'
|
|
6
7
|
import { type i18n } from 'i18next'
|
|
7
8
|
|
|
9
|
+
import { CY } from '../../../constants.js'
|
|
8
10
|
import { createTranslator } from './createTranslator.js'
|
|
9
11
|
import { extractBaseTranslations } from './extractBaseTranslations.js'
|
|
10
12
|
import { createFormI18nInstance } from './index.js'
|
|
11
|
-
import {
|
|
12
|
-
type FormDefinitionTranslations,
|
|
13
|
-
type Translator
|
|
14
|
-
} from './types.js'
|
|
13
|
+
import { type FormDefinitionTranslations } from './types.js'
|
|
15
14
|
|
|
16
15
|
export function createFormTranslator(
|
|
17
|
-
|
|
16
|
+
metadata: FormMetadata,
|
|
17
|
+
definition: FormDefinition | undefined,
|
|
18
18
|
language: string
|
|
19
|
-
)
|
|
20
|
-
const baseTranslations = extractBaseTranslations(
|
|
19
|
+
) {
|
|
20
|
+
const baseTranslations = extractBaseTranslations(definition)
|
|
21
21
|
const i18nInstance = createFormI18nInstance(baseTranslations)
|
|
22
|
-
loadFormTranslations(
|
|
22
|
+
loadFormTranslations(definition, i18nInstance)
|
|
23
|
+
extractMetadataBaseTranslations(metadata, i18nInstance)
|
|
24
|
+
|
|
25
|
+
const translator = createTranslator(i18nInstance, language)
|
|
23
26
|
|
|
24
|
-
return
|
|
27
|
+
return translator
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
export function loadFormTranslations(
|
|
30
|
+
export function loadFormTranslations(
|
|
31
|
+
def: FormDefinition | undefined,
|
|
32
|
+
i18nInstance: i18n
|
|
33
|
+
) {
|
|
34
|
+
if (!def) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
28
38
|
const formTranslations = def.metadata?.translations as
|
|
29
39
|
| FormDefinitionTranslations
|
|
30
40
|
| undefined
|
|
@@ -34,7 +44,7 @@ export function loadFormTranslations(def: FormDefinition, i18nInstance: i18n) {
|
|
|
34
44
|
i18nInstance.addResourceBundle(lng, 'form', resources, true, true)
|
|
35
45
|
|
|
36
46
|
// Temporary workaround - until we develop a better solution
|
|
37
|
-
if (lng ===
|
|
47
|
+
if (lng === CY) {
|
|
38
48
|
i18nInstance.addResource(
|
|
39
49
|
lng,
|
|
40
50
|
'form',
|
|
@@ -51,3 +61,24 @@ export function loadFormTranslations(def: FormDefinition, i18nInstance: i18n) {
|
|
|
51
61
|
}
|
|
52
62
|
}
|
|
53
63
|
}
|
|
64
|
+
|
|
65
|
+
export function extractMetadataBaseTranslations(
|
|
66
|
+
metadata: FormMetadata | undefined,
|
|
67
|
+
i18nInstance: i18n
|
|
68
|
+
) {
|
|
69
|
+
if (metadata) {
|
|
70
|
+
const translations = {
|
|
71
|
+
'form.title': metadata.title,
|
|
72
|
+
'form.contact.email.address': metadata.contact?.email?.address ?? '',
|
|
73
|
+
'form.contact.email.responseTime':
|
|
74
|
+
metadata.contact?.email?.responseTime ?? '',
|
|
75
|
+
'form.contact.online.url': metadata.contact?.online?.url ?? '',
|
|
76
|
+
'form.contact.online.text': metadata.contact?.online?.text ?? '',
|
|
77
|
+
'form.contact.phone': metadata.contact?.phone ?? '',
|
|
78
|
+
'form.submissionGuidance': metadata.submissionGuidance ?? '',
|
|
79
|
+
'form.privacyNoticeText': metadata.privacyNoticeText ?? '',
|
|
80
|
+
'form.privacyNoticeUrl': metadata.privacyNoticeUrl ?? ''
|
|
81
|
+
}
|
|
82
|
+
i18nInstance.addResourceBundle('en-GB', 'form', translations, true, true)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -7,13 +7,19 @@ import { type FormDefinitionTranslations } from './types.js'
|
|
|
7
7
|
|
|
8
8
|
type BaseTranslations = FormDefinitionTranslations[string]
|
|
9
9
|
|
|
10
|
-
export function extractBaseTranslations(
|
|
10
|
+
export function extractBaseTranslations(
|
|
11
|
+
def: FormDefinition | undefined
|
|
12
|
+
): BaseTranslations {
|
|
11
13
|
const pages: BaseTranslations['pages'] = {}
|
|
12
14
|
const components: BaseTranslations['components'] = {}
|
|
13
15
|
const sections: BaseTranslations['sections'] = {}
|
|
14
16
|
const listItems: BaseTranslations['listItems'] = {}
|
|
15
17
|
const form: BaseTranslations['form'] = {}
|
|
16
18
|
|
|
19
|
+
if (!def) {
|
|
20
|
+
return { pages, components, sections, listItems, form }
|
|
21
|
+
}
|
|
22
|
+
|
|
17
23
|
for (const page of def.pages) {
|
|
18
24
|
if (page.id && page.title) {
|
|
19
25
|
pages[page.id] = { title: page.title }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type FormMetadata, type FormStatus } from '@defra/forms-model'
|
|
2
|
+
import Boom from '@hapi/boom'
|
|
3
|
+
import { LRUCache } from 'lru-cache'
|
|
4
|
+
|
|
5
|
+
import { getPluginOptions } from '../helpers.js'
|
|
6
|
+
import { createFormTranslator } from './createFormTranslator.js'
|
|
7
|
+
import { type Translator } from './types.js'
|
|
8
|
+
import { type AnyFormRequest } from '../types.js'
|
|
9
|
+
|
|
10
|
+
const cache = new LRUCache({
|
|
11
|
+
max: 100,
|
|
12
|
+
ttl: 1000 * 60 * 15 // 15 minutes
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get translator for plugin, for the current form's metadata (as well as the plugin-specific boilerplate).
|
|
17
|
+
* This is an async call so we can read the form definition inside this call.
|
|
18
|
+
* See docs/features/multi-language.md for the language and translation flow overview.
|
|
19
|
+
* @param {AnyFormRequest} request
|
|
20
|
+
* @param {FormMetadata} metadata - the metadata of the form
|
|
21
|
+
* @param {FormStatus} status - the form status to use when retrieving the definition
|
|
22
|
+
* @param {string} language - the language to use for the translator
|
|
23
|
+
*/
|
|
24
|
+
export async function getCachedPluginTranslator(
|
|
25
|
+
request: AnyFormRequest,
|
|
26
|
+
metadata: FormMetadata,
|
|
27
|
+
status: FormStatus,
|
|
28
|
+
language: string
|
|
29
|
+
) {
|
|
30
|
+
const key = `${metadata.id}-${status}-${language}-plugin-meta`
|
|
31
|
+
|
|
32
|
+
if (cache.has(key)) {
|
|
33
|
+
return cache.get(key) as unknown as Translator
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const { services } = getPluginOptions(request.server)
|
|
37
|
+
|
|
38
|
+
const definition = await services?.formsService.getFormDefinition(
|
|
39
|
+
metadata.id,
|
|
40
|
+
status
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if (!definition) {
|
|
44
|
+
throw Boom.notFound(
|
|
45
|
+
`FormDefinition not found for form ${metadata.id} and status ${status}`
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const translator = createFormTranslator(metadata, definition, language)
|
|
50
|
+
|
|
51
|
+
cache.set(key, translator)
|
|
52
|
+
|
|
53
|
+
return translator
|
|
54
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type FormDefinition } from '@defra/forms-model'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Return a list of available languages.
|
|
5
|
+
* Empty array if only English, or an array of English and Welsh if translations have been defined.
|
|
6
|
+
* @param {FormDefinition} def
|
|
7
|
+
*/
|
|
8
|
+
export function getAvailableLanguages(
|
|
9
|
+
def: FormDefinition
|
|
10
|
+
): { name: string; code: string }[] {
|
|
11
|
+
// @ts-expect-error - dynamic property
|
|
12
|
+
if (def.metadata?.translations?.cy) {
|
|
13
|
+
return [
|
|
14
|
+
{ name: 'English', code: 'en-GB' },
|
|
15
|
+
{ name: 'Cymraeg', code: 'cy' }
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
return []
|
|
19
|
+
}
|