@defra/forms-engine-plugin 5.0.0-alpha.2 → 5.0.0-alpha.21
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/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 +7 -0
- package/.public/javascripts/shared.min.js.map +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 +153 -5
- package/.server/client/javascripts/geospatial-map.js +157 -77
- package/.server/client/javascripts/geospatial-map.js.map +1 -1
- 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 +54 -5
- 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 +10 -0
- package/.server/client/javascripts/map.js +42 -0
- 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/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 +9 -3
- package/.server/server/plugins/engine/components/AutocompleteField.js +12 -0
- package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
- package/.server/server/plugins/engine/components/CheckboxesField.d.ts +21 -0
- 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 +1 -0
- 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 +11 -6
- 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 +5 -2
- 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 +21 -0
- 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 +1 -0
- package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +8 -2
- package/.server/server/plugins/engine/components/LocationFieldBase.js +25 -6
- 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 +16 -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 +3 -0
- package/.server/server/plugins/engine/components/PaymentField.js +17 -6
- 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/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 +5 -2
- package/.server/server/plugins/engine/components/YesNoField.js +17 -8
- package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/components.js +3 -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 +56 -15
- package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/index.d.ts +7 -0
- package/.server/server/plugins/engine/components/helpers/index.js +13 -1
- package/.server/server/plugins/engine/components/helpers/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 +22 -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 +33 -4
- 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 +192 -9
- package/.server/server/plugins/engine/i18n/translations/en-GB.json +125 -7
- package/.server/server/plugins/engine/i18n/types.d.ts +3 -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/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 +7 -3
- 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/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 +10 -3
- package/.server/server/plugins/engine/types/schema.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +18 -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/multilinetextfield.html +12 -1
- package/.server/server/plugins/engine/views/components/osgridreffield.html +4 -1
- package/.server/server/plugins/engine/views/components/paymentfield.html +1 -1
- 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/partials/preview-banner.html +3 -1
- package/.server/server/plugins/engine/views/unavailable.html +14 -11
- 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 +87 -33
- 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 +47 -15
- 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/package.json +20 -5
- package/src/client/javascripts/file-upload.js +11 -3
- package/src/client/javascripts/geospatial-map.js +176 -81
- package/src/client/javascripts/govuk.js +2 -0
- package/src/client/javascripts/location-map.js +60 -4
- package/src/client/javascripts/map-constants.js +3 -0
- package/src/client/javascripts/map.js +47 -0
- 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/plugins/engine/__stubs__/definitions.ts +155 -0
- package/src/server/plugins/engine/components/AutocompleteField.ts +13 -0
- package/src/server/plugins/engine/components/CheckboxesField.ts +38 -5
- package/src/server/plugins/engine/components/ComponentBase.ts +2 -0
- package/src/server/plugins/engine/components/ComponentCollection.ts +16 -11
- package/src/server/plugins/engine/components/DatePartsField.ts +20 -9
- package/src/server/plugins/engine/components/DeclarationField.ts +7 -6
- 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 +44 -3
- 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/LocationFieldBase.ts +30 -7
- 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 +21 -1
- package/src/server/plugins/engine/components/OsGridRefField.ts +22 -3
- package/src/server/plugins/engine/components/PaymentField.ts +15 -5
- package/src/server/plugins/engine/components/UkAddressField.ts +30 -7
- package/src/server/plugins/engine/components/YesNoField.ts +17 -9
- package/src/server/plugins/engine/components/helpers/components.ts +3 -3
- package/src/server/plugins/engine/components/helpers/geospatial.ts +84 -21
- package/src/server/plugins/engine/components/helpers/index.ts +19 -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 +62 -11
- 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 +192 -9
- package/src/server/plugins/engine/i18n/translations/en-GB.json +125 -7
- package/src/server/plugins/engine/i18n/types.ts +3 -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/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 +10 -5
- 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/types/enums.ts +4 -3
- package/src/server/plugins/engine/types/schema.ts +17 -4
- package/src/server/plugins/engine/types.ts +19 -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/multilinetextfield.html +12 -1
- package/src/server/plugins/engine/views/components/osgridreffield.html +4 -1
- package/src/server/plugins/engine/views/components/paymentfield.html +1 -1
- 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/partials/preview-banner.html +3 -1
- package/src/server/plugins/engine/views/unavailable.html +14 -11
- 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 +75 -43
- package/src/server/plugins/postcode-lookup/routes/index.js +73 -16
- 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
|
@@ -45,6 +45,7 @@ export class PaymentField extends FormComponent {
|
|
|
45
45
|
declare options: PaymentFieldComponent['options']
|
|
46
46
|
declare formSchema: ObjectSchema
|
|
47
47
|
declare stateSchema: ObjectSchema
|
|
48
|
+
declare def: PaymentFieldComponent
|
|
48
49
|
isAppendageStateSingleObject = true
|
|
49
50
|
|
|
50
51
|
constructor(
|
|
@@ -54,6 +55,7 @@ export class PaymentField extends FormComponent {
|
|
|
54
55
|
super(def, props)
|
|
55
56
|
|
|
56
57
|
this.options = def.options
|
|
58
|
+
this.def = def
|
|
57
59
|
|
|
58
60
|
const paymentStateSchema = joi
|
|
59
61
|
.object({
|
|
@@ -61,6 +63,7 @@ export class PaymentField extends FormComponent {
|
|
|
61
63
|
reference: joi.string().required(),
|
|
62
64
|
amount: joi.number().required(),
|
|
63
65
|
description: joi.string().required(),
|
|
66
|
+
descriptionInEng: joi.string().optional(),
|
|
64
67
|
uuid: joi.string().uuid().required(),
|
|
65
68
|
formId: joi.string().required(),
|
|
66
69
|
isLivePayment: joi.boolean().required(),
|
|
@@ -110,6 +113,8 @@ export class PaymentField extends FormComponent {
|
|
|
110
113
|
getViewModel(context: RenderContext) {
|
|
111
114
|
const { payload } = context
|
|
112
115
|
const viewModel = super.getViewModel(context)
|
|
116
|
+
const { translator } = context
|
|
117
|
+
const { tComponent } = translator
|
|
113
118
|
|
|
114
119
|
// Payload is pre-populated from state if a payment has already been made
|
|
115
120
|
const paymentState = this.isPaymentState(payload[this.name] as unknown)
|
|
@@ -124,7 +129,8 @@ export class PaymentField extends FormComponent {
|
|
|
124
129
|
return {
|
|
125
130
|
...viewModel,
|
|
126
131
|
amount: formatCurrency(amount),
|
|
127
|
-
description:
|
|
132
|
+
description:
|
|
133
|
+
tComponent(this.def, 'paymentDescription') || this.options.description,
|
|
128
134
|
paymentState
|
|
129
135
|
}
|
|
130
136
|
}
|
|
@@ -234,8 +240,9 @@ export class PaymentField extends FormComponent {
|
|
|
234
240
|
): Promise<unknown> {
|
|
235
241
|
const { options, name: componentName } = args.component
|
|
236
242
|
const { model } = args.controller
|
|
237
|
-
const language =
|
|
238
|
-
|
|
243
|
+
const { language, t, tComponent } = model.createTranslator(
|
|
244
|
+
resolveLanguage(request)
|
|
245
|
+
)
|
|
239
246
|
const state = await args.controller.getState(request)
|
|
240
247
|
const { baseUrl } = getPluginOptions(request.server)
|
|
241
248
|
const summaryUrl = `${baseUrl}/${model.basePath}/summary`
|
|
@@ -267,7 +274,8 @@ export class PaymentField extends FormComponent {
|
|
|
267
274
|
return h.redirect(summaryUrl).code(StatusCodes.SEE_OTHER)
|
|
268
275
|
}
|
|
269
276
|
|
|
270
|
-
const description =
|
|
277
|
+
const description =
|
|
278
|
+
tComponent(args.component, 'paymentDescription') || options.description
|
|
271
279
|
|
|
272
280
|
const slug = `/${model.basePath}`
|
|
273
281
|
|
|
@@ -287,7 +295,7 @@ export class PaymentField extends FormComponent {
|
|
|
287
295
|
payCallbackUrl,
|
|
288
296
|
reference,
|
|
289
297
|
isLivePayment,
|
|
290
|
-
{ formId, slug },
|
|
298
|
+
{ formId, slug, language },
|
|
291
299
|
prefilledEmail
|
|
292
300
|
)
|
|
293
301
|
|
|
@@ -308,6 +316,7 @@ export class PaymentField extends FormComponent {
|
|
|
308
316
|
reference,
|
|
309
317
|
amount: resolvedAmount,
|
|
310
318
|
description,
|
|
319
|
+
descriptionInEng: options.description,
|
|
311
320
|
paymentId: payment.paymentId,
|
|
312
321
|
componentName,
|
|
313
322
|
returnUrl: summaryUrl,
|
|
@@ -444,6 +453,7 @@ export interface PaymentSessionData {
|
|
|
444
453
|
reference: string
|
|
445
454
|
amount: number
|
|
446
455
|
description: string
|
|
456
|
+
descriptionInEng?: string
|
|
447
457
|
paymentId: string
|
|
448
458
|
componentName: string
|
|
449
459
|
returnUrl: string
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ComponentType,
|
|
3
|
+
FormStatus,
|
|
4
|
+
type FormMetadata,
|
|
5
|
+
type UkAddressFieldComponent
|
|
6
|
+
} from '@defra/forms-model'
|
|
2
7
|
import { type ObjectSchema } from 'joi'
|
|
3
8
|
import lowerFirst from 'lodash/lowerFirst.js'
|
|
4
9
|
|
|
@@ -9,6 +14,8 @@ import {
|
|
|
9
14
|
} from './FormComponent.js'
|
|
10
15
|
import { TextField } from './TextField.js'
|
|
11
16
|
import { type RenderContext } from './types.js'
|
|
17
|
+
import { getCachedPluginTranslator } from '../i18n/form.js'
|
|
18
|
+
import { getAvailableLanguages } from '../i18n/languages.js'
|
|
12
19
|
import { type Translator } from '../i18n/types.js'
|
|
13
20
|
import {
|
|
14
21
|
type FormRequestPayload,
|
|
@@ -207,7 +214,7 @@ export class UkAddressField extends FormComponent {
|
|
|
207
214
|
|
|
208
215
|
/**
|
|
209
216
|
* For screen readers, only hide legend visually. This can be overridden
|
|
210
|
-
* by single component
|
|
217
|
+
* by single component (see QuestionPageController and showTitle handling)
|
|
211
218
|
*/
|
|
212
219
|
classes: options.hideTitle
|
|
213
220
|
? 'govuk-visually-hidden'
|
|
@@ -290,7 +297,6 @@ export class UkAddressField extends FormComponent {
|
|
|
290
297
|
)
|
|
291
298
|
}
|
|
292
299
|
|
|
293
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
294
300
|
static async dispatcher(
|
|
295
301
|
request: FormRequestPayload,
|
|
296
302
|
h: FormResponseToolkit,
|
|
@@ -299,14 +305,31 @@ export class UkAddressField extends FormComponent {
|
|
|
299
305
|
const { controller, component } = args
|
|
300
306
|
const language = resolveLanguage(request)
|
|
301
307
|
|
|
308
|
+
const availableLanguages = getAvailableLanguages(controller.model.def)
|
|
309
|
+
const languages = availableLanguages.length
|
|
310
|
+
? { languages: availableLanguages }
|
|
311
|
+
: {}
|
|
312
|
+
|
|
313
|
+
const translator = await getCachedPluginTranslator(
|
|
314
|
+
request,
|
|
315
|
+
{ id: controller.model.formId } as unknown as FormMetadata,
|
|
316
|
+
args.isLive ? FormStatus.Live : FormStatus.Draft,
|
|
317
|
+
language
|
|
318
|
+
)
|
|
319
|
+
const { tComponent, tForm } = translator
|
|
320
|
+
|
|
302
321
|
return dispatch(request, h, {
|
|
303
|
-
formName:
|
|
322
|
+
formName: tForm('title'),
|
|
323
|
+
formId: controller.model.formId,
|
|
324
|
+
formStatus: args.isLive ? FormStatus.Live : FormStatus.Draft,
|
|
325
|
+
componentId: component.id ?? 'unknown',
|
|
304
326
|
componentName: component.name,
|
|
305
|
-
componentHint: component
|
|
306
|
-
componentTitle: component
|
|
327
|
+
componentHint: tComponent(component, 'hint'),
|
|
328
|
+
componentTitle: tComponent(component, 'title') || controller.title,
|
|
307
329
|
step: args.actionArgs.step,
|
|
308
330
|
sourceUrl: args.sourceUrl,
|
|
309
|
-
language
|
|
331
|
+
language,
|
|
332
|
+
...languages
|
|
310
333
|
})
|
|
311
334
|
}
|
|
312
335
|
}
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
yesNoListName,
|
|
5
5
|
type YesNoFieldComponent
|
|
6
6
|
} from '@defra/forms-model'
|
|
7
|
-
import { type LanguageMessages } from 'joi'
|
|
8
7
|
|
|
9
8
|
import { SelectionControlField } from './SelectionControlField.js'
|
|
10
9
|
import { addClassOptionIfNone } from './helpers/index.js'
|
|
@@ -12,7 +11,6 @@ import { buildValidationMessages } from '../i18n/buildValidationMessages.js'
|
|
|
12
11
|
import { type Translator } from '../i18n/types.js'
|
|
13
12
|
import { messageTemplate } from '../pageControllers/validationOptions.js'
|
|
14
13
|
import { type ErrorMessageTemplateList } from '../types.js'
|
|
15
|
-
import { convertToLanguageMessages } from '../../../utils/type-utils.js'
|
|
16
14
|
|
|
17
15
|
/**
|
|
18
16
|
* @description
|
|
@@ -45,21 +43,31 @@ export class YesNoField extends SelectionControlField {
|
|
|
45
43
|
formSchema = formSchema.optional()
|
|
46
44
|
}
|
|
47
45
|
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
if (options.customValidationMessage) {
|
|
47
|
+
const message = options.customValidationMessage
|
|
48
|
+
|
|
49
|
+
formSchema = formSchema.messages({
|
|
50
|
+
'any.required': message
|
|
51
|
+
})
|
|
52
|
+
} else if (options.customValidationMessages) {
|
|
53
|
+
formSchema = formSchema.messages(options.customValidationMessages)
|
|
54
|
+
} else {
|
|
55
|
+
formSchema = formSchema.messages({
|
|
50
56
|
'any.required': messageTemplate.selectYesNoRequired
|
|
51
57
|
})
|
|
52
|
-
|
|
58
|
+
}
|
|
53
59
|
|
|
54
60
|
this.formSchema = formSchema
|
|
55
61
|
this.options = options
|
|
56
62
|
}
|
|
57
63
|
|
|
58
|
-
getValidationMessagesOverride(translator: Translator)
|
|
64
|
+
getValidationMessagesOverride(translator: Translator) {
|
|
59
65
|
const { selectYesNoRequired } = buildValidationMessages(translator.t)
|
|
60
|
-
return
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
return {
|
|
67
|
+
[this.name]: {
|
|
68
|
+
'any.required': selectYesNoRequired
|
|
69
|
+
}
|
|
70
|
+
}
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
/**
|
|
@@ -6,6 +6,7 @@ import { ListFormComponent } from '../ListFormComponent.js'
|
|
|
6
6
|
import { escapeMarkdown } from './index.js'
|
|
7
7
|
import * as Components from '../index.js'
|
|
8
8
|
import { markdown } from '../markdownParser.js'
|
|
9
|
+
import { UnknownComponentTypeError } from '../../errors.js'
|
|
9
10
|
import { type Translator } from '../../i18n/types.js'
|
|
10
11
|
import { type FormState } from '../../types.js'
|
|
11
12
|
|
|
@@ -210,7 +211,7 @@ export function createComponent(
|
|
|
210
211
|
}
|
|
211
212
|
|
|
212
213
|
if (typeof component === 'undefined') {
|
|
213
|
-
throw new
|
|
214
|
+
throw new UnknownComponentTypeError(def.type)
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
return component
|
|
@@ -347,8 +348,7 @@ export function getAnswerMarkdown(
|
|
|
347
348
|
field instanceof Components.EastingNorthingField ||
|
|
348
349
|
field instanceof Components.LatLongField
|
|
349
350
|
) {
|
|
350
|
-
|
|
351
|
-
answerEscaped = contextValue ? `${contextValue}\n` : ''
|
|
351
|
+
answerEscaped = answer ? `${answer}\n` : ''
|
|
352
352
|
} else if (field instanceof Components.GeospatialField) {
|
|
353
353
|
const features = field.getFormValueFromState(state)
|
|
354
354
|
const value = field.getDisplayStringFromFormValue(features, translator)
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
GeospatialFieldOptionsCountryEnum,
|
|
3
2
|
type GeospatialFieldComponent,
|
|
4
3
|
type GeospatialFieldOptionsCountry
|
|
5
4
|
} from '@defra/forms-model'
|
|
6
5
|
import Bourne from '@hapi/bourne'
|
|
7
6
|
import { booleanWithin } from '@turf/boolean-within'
|
|
7
|
+
import { point } from '@turf/helpers'
|
|
8
|
+
// @ts-expect-error - no types
|
|
9
|
+
import OsGridRef from 'geodesy/osgridref.js'
|
|
8
10
|
import JoiBase, { type CustomValidator } from 'joi'
|
|
9
11
|
|
|
12
|
+
import { type EastingNorthingField } from '../EastingNorthingField.js'
|
|
13
|
+
import { type EastingNorthingState } from '../types.js'
|
|
10
14
|
import {
|
|
11
15
|
type Coordinates,
|
|
12
16
|
type Feature,
|
|
@@ -15,13 +19,6 @@ import {
|
|
|
15
19
|
} from '../../types.js'
|
|
16
20
|
import { countries } from '../../../map/routes/index.js'
|
|
17
21
|
|
|
18
|
-
const countriesDesc: Record<GeospatialFieldOptionsCountryEnum, string> = {
|
|
19
|
-
[GeospatialFieldOptionsCountryEnum.England]: 'England',
|
|
20
|
-
[GeospatialFieldOptionsCountryEnum.NorthernIreland]: 'Northern Ireland',
|
|
21
|
-
[GeospatialFieldOptionsCountryEnum.Scotland]: 'Scotland',
|
|
22
|
-
[GeospatialFieldOptionsCountryEnum.Wales]: 'Wales'
|
|
23
|
-
}
|
|
24
|
-
|
|
25
22
|
const Joi = JoiBase.extend({
|
|
26
23
|
type: 'array',
|
|
27
24
|
base: JoiBase.array(),
|
|
@@ -98,25 +95,43 @@ const featureSchema = Joi.object<Feature>().keys({
|
|
|
98
95
|
geometry: featureGeometrySchema
|
|
99
96
|
})
|
|
100
97
|
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
export function determineLimits(
|
|
99
|
+
def: GeospatialFieldComponent,
|
|
100
|
+
isOptional: boolean
|
|
104
101
|
) {
|
|
105
|
-
const {
|
|
106
|
-
const
|
|
107
|
-
|
|
102
|
+
const { schema: constraints } = def
|
|
103
|
+
const limits: { min?: number; max?: number; length?: number } = {}
|
|
108
104
|
if (typeof constraints?.length === 'number') {
|
|
109
|
-
|
|
105
|
+
limits.length = constraints.length
|
|
110
106
|
} else {
|
|
111
107
|
if (typeof constraints?.min === 'number') {
|
|
112
|
-
|
|
108
|
+
limits.min = constraints.min
|
|
113
109
|
} else if (!isOptional) {
|
|
114
|
-
|
|
110
|
+
limits.min = 1
|
|
115
111
|
}
|
|
116
112
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
113
|
+
limits.max = typeof constraints?.max === 'number' ? constraints.max : 50
|
|
114
|
+
}
|
|
115
|
+
return limits
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function applySchemaConstraints(
|
|
119
|
+
schema: JoiBase.ArraySchema<Feature[]>,
|
|
120
|
+
def: GeospatialFieldComponent
|
|
121
|
+
) {
|
|
122
|
+
const { options } = def
|
|
123
|
+
const isOptional = options.required === false
|
|
124
|
+
|
|
125
|
+
const limits = determineLimits(def, isOptional)
|
|
126
|
+
|
|
127
|
+
if (limits.length !== undefined) {
|
|
128
|
+
schema = schema.length(limits.length)
|
|
129
|
+
}
|
|
130
|
+
if (limits.min !== undefined) {
|
|
131
|
+
schema = schema.min(limits.min)
|
|
132
|
+
}
|
|
133
|
+
if (limits.max !== undefined) {
|
|
134
|
+
schema = schema.max(limits.max)
|
|
120
135
|
}
|
|
121
136
|
|
|
122
137
|
if (isOptional) {
|
|
@@ -156,7 +171,7 @@ export function getGeospatialSchema(
|
|
|
156
171
|
|
|
157
172
|
if (!result) {
|
|
158
173
|
return helpers.error('any.custom', {
|
|
159
|
-
country
|
|
174
|
+
country
|
|
160
175
|
})
|
|
161
176
|
}
|
|
162
177
|
|
|
@@ -171,3 +186,51 @@ export function getGeospatialSchema(
|
|
|
171
186
|
def
|
|
172
187
|
)
|
|
173
188
|
}
|
|
189
|
+
|
|
190
|
+
export function getEastingNorthingCountryValidator(
|
|
191
|
+
field: EastingNorthingField,
|
|
192
|
+
country: GeospatialFieldOptionsCountry
|
|
193
|
+
) {
|
|
194
|
+
const validateCountryBounds: CustomValidator = (value, helpers) => {
|
|
195
|
+
const countryFeature = countries.features.find(
|
|
196
|
+
(feature) => feature.id === country
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
if (!countryFeature) {
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
201
|
+
return value
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const eastingNorthing = field.getFormValueFromState(
|
|
205
|
+
value as EastingNorthingState
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
if (!eastingNorthing) {
|
|
209
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
210
|
+
return value
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const gridRef = new OsGridRef(
|
|
214
|
+
eastingNorthing.easting,
|
|
215
|
+
eastingNorthing.northing
|
|
216
|
+
)
|
|
217
|
+
const latLong = gridRef.toLatLon()
|
|
218
|
+
const coord = point([latLong.longitude, latLong.latitude])
|
|
219
|
+
const within = booleanWithin(coord, countryFeature)
|
|
220
|
+
|
|
221
|
+
if (!within) {
|
|
222
|
+
return helpers.error(
|
|
223
|
+
'any.custom',
|
|
224
|
+
{
|
|
225
|
+
country
|
|
226
|
+
},
|
|
227
|
+
{ path: [field.name] }
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
232
|
+
return value
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return validateCountryBounds
|
|
236
|
+
}
|
|
@@ -2,6 +2,8 @@ import { type ComponentDef } from '@defra/forms-model'
|
|
|
2
2
|
import joi, { type JoiExpression, type ReferenceOptions } from 'joi'
|
|
3
3
|
import lowerFirst from 'lodash/lowerFirst.js'
|
|
4
4
|
|
|
5
|
+
import { type Translator } from '../../i18n/types.js'
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Prevent Markdown formatting
|
|
7
9
|
* @see {@link https://pandoc.org/chunkedhtml-demo/8.11-backslash-escapes.html}
|
|
@@ -66,3 +68,20 @@ export const lowerFirstExpressionOptions = {
|
|
|
66
68
|
*/
|
|
67
69
|
export const createLowerFirstExpression = (template: string): JoiExpression =>
|
|
68
70
|
joi.expression(template, lowerFirstExpressionOptions) as JoiExpression
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Translate a component label, in precedence order of errorDescription, then shortDesciption, then title
|
|
74
|
+
* @param {ComponentDef} component
|
|
75
|
+
* @param {Translator} translator
|
|
76
|
+
*/
|
|
77
|
+
export function getTranslatedLabel(
|
|
78
|
+
component: ComponentDef,
|
|
79
|
+
translator: Translator
|
|
80
|
+
) {
|
|
81
|
+
const { tComponent } = translator
|
|
82
|
+
const translatedLabel =
|
|
83
|
+
tComponent(component, 'errorDescription') ||
|
|
84
|
+
tComponent(component, 'shortDescription') ||
|
|
85
|
+
tComponent(component, 'title')
|
|
86
|
+
return translatedLabel
|
|
87
|
+
}
|
|
@@ -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
|
+
*/
|