@defra/forms-engine-plugin 0.0.1
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/.browserslistrc +16 -0
- package/.editorconfig +9 -0
- package/.eslintrc.cjs +266 -0
- package/.github/dependabot.yml +85 -0
- package/.github/workflows/check-pull-request.yml +209 -0
- package/.github/workflows/pr-notifier.yml +98 -0
- package/.github/workflows/publish.yml +111 -0
- package/.husky/pre-commit +1 -0
- package/.lintstagedrc.js +4 -0
- package/.nvmrc +1 -0
- package/.prettierignore +8 -0
- package/.prettierrc.cjs +26 -0
- package/.server/client/javascripts/application.js +68 -0
- package/.server/client/javascripts/application.js.map +1 -0
- package/.server/client/javascripts/file-upload.js +292 -0
- package/.server/client/javascripts/file-upload.js.map +1 -0
- package/.server/client/stylesheets/_code.scss +33 -0
- package/.server/client/stylesheets/_govuk-frontend.scss +4 -0
- package/.server/client/stylesheets/_prose.scss +56 -0
- package/.server/client/stylesheets/_service-banner.scss +24 -0
- package/.server/client/stylesheets/_summary-list.scss +28 -0
- package/.server/client/stylesheets/_tag-env.scss +24 -0
- package/.server/client/stylesheets/application.scss +14 -0
- package/.server/common/cookies.js +55 -0
- package/.server/common/cookies.js.map +1 -0
- package/.server/common/cookies.test.js +15 -0
- package/.server/common/cookies.test.js.map +1 -0
- package/.server/common/types.js +6 -0
- package/.server/common/types.js.map +1 -0
- package/.server/config/index.js +241 -0
- package/.server/config/index.js.map +1 -0
- package/.server/index.js +25 -0
- package/.server/index.js.map +1 -0
- package/.server/server/common/helpers/logging/logger-options.js +44 -0
- package/.server/server/common/helpers/logging/logger-options.js.map +1 -0
- package/.server/server/common/helpers/logging/logger.js +6 -0
- package/.server/server/common/helpers/logging/logger.js.map +1 -0
- package/.server/server/common/helpers/logging/request-logger.js +7 -0
- package/.server/server/common/helpers/logging/request-logger.js.map +1 -0
- package/.server/server/common/helpers/logging/request-tracing.js +12 -0
- package/.server/server/common/helpers/logging/request-tracing.js.map +1 -0
- package/.server/server/common/helpers/redis-client.js +55 -0
- package/.server/server/common/helpers/redis-client.js.map +1 -0
- package/.server/server/constants.js +2 -0
- package/.server/server/constants.js.map +1 -0
- package/.server/server/forms/README.md +10 -0
- package/.server/server/forms/components.json +1015 -0
- package/.server/server/forms/report-a-terrorist.json +270 -0
- package/.server/server/forms/runner-components-test.json +365 -0
- package/.server/server/forms/test.json +581 -0
- package/.server/server/index.js +116 -0
- package/.server/server/index.js.map +1 -0
- package/.server/server/plugins/blankie.js +29 -0
- package/.server/server/plugins/blankie.js.map +1 -0
- package/.server/server/plugins/crumb.js +15 -0
- package/.server/server/plugins/crumb.js.map +1 -0
- package/.server/server/plugins/engine/README.md +87 -0
- package/.server/server/plugins/engine/components/AutocompleteField.js +37 -0
- package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -0
- package/.server/server/plugins/engine/components/CheckboxesField.js +79 -0
- package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -0
- package/.server/server/plugins/engine/components/ComponentBase.js +55 -0
- package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -0
- package/.server/server/plugins/engine/components/ComponentCollection.js +198 -0
- package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -0
- package/.server/server/plugins/engine/components/DatePartsField.js +208 -0
- package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -0
- package/.server/server/plugins/engine/components/Details.js +26 -0
- package/.server/server/plugins/engine/components/Details.js.map +1 -0
- package/.server/server/plugins/engine/components/EmailAddressField.js +40 -0
- package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -0
- package/.server/server/plugins/engine/components/FileUploadField.js +195 -0
- package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -0
- package/.server/server/plugins/engine/components/FormComponent.js +210 -0
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -0
- package/.server/server/plugins/engine/components/Html.js +24 -0
- package/.server/server/plugins/engine/components/Html.js.map +1 -0
- package/.server/server/plugins/engine/components/InsetText.js +22 -0
- package/.server/server/plugins/engine/components/InsetText.js.map +1 -0
- package/.server/server/plugins/engine/components/List.js +65 -0
- package/.server/server/plugins/engine/components/List.js.map +1 -0
- package/.server/server/plugins/engine/components/ListFormComponent.js +87 -0
- package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -0
- package/.server/server/plugins/engine/components/MonthYearField.js +172 -0
- package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -0
- package/.server/server/plugins/engine/components/MultilineTextField.js +115 -0
- package/.server/server/plugins/engine/components/MultilineTextField.js.map +1 -0
- package/.server/server/plugins/engine/components/NumberField.js +137 -0
- package/.server/server/plugins/engine/components/NumberField.js.map +1 -0
- package/.server/server/plugins/engine/components/RadiosField.js +18 -0
- package/.server/server/plugins/engine/components/RadiosField.js.map +1 -0
- package/.server/server/plugins/engine/components/SelectField.js +33 -0
- package/.server/server/plugins/engine/components/SelectField.js.map +1 -0
- package/.server/server/plugins/engine/components/SelectionControlField.js +43 -0
- package/.server/server/plugins/engine/components/SelectionControlField.js.map +1 -0
- package/.server/server/plugins/engine/components/TelephoneNumberField.js +43 -0
- package/.server/server/plugins/engine/components/TelephoneNumberField.js.map +1 -0
- package/.server/server/plugins/engine/components/TextField.js +63 -0
- package/.server/server/plugins/engine/components/TextField.js.map +1 -0
- package/.server/server/plugins/engine/components/UkAddressField.js +130 -0
- package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -0
- package/.server/server/plugins/engine/components/YesNoField.js +28 -0
- package/.server/server/plugins/engine/components/YesNoField.js.map +1 -0
- package/.server/server/plugins/engine/components/constants.js +2 -0
- package/.server/server/plugins/engine/components/constants.js.map +1 -0
- package/.server/server/plugins/engine/components/helpers.js +219 -0
- package/.server/server/plugins/engine/components/helpers.js.map +1 -0
- package/.server/server/plugins/engine/components/index.js +25 -0
- package/.server/server/plugins/engine/components/index.js.map +1 -0
- package/.server/server/plugins/engine/components/types.js +2 -0
- package/.server/server/plugins/engine/components/types.js.map +1 -0
- package/.server/server/plugins/engine/configureEnginePlugin.js +44 -0
- package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -0
- package/.server/server/plugins/engine/helpers.js +268 -0
- package/.server/server/plugins/engine/helpers.js.map +1 -0
- package/.server/server/plugins/engine/index.js +6 -0
- package/.server/server/plugins/engine/index.js.map +1 -0
- package/.server/server/plugins/engine/models/FormModel.js +363 -0
- package/.server/server/plugins/engine/models/FormModel.js.map +1 -0
- package/.server/server/plugins/engine/models/RepeatingSummaryViewModel.js +2 -0
- package/.server/server/plugins/engine/models/RepeatingSummaryViewModel.js.map +1 -0
- package/.server/server/plugins/engine/models/Section.js +2 -0
- package/.server/server/plugins/engine/models/Section.js.map +1 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js +183 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -0
- package/.server/server/plugins/engine/models/index.js +3 -0
- package/.server/server/plugins/engine/models/index.js.map +1 -0
- package/.server/server/plugins/engine/models/types.js +2 -0
- package/.server/server/plugins/engine/models/types.js.map +1 -0
- package/.server/server/plugins/engine/outputFormatters/human/v1.js +44 -0
- package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -0
- package/.server/server/plugins/engine/outputFormatters/index.js +24 -0
- package/.server/server/plugins/engine/outputFormatters/index.js.map +1 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v1.js +104 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v1.js.map +1 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js +110 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +401 -0
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/PageController.js +133 -0
- package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +482 -0
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/README.md +28 -0
- package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +372 -0
- package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/StartPageController.js +16 -0
- package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/StatusPageController.js +43 -0
- package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +195 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/TerminalPageController.js +8 -0
- package/.server/server/plugins/engine/pageControllers/TerminalPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/helpers.js +69 -0
- package/.server/server/plugins/engine/pageControllers/helpers.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/index.js +10 -0
- package/.server/server/plugins/engine/pageControllers/index.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/validationOptions.js +78 -0
- package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -0
- package/.server/server/plugins/engine/plugin.js +562 -0
- package/.server/server/plugins/engine/plugin.js.map +1 -0
- package/.server/server/plugins/engine/services/formSubmissionService.js +39 -0
- package/.server/server/plugins/engine/services/formSubmissionService.js.map +1 -0
- package/.server/server/plugins/engine/services/formsService.js +41 -0
- package/.server/server/plugins/engine/services/formsService.js.map +1 -0
- package/.server/server/plugins/engine/services/formsService.test.js +71 -0
- package/.server/server/plugins/engine/services/formsService.test.js.map +1 -0
- package/.server/server/plugins/engine/services/index.js +4 -0
- package/.server/server/plugins/engine/services/index.js.map +1 -0
- package/.server/server/plugins/engine/services/notifyService.js +45 -0
- package/.server/server/plugins/engine/services/notifyService.js.map +1 -0
- package/.server/server/plugins/engine/services/uploadService.js +51 -0
- package/.server/server/plugins/engine/services/uploadService.js.map +1 -0
- package/.server/server/plugins/engine/types.js +53 -0
- package/.server/server/plugins/engine/types.js.map +1 -0
- package/.server/server/plugins/engine/views/components/autocompletefield.html +5 -0
- package/.server/server/plugins/engine/views/components/checkboxesfield.html +5 -0
- package/.server/server/plugins/engine/views/components/datepartsfield.html +5 -0
- package/.server/server/plugins/engine/views/components/details.html +6 -0
- package/.server/server/plugins/engine/views/components/emailaddressfield.html +5 -0
- package/.server/server/plugins/engine/views/components/fileuploadfield-key.html +8 -0
- package/.server/server/plugins/engine/views/components/fileuploadfield-value.html +3 -0
- package/.server/server/plugins/engine/views/components/fileuploadfield.html +24 -0
- package/.server/server/plugins/engine/views/components/html.html +3 -0
- package/.server/server/plugins/engine/views/components/insettext.html +7 -0
- package/.server/server/plugins/engine/views/components/list.html +36 -0
- package/.server/server/plugins/engine/views/components/monthyearfield.html +5 -0
- package/.server/server/plugins/engine/views/components/multilinetextfield.html +10 -0
- package/.server/server/plugins/engine/views/components/numberfield.html +5 -0
- package/.server/server/plugins/engine/views/components/radiosfield.html +5 -0
- package/.server/server/plugins/engine/views/components/selectfield.html +5 -0
- package/.server/server/plugins/engine/views/components/telephonenumberfield.html +5 -0
- package/.server/server/plugins/engine/views/components/textfield.html +5 -0
- package/.server/server/plugins/engine/views/components/ukaddressfield.html +25 -0
- package/.server/server/plugins/engine/views/components/yesnofield.html +5 -0
- package/.server/server/plugins/engine/views/file-upload.html +45 -0
- package/.server/server/plugins/engine/views/index.html +39 -0
- package/.server/server/plugins/engine/views/item-delete.html +56 -0
- package/.server/server/plugins/engine/views/partials/components.html +6 -0
- package/.server/server/plugins/engine/views/partials/conditional-components.html +3 -0
- package/.server/server/plugins/engine/views/partials/debug.html +44 -0
- package/.server/server/plugins/engine/views/partials/form.html +15 -0
- package/.server/server/plugins/engine/views/partials/heading.html +16 -0
- package/.server/server/plugins/engine/views/partials/preview-banner.html +32 -0
- package/.server/server/plugins/engine/views/partials/preview-banner.test.js +108 -0
- package/.server/server/plugins/engine/views/partials/preview-banner.test.js.map +1 -0
- package/.server/server/plugins/engine/views/partials/warn-missing-notification-email.html +10 -0
- package/.server/server/plugins/engine/views/repeat-list-summary.html +53 -0
- package/.server/server/plugins/errorPages.js +49 -0
- package/.server/server/plugins/errorPages.js.map +1 -0
- package/.server/server/plugins/nunjucks/context.js +79 -0
- package/.server/server/plugins/nunjucks/context.js.map +1 -0
- package/.server/server/plugins/nunjucks/context.test.js +134 -0
- package/.server/server/plugins/nunjucks/context.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/enviroment.test.js +166 -0
- package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/environment.js +95 -0
- package/.server/server/plugins/nunjucks/environment.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/answer.js +26 -0
- package/.server/server/plugins/nunjucks/filters/answer.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/answer.test.js +70 -0
- package/.server/server/plugins/nunjucks/filters/answer.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/evaluate.js +22 -0
- package/.server/server/plugins/nunjucks/filters/evaluate.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/field.js +26 -0
- package/.server/server/plugins/nunjucks/filters/field.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/field.test.js +64 -0
- package/.server/server/plugins/nunjucks/filters/field.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/highlight.js +14 -0
- package/.server/server/plugins/nunjucks/filters/highlight.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/href.js +28 -0
- package/.server/server/plugins/nunjucks/filters/href.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/href.test.js +63 -0
- package/.server/server/plugins/nunjucks/filters/href.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/index.js +9 -0
- package/.server/server/plugins/nunjucks/filters/index.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/inspect.js +16 -0
- package/.server/server/plugins/nunjucks/filters/inspect.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/page.js +23 -0
- package/.server/server/plugins/nunjucks/filters/page.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/page.test.js +51 -0
- package/.server/server/plugins/nunjucks/filters/page.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/index.js +4 -0
- package/.server/server/plugins/nunjucks/index.js.map +1 -0
- package/.server/server/plugins/nunjucks/plugin.js +38 -0
- package/.server/server/plugins/nunjucks/plugin.js.map +1 -0
- package/.server/server/plugins/nunjucks/render.js +41 -0
- package/.server/server/plugins/nunjucks/render.js.map +1 -0
- package/.server/server/plugins/nunjucks/types.js +41 -0
- package/.server/server/plugins/nunjucks/types.js.map +1 -0
- package/.server/server/plugins/pulse.js +8 -0
- package/.server/server/plugins/pulse.js.map +1 -0
- package/.server/server/plugins/router.js +169 -0
- package/.server/server/plugins/router.js.map +1 -0
- package/.server/server/plugins/session.js +28 -0
- package/.server/server/plugins/session.js.map +1 -0
- package/.server/server/routes/health.js +15 -0
- package/.server/server/routes/health.js.map +1 -0
- package/.server/server/routes/health.test.js +32 -0
- package/.server/server/routes/health.test.js.map +1 -0
- package/.server/server/routes/index.js +3 -0
- package/.server/server/routes/index.js.map +1 -0
- package/.server/server/routes/public.js +37 -0
- package/.server/server/routes/public.js.map +1 -0
- package/.server/server/routes/types.js +14 -0
- package/.server/server/routes/types.js.map +1 -0
- package/.server/server/schemas/index.js +15 -0
- package/.server/server/schemas/index.js.map +1 -0
- package/.server/server/secure-context.js +36 -0
- package/.server/server/secure-context.js.map +1 -0
- package/.server/server/services/cacheService.js +85 -0
- package/.server/server/services/cacheService.js.map +1 -0
- package/.server/server/services/httpService.js +44 -0
- package/.server/server/services/httpService.js.map +1 -0
- package/.server/server/services/httpService.test.js +504 -0
- package/.server/server/services/httpService.test.js.map +1 -0
- package/.server/server/services/index.js +2 -0
- package/.server/server/services/index.js.map +1 -0
- package/.server/server/types.js +2 -0
- package/.server/server/types.js.map +1 -0
- package/.server/server/utils/notify.js +40 -0
- package/.server/server/utils/notify.js.map +1 -0
- package/.server/server/utils/secure-context/get-trust-store-certs.js +7 -0
- package/.server/server/utils/secure-context/get-trust-store-certs.js.map +1 -0
- package/.server/server/utils/secure-context/get-trust-store-certs.test.js +14 -0
- package/.server/server/utils/secure-context/get-trust-store-certs.test.js.map +1 -0
- package/.server/server/utils/utils.js +20 -0
- package/.server/server/utils/utils.js.map +1 -0
- package/.server/server/utils/utils.test.js +49 -0
- package/.server/server/utils/utils.test.js.map +1 -0
- package/.server/server/views/404.html +16 -0
- package/.server/server/views/500.html +19 -0
- package/.server/server/views/components/debug/macro.njk +3 -0
- package/.server/server/views/components/debug/template.njk +13 -0
- package/.server/server/views/components/service-banner/macro.njk +3 -0
- package/.server/server/views/components/service-banner/template.njk +20 -0
- package/.server/server/views/components/service-banner/template.test.js +36 -0
- package/.server/server/views/components/service-banner/template.test.js.map +1 -0
- package/.server/server/views/components/tag-env/macro.njk +3 -0
- package/.server/server/views/components/tag-env/template.njk +30 -0
- package/.server/server/views/components/tag-env/template.test.js +59 -0
- package/.server/server/views/components/tag-env/template.test.js.map +1 -0
- package/.server/server/views/confirmation.html +19 -0
- package/.server/server/views/help/accessibility-statement.html +58 -0
- package/.server/server/views/help/cookie-preferences.html +57 -0
- package/.server/server/views/help/cookies.html +71 -0
- package/.server/server/views/help/get-support.html +37 -0
- package/.server/server/views/help/privacy-notice.html +68 -0
- package/.server/server/views/help/terms-and-conditions.html +83 -0
- package/.server/server/views/layout.html +199 -0
- package/.server/server/views/summary.html +50 -0
- package/.server/typings/hapi/index.d.js +2 -0
- package/.server/typings/hapi/index.d.js.map +1 -0
- package/.server/typings/hapi-tracing/index.d.js +2 -0
- package/.server/typings/hapi-tracing/index.d.js.map +1 -0
- package/.server/typings/index.d.js +2 -0
- package/.server/typings/index.d.js.map +1 -0
- package/.server/typings/joi/index.d.js +2 -0
- package/.server/typings/joi/index.d.js.map +1 -0
- package/Dockerfile +61 -0
- package/LICENCE +8 -0
- package/Procfile +1 -0
- package/README.md +87 -0
- package/babel.config.cjs +55 -0
- package/compose/aws.env +4 -0
- package/compose/start-localstack.sh +26 -0
- package/docker-compose.yaml +86 -0
- package/globals.d.ts +1 -0
- package/jest.config.cjs +54 -0
- package/jest.environment.js +4 -0
- package/jest.setup.cjs +14 -0
- package/package.json +163 -0
- package/postcss.config.js +26 -0
- package/sonar-project.properties +17 -0
- package/src/client/javascripts/application.js +87 -0
- package/src/client/javascripts/file-upload.js +386 -0
- package/src/client/stylesheets/_code.scss +33 -0
- package/src/client/stylesheets/_govuk-frontend.scss +4 -0
- package/src/client/stylesheets/_prose.scss +56 -0
- package/src/client/stylesheets/_service-banner.scss +24 -0
- package/src/client/stylesheets/_summary-list.scss +28 -0
- package/src/client/stylesheets/_tag-env.scss +24 -0
- package/src/client/stylesheets/application.scss +14 -0
- package/src/common/cookies.js +58 -0
- package/src/common/cookies.test.js +23 -0
- package/src/common/types.js +5 -0
- package/src/config/index.ts +271 -0
- package/src/index.ts +31 -0
- package/src/server/common/helpers/logging/logger-options.test.ts +50 -0
- package/src/server/common/helpers/logging/logger-options.ts +46 -0
- package/src/server/common/helpers/logging/logger.ts +7 -0
- package/src/server/common/helpers/logging/request-logger.ts +9 -0
- package/src/server/common/helpers/logging/request-tracing.js +10 -0
- package/src/server/common/helpers/redis-client.js +70 -0
- package/src/server/constants.js +1 -0
- package/src/server/forms/README.md +10 -0
- package/src/server/forms/components.json +1015 -0
- package/src/server/forms/report-a-terrorist.json +270 -0
- package/src/server/forms/runner-components-test.json +365 -0
- package/src/server/forms/test.json +581 -0
- package/src/server/index.test.ts +582 -0
- package/src/server/index.ts +140 -0
- package/src/server/plugins/blankie.test.ts +73 -0
- package/src/server/plugins/blankie.ts +48 -0
- package/src/server/plugins/crumb.ts +20 -0
- package/src/server/plugins/engine/README.md +87 -0
- package/src/server/plugins/engine/components/AutocompleteField.test.ts +294 -0
- package/src/server/plugins/engine/components/AutocompleteField.ts +49 -0
- package/src/server/plugins/engine/components/CheckboxesField.test.ts +379 -0
- package/src/server/plugins/engine/components/CheckboxesField.ts +106 -0
- package/src/server/plugins/engine/components/ComponentBase.ts +97 -0
- package/src/server/plugins/engine/components/ComponentCollection.ts +278 -0
- package/src/server/plugins/engine/components/DatePartsField.test.ts +822 -0
- package/src/server/plugins/engine/components/DatePartsField.ts +264 -0
- package/src/server/plugins/engine/components/Details.test.ts +49 -0
- package/src/server/plugins/engine/components/Details.ts +30 -0
- package/src/server/plugins/engine/components/EmailAddressField.test.ts +395 -0
- package/src/server/plugins/engine/components/EmailAddressField.ts +55 -0
- package/src/server/plugins/engine/components/FileUploadField.test.ts +778 -0
- package/src/server/plugins/engine/components/FileUploadField.ts +262 -0
- package/src/server/plugins/engine/components/FormComponent.ts +249 -0
- package/src/server/plugins/engine/components/Html.test.ts +48 -0
- package/src/server/plugins/engine/components/Html.ts +29 -0
- package/src/server/plugins/engine/components/InsetText.test.ts +48 -0
- package/src/server/plugins/engine/components/InsetText.ts +27 -0
- package/src/server/plugins/engine/components/List.test.ts +76 -0
- package/src/server/plugins/engine/components/List.ts +72 -0
- package/src/server/plugins/engine/components/ListFormComponent.ts +140 -0
- package/src/server/plugins/engine/components/MonthYearField.test.ts +567 -0
- package/src/server/plugins/engine/components/MonthYearField.ts +222 -0
- package/src/server/plugins/engine/components/MultilineTextField.test.ts +558 -0
- package/src/server/plugins/engine/components/MultilineTextField.ts +138 -0
- package/src/server/plugins/engine/components/NumberField.test.ts +701 -0
- package/src/server/plugins/engine/components/NumberField.ts +163 -0
- package/src/server/plugins/engine/components/RadiosField.test.ts +288 -0
- package/src/server/plugins/engine/components/RadiosField.ts +24 -0
- package/src/server/plugins/engine/components/SelectField.test.ts +288 -0
- package/src/server/plugins/engine/components/SelectField.ts +47 -0
- package/src/server/plugins/engine/components/SelectionControlField.ts +43 -0
- package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +356 -0
- package/src/server/plugins/engine/components/TelephoneNumberField.ts +67 -0
- package/src/server/plugins/engine/components/TextField.test.ts +489 -0
- package/src/server/plugins/engine/components/TextField.ts +96 -0
- package/src/server/plugins/engine/components/UkAddressField.test.ts +623 -0
- package/src/server/plugins/engine/components/UkAddressField.ts +172 -0
- package/src/server/plugins/engine/components/YesNoField.test.ts +248 -0
- package/src/server/plugins/engine/components/YesNoField.ts +31 -0
- package/src/server/plugins/engine/components/constants.ts +1 -0
- package/src/server/plugins/engine/components/helpers.ts +330 -0
- package/src/server/plugins/engine/components/index.ts +24 -0
- package/src/server/plugins/engine/components/types.ts +117 -0
- package/src/server/plugins/engine/configureEnginePlugin.ts +47 -0
- package/src/server/plugins/engine/helpers.test.ts +791 -0
- package/src/server/plugins/engine/helpers.ts +379 -0
- package/src/server/plugins/engine/index.ts +7 -0
- package/src/server/plugins/engine/models/FormModel.test.ts +42 -0
- package/src/server/plugins/engine/models/FormModel.ts +443 -0
- package/src/server/plugins/engine/models/RepeatingSummaryViewModel.ts +0 -0
- package/src/server/plugins/engine/models/Section.ts +0 -0
- package/src/server/plugins/engine/models/SummaryViewModel.test.ts +209 -0
- package/src/server/plugins/engine/models/SummaryViewModel.ts +220 -0
- package/src/server/plugins/engine/models/index.ts +2 -0
- package/src/server/plugins/engine/models/types.ts +114 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +143 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.ts +73 -0
- package/src/server/plugins/engine/outputFormatters/index.test.ts +17 -0
- package/src/server/plugins/engine/outputFormatters/index.ts +44 -0
- package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +229 -0
- package/src/server/plugins/engine/outputFormatters/machine/v1.ts +140 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +229 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.ts +153 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +1108 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +446 -0
- package/src/server/plugins/engine/pageControllers/PageController.test.ts +205 -0
- package/src/server/plugins/engine/pageControllers/PageController.ts +176 -0
- package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +1264 -0
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +561 -0
- package/src/server/plugins/engine/pageControllers/README.md +28 -0
- package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +264 -0
- package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +458 -0
- package/src/server/plugins/engine/pageControllers/StartPageController.ts +18 -0
- package/src/server/plugins/engine/pageControllers/StatusPageController.ts +50 -0
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +261 -0
- package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +28 -0
- package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +19 -0
- package/src/server/plugins/engine/pageControllers/helpers.test.ts +198 -0
- package/src/server/plugins/engine/pageControllers/helpers.ts +101 -0
- package/src/server/plugins/engine/pageControllers/index.ts +10 -0
- package/src/server/plugins/engine/pageControllers/validationOptions.ts +89 -0
- package/src/server/plugins/engine/plugin.ts +673 -0
- package/src/server/plugins/engine/services/formSubmissionService.js +46 -0
- package/src/server/plugins/engine/services/formsService.js +46 -0
- package/src/server/plugins/engine/services/formsService.test.js +90 -0
- package/src/server/plugins/engine/services/index.js +3 -0
- package/src/server/plugins/engine/services/notifyService.test.ts +132 -0
- package/src/server/plugins/engine/services/notifyService.ts +64 -0
- package/src/server/plugins/engine/services/uploadService.js +60 -0
- package/src/server/plugins/engine/types.ts +315 -0
- package/src/server/plugins/engine/views/components/autocompletefield.html +5 -0
- package/src/server/plugins/engine/views/components/checkboxesfield.html +5 -0
- package/src/server/plugins/engine/views/components/datepartsfield.html +5 -0
- package/src/server/plugins/engine/views/components/details.html +6 -0
- package/src/server/plugins/engine/views/components/emailaddressfield.html +5 -0
- package/src/server/plugins/engine/views/components/fileuploadfield-key.html +8 -0
- package/src/server/plugins/engine/views/components/fileuploadfield-value.html +3 -0
- package/src/server/plugins/engine/views/components/fileuploadfield.html +24 -0
- package/src/server/plugins/engine/views/components/html.html +3 -0
- package/src/server/plugins/engine/views/components/insettext.html +7 -0
- package/src/server/plugins/engine/views/components/list.html +36 -0
- package/src/server/plugins/engine/views/components/monthyearfield.html +5 -0
- package/src/server/plugins/engine/views/components/multilinetextfield.html +10 -0
- package/src/server/plugins/engine/views/components/numberfield.html +5 -0
- package/src/server/plugins/engine/views/components/radiosfield.html +5 -0
- package/src/server/plugins/engine/views/components/selectfield.html +5 -0
- package/src/server/plugins/engine/views/components/telephonenumberfield.html +5 -0
- package/src/server/plugins/engine/views/components/textfield.html +5 -0
- package/src/server/plugins/engine/views/components/ukaddressfield.html +25 -0
- package/src/server/plugins/engine/views/components/yesnofield.html +5 -0
- package/src/server/plugins/engine/views/file-upload.html +45 -0
- package/src/server/plugins/engine/views/index.html +39 -0
- package/src/server/plugins/engine/views/item-delete.html +56 -0
- package/src/server/plugins/engine/views/partials/components.html +6 -0
- package/src/server/plugins/engine/views/partials/conditional-components.html +3 -0
- package/src/server/plugins/engine/views/partials/debug.html +44 -0
- package/src/server/plugins/engine/views/partials/form.html +15 -0
- package/src/server/plugins/engine/views/partials/heading.html +16 -0
- package/src/server/plugins/engine/views/partials/preview-banner.html +32 -0
- package/src/server/plugins/engine/views/partials/preview-banner.test.js +122 -0
- package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +10 -0
- package/src/server/plugins/engine/views/repeat-list-summary.html +53 -0
- package/src/server/plugins/errorPages.ts +58 -0
- package/src/server/plugins/nunjucks/context.js +88 -0
- package/src/server/plugins/nunjucks/context.test.js +142 -0
- package/src/server/plugins/nunjucks/enviroment.test.js +201 -0
- package/src/server/plugins/nunjucks/environment.js +116 -0
- package/src/server/plugins/nunjucks/filters/answer.js +27 -0
- package/src/server/plugins/nunjucks/filters/answer.test.js +89 -0
- package/src/server/plugins/nunjucks/filters/evaluate.js +21 -0
- package/src/server/plugins/nunjucks/filters/field.js +28 -0
- package/src/server/plugins/nunjucks/filters/field.test.js +75 -0
- package/src/server/plugins/nunjucks/filters/highlight.js +11 -0
- package/src/server/plugins/nunjucks/filters/href.js +30 -0
- package/src/server/plugins/nunjucks/filters/href.test.js +80 -0
- package/src/server/plugins/nunjucks/filters/index.js +8 -0
- package/src/server/plugins/nunjucks/filters/inspect.js +15 -0
- package/src/server/plugins/nunjucks/filters/page.js +24 -0
- package/src/server/plugins/nunjucks/filters/page.test.js +65 -0
- package/src/server/plugins/nunjucks/index.js +3 -0
- package/src/server/plugins/nunjucks/plugin.js +40 -0
- package/src/server/plugins/nunjucks/render.js +42 -0
- package/src/server/plugins/nunjucks/types.js +40 -0
- package/src/server/plugins/pulse.ts +11 -0
- package/src/server/plugins/router.ts +201 -0
- package/src/server/plugins/session.ts +28 -0
- package/src/server/routes/health.js +13 -0
- package/src/server/routes/health.test.js +35 -0
- package/src/server/routes/index.test.ts +125 -0
- package/src/server/routes/index.ts +2 -0
- package/src/server/routes/public.ts +47 -0
- package/src/server/routes/types.ts +48 -0
- package/src/server/schemas/index.ts +34 -0
- package/src/server/secure-context.js +43 -0
- package/src/server/services/cacheService.test.ts +276 -0
- package/src/server/services/cacheService.ts +131 -0
- package/src/server/services/httpService.test.js +491 -0
- package/src/server/services/httpService.ts +50 -0
- package/src/server/services/index.ts +1 -0
- package/src/server/types.ts +54 -0
- package/src/server/utils/notify.test.ts +37 -0
- package/src/server/utils/notify.ts +50 -0
- package/src/server/utils/secure-context/get-trust-store-certs.js +11 -0
- package/src/server/utils/secure-context/get-trust-store-certs.test.js +19 -0
- package/src/server/utils/utils.js +24 -0
- package/src/server/utils/utils.test.js +54 -0
- package/src/server/views/404.html +16 -0
- package/src/server/views/500.html +19 -0
- package/src/server/views/components/debug/macro.njk +3 -0
- package/src/server/views/components/debug/template.njk +13 -0
- package/src/server/views/components/service-banner/macro.njk +3 -0
- package/src/server/views/components/service-banner/template.njk +20 -0
- package/src/server/views/components/service-banner/template.test.js +43 -0
- package/src/server/views/components/tag-env/macro.njk +3 -0
- package/src/server/views/components/tag-env/template.njk +30 -0
- package/src/server/views/components/tag-env/template.test.js +66 -0
- package/src/server/views/confirmation.html +19 -0
- package/src/server/views/help/accessibility-statement.html +58 -0
- package/src/server/views/help/cookie-preferences.html +57 -0
- package/src/server/views/help/cookies.html +71 -0
- package/src/server/views/help/get-support.html +37 -0
- package/src/server/views/help/privacy-notice.html +68 -0
- package/src/server/views/help/terms-and-conditions.html +83 -0
- package/src/server/views/layout.html +199 -0
- package/src/server/views/summary.html +50 -0
- package/src/typings/hapi/index.d.ts +95 -0
- package/src/typings/hapi-tracing/index.d.ts +6 -0
- package/src/typings/index.d.ts +3 -0
- package/src/typings/joi/index.d.ts +22 -0
- package/stylelint.config.js +10 -0
- package/test/client/javascripts/file-upload.test.js +1197 -0
- package/test/condition/checkboxes.test.js +112 -0
- package/test/condition/radios.test.js +112 -0
- package/test/condition/text.test.js +103 -0
- package/test/fixtures/assets-manifest.json +4 -0
- package/test/fixtures/form.js +86 -0
- package/test/fixtures/index.js +2 -0
- package/test/fixtures/list.js +92 -0
- package/test/form/cookies.test.js +338 -0
- package/test/form/csrf.test.js +87 -0
- package/test/form/definitions/basic.js +101 -0
- package/test/form/definitions/blank.js +10 -0
- package/test/form/definitions/checkboxes.json +88 -0
- package/test/form/definitions/components.json +452 -0
- package/test/form/definitions/conditional-reveal.js +140 -0
- package/test/form/definitions/conditions-basic.js +187 -0
- package/test/form/definitions/conditions-complex.js +338 -0
- package/test/form/definitions/conditions-dates.js +78 -0
- package/test/form/definitions/conditions-escaping.js +143 -0
- package/test/form/definitions/demo-cph-number.js +3099 -0
- package/test/form/definitions/feedback.json +45 -0
- package/test/form/definitions/fields-optional.js +402 -0
- package/test/form/definitions/fields-required.js +402 -0
- package/test/form/definitions/file-upload-basic.js +44 -0
- package/test/form/definitions/file-upload.js +66 -0
- package/test/form/definitions/minimal.js +39 -0
- package/test/form/definitions/phase-alpha.json +33 -0
- package/test/form/definitions/phase-default.json +26 -0
- package/test/form/definitions/radios.json +88 -0
- package/test/form/definitions/repeat-mixed.js +54 -0
- package/test/form/definitions/repeat.js +70 -0
- package/test/form/definitions/status.json +126 -0
- package/test/form/definitions/templates.js +183 -0
- package/test/form/definitions/test.json +581 -0
- package/test/form/definitions/text.json +75 -0
- package/test/form/definitions/titles.json +170 -0
- package/test/form/definitions.test.js +47 -0
- package/test/form/exit-page.test.js +210 -0
- package/test/form/feedback.test.js +68 -0
- package/test/form/fields-optional.test.js +237 -0
- package/test/form/fields-required.test.js +294 -0
- package/test/form/file-upload.test.js +313 -0
- package/test/form/govuk-notify.test.js +449 -0
- package/test/form/journey-basic.test.js +444 -0
- package/test/form/persist-files.test.js +227 -0
- package/test/form/phase-banner.test.js +71 -0
- package/test/form/repeat.test.js +628 -0
- package/test/form/summary-submission-email.test.js +95 -0
- package/test/form/template.test.js +288 -0
- package/test/form/titles.test.js +204 -0
- package/test/helpers/component-helpers.js +74 -0
- package/test/utils/get-cookie.js +42 -0
- package/test/utils/get-form-definitions.js +18 -0
- package/tmp.pdf +1 -0
- package/tsconfig.json +28 -0
- package/webpack.config.js +208 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formSubmissionService.js","names":["config","postJson","submissionUrl","get","persistFiles","files","persistedRetrievalKey","postJsonByType","payload","result","submit","data"],"sources":["../../../../../src/server/plugins/engine/services/formSubmissionService.js"],"sourcesContent":["import { config } from '~/src/config/index.js'\nimport { postJson } from '~/src/server/services/httpService.js'\n\nconst submissionUrl = config.get('submissionUrl')\n\n/**\n * Persist files by extending the time-to-live to 30 days\n * @param {{fileId: string, initiatedRetrievalKey: string}[]} files - batch of files to persist\n * @param {string} persistedRetrievalKey - final retrieval key when submitting\n */\nexport async function persistFiles(files, persistedRetrievalKey) {\n const postJsonByType = /** @type {typeof postJson<object>} */ (postJson)\n\n const payload = {\n files,\n persistedRetrievalKey\n }\n\n const result = await postJsonByType(`${submissionUrl}/files/persist`, {\n payload\n })\n\n return result\n}\n\n/**\n * Submit form\n * @param {SubmitPayload} data - submission data\n */\nexport async function submit(data) {\n const postJsonByType = /** @type {typeof postJson<SubmitResponsePayload>} */ (\n postJson\n )\n\n const payload = data\n\n const result = await postJsonByType(`${submissionUrl}/submit`, {\n payload\n })\n\n return result.payload\n}\n\n/**\n * @import { SubmitPayload, SubmitResponsePayload } from '@defra/forms-model'\n */\n"],"mappings":"AAAA,SAASA,MAAM;AACf,SAASC,QAAQ;AAEjB,MAAMC,aAAa,GAAGF,MAAM,CAACG,GAAG,CAAC,eAAe,CAAC;;AAEjD;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,YAAYA,CAACC,KAAK,EAAEC,qBAAqB,EAAE;EAC/D,MAAMC,cAAc,GAAG,sCAAwCN,QAAS;EAExE,MAAMO,OAAO,GAAG;IACdH,KAAK;IACLC;EACF,CAAC;EAED,MAAMG,MAAM,GAAG,MAAMF,cAAc,CAAC,GAAGL,aAAa,gBAAgB,EAAE;IACpEM;EACF,CAAC,CAAC;EAEF,OAAOC,MAAM;AACf;;AAEA;AACA;AACA;AACA;AACA,OAAO,eAAeC,MAAMA,CAACC,IAAI,EAAE;EACjC,MAAMJ,cAAc,GAAG;EACrBN,QACD;EAED,MAAMO,OAAO,GAAGG,IAAI;EAEpB,MAAMF,MAAM,GAAG,MAAMF,cAAc,CAAC,GAAGL,aAAa,SAAS,EAAE;IAC7DM;EACF,CAAC,CAAC;EAEF,OAAOC,MAAM,CAACD,OAAO;AACvB;;AAEA;AACA;AACA","ignoreList":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { formMetadataSchema } from '@defra/forms-model';
|
|
2
|
+
import { config } from "../../../../config/index.js";
|
|
3
|
+
import { FormStatus } from "../../../routes/types.js";
|
|
4
|
+
import { getJson } from "../../../services/httpService.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Retrieves a form definition from the form manager for a given slug
|
|
8
|
+
* @param {string} slug - the slug of the form
|
|
9
|
+
*/
|
|
10
|
+
export async function getFormMetadata(slug) {
|
|
11
|
+
const getJsonByType = /** @type {typeof getJson<FormMetadata>} */getJson;
|
|
12
|
+
const {
|
|
13
|
+
payload: metadata
|
|
14
|
+
} = await getJsonByType(`${config.get('managerUrl')}/forms/slug/${slug}`);
|
|
15
|
+
|
|
16
|
+
// Run it through the schema to coerce dates
|
|
17
|
+
const result = formMetadataSchema.validate(metadata);
|
|
18
|
+
if (result.error) {
|
|
19
|
+
throw result.error;
|
|
20
|
+
}
|
|
21
|
+
return result.value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Retrieves a form definition from the form manager for a given id
|
|
26
|
+
* @param {string} id - the id of the form
|
|
27
|
+
* @param {FormStatus} state - the state of the form
|
|
28
|
+
*/
|
|
29
|
+
export async function getFormDefinition(id, state) {
|
|
30
|
+
const getJsonByType = /** @type {typeof getJson<FormDefinition>} */getJson;
|
|
31
|
+
const suffix = state === FormStatus.Draft ? `/${state}` : '';
|
|
32
|
+
const {
|
|
33
|
+
payload: definition
|
|
34
|
+
} = await getJsonByType(`${config.get('managerUrl')}/forms/${id}/definition${suffix}`);
|
|
35
|
+
return definition;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @import { FormDefinition, FormMetadata } from '@defra/forms-model'
|
|
40
|
+
*/
|
|
41
|
+
//# sourceMappingURL=formsService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formsService.js","names":["formMetadataSchema","config","FormStatus","getJson","getFormMetadata","slug","getJsonByType","payload","metadata","get","result","validate","error","value","getFormDefinition","id","state","suffix","Draft","definition"],"sources":["../../../../../src/server/plugins/engine/services/formsService.js"],"sourcesContent":["import { formMetadataSchema } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { FormStatus } from '~/src/server/routes/types.js'\nimport { getJson } from '~/src/server/services/httpService.js'\n\n/**\n * Retrieves a form definition from the form manager for a given slug\n * @param {string} slug - the slug of the form\n */\nexport async function getFormMetadata(slug) {\n const getJsonByType = /** @type {typeof getJson<FormMetadata>} */ (getJson)\n\n const { payload: metadata } = await getJsonByType(\n `${config.get('managerUrl')}/forms/slug/${slug}`\n )\n\n // Run it through the schema to coerce dates\n const result = formMetadataSchema.validate(metadata)\n\n if (result.error) {\n throw result.error\n }\n\n return result.value\n}\n\n/**\n * Retrieves a form definition from the form manager for a given id\n * @param {string} id - the id of the form\n * @param {FormStatus} state - the state of the form\n */\nexport async function getFormDefinition(id, state) {\n const getJsonByType = /** @type {typeof getJson<FormDefinition>} */ (getJson)\n\n const suffix = state === FormStatus.Draft ? `/${state}` : ''\n const { payload: definition } = await getJsonByType(\n `${config.get('managerUrl')}/forms/${id}/definition${suffix}`\n )\n\n return definition\n}\n\n/**\n * @import { FormDefinition, FormMetadata } from '@defra/forms-model'\n */\n"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,oBAAoB;AAEvD,SAASC,MAAM;AACf,SAASC,UAAU;AACnB,SAASC,OAAO;;AAEhB;AACA;AACA;AACA;AACA,OAAO,eAAeC,eAAeA,CAACC,IAAI,EAAE;EAC1C,MAAMC,aAAa,GAAG,2CAA6CH,OAAQ;EAE3E,MAAM;IAAEI,OAAO,EAAEC;EAAS,CAAC,GAAG,MAAMF,aAAa,CAC/C,GAAGL,MAAM,CAACQ,GAAG,CAAC,YAAY,CAAC,eAAeJ,IAAI,EAChD,CAAC;;EAED;EACA,MAAMK,MAAM,GAAGV,kBAAkB,CAACW,QAAQ,CAACH,QAAQ,CAAC;EAEpD,IAAIE,MAAM,CAACE,KAAK,EAAE;IAChB,MAAMF,MAAM,CAACE,KAAK;EACpB;EAEA,OAAOF,MAAM,CAACG,KAAK;AACrB;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,iBAAiBA,CAACC,EAAE,EAAEC,KAAK,EAAE;EACjD,MAAMV,aAAa,GAAG,6CAA+CH,OAAQ;EAE7E,MAAMc,MAAM,GAAGD,KAAK,KAAKd,UAAU,CAACgB,KAAK,GAAG,IAAIF,KAAK,EAAE,GAAG,EAAE;EAC5D,MAAM;IAAET,OAAO,EAAEY;EAAW,CAAC,GAAG,MAAMb,aAAa,CACjD,GAAGL,MAAM,CAACQ,GAAG,CAAC,YAAY,CAAC,UAAUM,EAAE,cAAcE,MAAM,EAC7D,CAAC;EAED,OAAOE,UAAU;AACnB;;AAEA;AACA;AACA","ignoreList":[]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { StatusCodes } from 'http-status-codes';
|
|
2
|
+
import { getFormDefinition, getFormMetadata } from "./formsService.js";
|
|
3
|
+
import { FormStatus } from "../../../routes/types.js";
|
|
4
|
+
import { getJson } from "../../../services/httpService.js";
|
|
5
|
+
import * as fixtures from "../../../../../test/fixtures/index.js";
|
|
6
|
+
const {
|
|
7
|
+
MANAGER_URL
|
|
8
|
+
} = process.env;
|
|
9
|
+
jest.mock("../../../services/httpService");
|
|
10
|
+
describe('Forms service', () => {
|
|
11
|
+
const {
|
|
12
|
+
definition,
|
|
13
|
+
metadata
|
|
14
|
+
} = fixtures.form;
|
|
15
|
+
describe('getFormMetadata', () => {
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
jest.mocked(getJson).mockResolvedValue({
|
|
18
|
+
res: (/** @type {IncomingMessage} */{
|
|
19
|
+
statusCode: StatusCodes.OK
|
|
20
|
+
}),
|
|
21
|
+
payload: metadata
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
it('requests JSON via form slug', async () => {
|
|
25
|
+
await getFormMetadata(metadata.slug);
|
|
26
|
+
expect(getJson).toHaveBeenCalledWith(`${MANAGER_URL}/forms/slug/${metadata.slug}`);
|
|
27
|
+
});
|
|
28
|
+
it('coerces timestamps from string to Date', async () => {
|
|
29
|
+
const payload = {
|
|
30
|
+
...structuredClone(metadata),
|
|
31
|
+
// JSON payload uses string dates in transit
|
|
32
|
+
createdAt: metadata.createdAt.toISOString(),
|
|
33
|
+
updatedAt: metadata.updatedAt.toISOString()
|
|
34
|
+
};
|
|
35
|
+
jest.mocked(getJson).mockResolvedValue({
|
|
36
|
+
res: (/** @type {IncomingMessage} */{
|
|
37
|
+
statusCode: StatusCodes.OK
|
|
38
|
+
}),
|
|
39
|
+
payload
|
|
40
|
+
});
|
|
41
|
+
await expect(getFormMetadata(metadata.slug)).resolves.toEqual({
|
|
42
|
+
...metadata,
|
|
43
|
+
createdAt: expect.any(Date),
|
|
44
|
+
updatedAt: expect.any(Date)
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe('getFormDefinition', () => {
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
jest.mocked(getJson).mockResolvedValue({
|
|
51
|
+
res: (/** @type {IncomingMessage} */{
|
|
52
|
+
statusCode: StatusCodes.OK
|
|
53
|
+
}),
|
|
54
|
+
payload: definition
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
it('requests JSON via form ID (draft)', async () => {
|
|
58
|
+
await getFormDefinition(metadata.id, FormStatus.Draft);
|
|
59
|
+
expect(getJson).toHaveBeenCalledWith(`${MANAGER_URL}/forms/${metadata.id}/definition/draft`);
|
|
60
|
+
});
|
|
61
|
+
it('requests JSON via form ID (live)', async () => {
|
|
62
|
+
await getFormDefinition(metadata.id, FormStatus.Live);
|
|
63
|
+
expect(getJson).toHaveBeenCalledWith(`${MANAGER_URL}/forms/${metadata.id}/definition`);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @import { IncomingMessage } from 'node:http'
|
|
70
|
+
*/
|
|
71
|
+
//# sourceMappingURL=formsService.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formsService.test.js","names":["StatusCodes","getFormDefinition","getFormMetadata","FormStatus","getJson","fixtures","MANAGER_URL","process","env","jest","mock","describe","definition","metadata","form","beforeEach","mocked","mockResolvedValue","res","statusCode","OK","payload","it","slug","expect","toHaveBeenCalledWith","structuredClone","createdAt","toISOString","updatedAt","resolves","toEqual","any","Date","id","Draft","Live"],"sources":["../../../../../src/server/plugins/engine/services/formsService.test.js"],"sourcesContent":["import { StatusCodes } from 'http-status-codes'\n\nimport {\n getFormDefinition,\n getFormMetadata\n} from '~/src/server/plugins/engine/services/formsService.js'\nimport { FormStatus } from '~/src/server/routes/types.js'\nimport { getJson } from '~/src/server/services/httpService.js'\nimport * as fixtures from '~/test/fixtures/index.js'\n\nconst { MANAGER_URL } = process.env\n\njest.mock('~/src/server/services/httpService')\n\ndescribe('Forms service', () => {\n const { definition, metadata } = fixtures.form\n\n describe('getFormMetadata', () => {\n beforeEach(() => {\n jest.mocked(getJson).mockResolvedValue({\n res: /** @type {IncomingMessage} */ ({\n statusCode: StatusCodes.OK\n }),\n payload: metadata\n })\n })\n\n it('requests JSON via form slug', async () => {\n await getFormMetadata(metadata.slug)\n\n expect(getJson).toHaveBeenCalledWith(\n `${MANAGER_URL}/forms/slug/${metadata.slug}`\n )\n })\n\n it('coerces timestamps from string to Date', async () => {\n const payload = {\n ...structuredClone(metadata),\n\n // JSON payload uses string dates in transit\n createdAt: metadata.createdAt.toISOString(),\n updatedAt: metadata.updatedAt.toISOString()\n }\n\n jest.mocked(getJson).mockResolvedValue({\n res: /** @type {IncomingMessage} */ ({\n statusCode: StatusCodes.OK\n }),\n payload\n })\n\n await expect(getFormMetadata(metadata.slug)).resolves.toEqual({\n ...metadata,\n createdAt: expect.any(Date),\n updatedAt: expect.any(Date)\n })\n })\n })\n\n describe('getFormDefinition', () => {\n beforeEach(() => {\n jest.mocked(getJson).mockResolvedValue({\n res: /** @type {IncomingMessage} */ ({\n statusCode: StatusCodes.OK\n }),\n payload: definition\n })\n })\n\n it('requests JSON via form ID (draft)', async () => {\n await getFormDefinition(metadata.id, FormStatus.Draft)\n\n expect(getJson).toHaveBeenCalledWith(\n `${MANAGER_URL}/forms/${metadata.id}/definition/draft`\n )\n })\n\n it('requests JSON via form ID (live)', async () => {\n await getFormDefinition(metadata.id, FormStatus.Live)\n\n expect(getJson).toHaveBeenCalledWith(\n `${MANAGER_URL}/forms/${metadata.id}/definition`\n )\n })\n })\n})\n\n/**\n * @import { IncomingMessage } from 'node:http'\n */\n"],"mappings":"AAAA,SAASA,WAAW,QAAQ,mBAAmB;AAE/C,SACEC,iBAAiB,EACjBC,eAAe;AAEjB,SAASC,UAAU;AACnB,SAASC,OAAO;AAChB,OAAO,KAAKC,QAAQ;AAEpB,MAAM;EAAEC;AAAY,CAAC,GAAGC,OAAO,CAACC,GAAG;AAEnCC,IAAI,CAACC,IAAI,gCAAoC,CAAC;AAE9CC,QAAQ,CAAC,eAAe,EAAE,MAAM;EAC9B,MAAM;IAAEC,UAAU;IAAEC;EAAS,CAAC,GAAGR,QAAQ,CAACS,IAAI;EAE9CH,QAAQ,CAAC,iBAAiB,EAAE,MAAM;IAChCI,UAAU,CAAC,MAAM;MACfN,IAAI,CAACO,MAAM,CAACZ,OAAO,CAAC,CAACa,iBAAiB,CAAC;QACrCC,GAAG,GAAE,8BAAgC;UACnCC,UAAU,EAAEnB,WAAW,CAACoB;QAC1B,CAAC,CAAC;QACFC,OAAO,EAAER;MACX,CAAC,CAAC;IACJ,CAAC,CAAC;IAEFS,EAAE,CAAC,6BAA6B,EAAE,YAAY;MAC5C,MAAMpB,eAAe,CAACW,QAAQ,CAACU,IAAI,CAAC;MAEpCC,MAAM,CAACpB,OAAO,CAAC,CAACqB,oBAAoB,CAClC,GAAGnB,WAAW,eAAeO,QAAQ,CAACU,IAAI,EAC5C,CAAC;IACH,CAAC,CAAC;IAEFD,EAAE,CAAC,wCAAwC,EAAE,YAAY;MACvD,MAAMD,OAAO,GAAG;QACd,GAAGK,eAAe,CAACb,QAAQ,CAAC;QAE5B;QACAc,SAAS,EAAEd,QAAQ,CAACc,SAAS,CAACC,WAAW,CAAC,CAAC;QAC3CC,SAAS,EAAEhB,QAAQ,CAACgB,SAAS,CAACD,WAAW,CAAC;MAC5C,CAAC;MAEDnB,IAAI,CAACO,MAAM,CAACZ,OAAO,CAAC,CAACa,iBAAiB,CAAC;QACrCC,GAAG,GAAE,8BAAgC;UACnCC,UAAU,EAAEnB,WAAW,CAACoB;QAC1B,CAAC,CAAC;QACFC;MACF,CAAC,CAAC;MAEF,MAAMG,MAAM,CAACtB,eAAe,CAACW,QAAQ,CAACU,IAAI,CAAC,CAAC,CAACO,QAAQ,CAACC,OAAO,CAAC;QAC5D,GAAGlB,QAAQ;QACXc,SAAS,EAAEH,MAAM,CAACQ,GAAG,CAACC,IAAI,CAAC;QAC3BJ,SAAS,EAAEL,MAAM,CAACQ,GAAG,CAACC,IAAI;MAC5B,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ,CAAC,CAAC;EAEFtB,QAAQ,CAAC,mBAAmB,EAAE,MAAM;IAClCI,UAAU,CAAC,MAAM;MACfN,IAAI,CAACO,MAAM,CAACZ,OAAO,CAAC,CAACa,iBAAiB,CAAC;QACrCC,GAAG,GAAE,8BAAgC;UACnCC,UAAU,EAAEnB,WAAW,CAACoB;QAC1B,CAAC,CAAC;QACFC,OAAO,EAAET;MACX,CAAC,CAAC;IACJ,CAAC,CAAC;IAEFU,EAAE,CAAC,mCAAmC,EAAE,YAAY;MAClD,MAAMrB,iBAAiB,CAACY,QAAQ,CAACqB,EAAE,EAAE/B,UAAU,CAACgC,KAAK,CAAC;MAEtDX,MAAM,CAACpB,OAAO,CAAC,CAACqB,oBAAoB,CAClC,GAAGnB,WAAW,UAAUO,QAAQ,CAACqB,EAAE,mBACrC,CAAC;IACH,CAAC,CAAC;IAEFZ,EAAE,CAAC,kCAAkC,EAAE,YAAY;MACjD,MAAMrB,iBAAiB,CAACY,QAAQ,CAACqB,EAAE,EAAE/B,UAAU,CAACiC,IAAI,CAAC;MAErDZ,MAAM,CAACpB,OAAO,CAAC,CAACqB,oBAAoB,CAClC,GAAGnB,WAAW,UAAUO,QAAQ,CAACqB,EAAE,aACrC,CAAC;IACH,CAAC,CAAC;EACJ,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACA;AACA","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["formsService","formSubmissionService","outputService"],"sources":["../../../../../src/server/plugins/engine/services/index.js"],"sourcesContent":["export * as formsService from '~/src/server/plugins/engine/services/formsService.js'\nexport * as formSubmissionService from '~/src/server/plugins/engine/services/formSubmissionService.js'\nexport * as outputService from '~/src/server/plugins/engine/services/notifyService.js'\n"],"mappings":"AAAA,OAAO,KAAKA,YAAY;AACxB,OAAO,KAAKC,qBAAqB;AACjC,OAAO,KAAKC,aAAa","ignoreList":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { config } from "../../../../config/index.js";
|
|
2
|
+
import { escapeMarkdown } from "../components/helpers.js";
|
|
3
|
+
import { checkFormStatus } from "../helpers.js";
|
|
4
|
+
import { getFormatter } from "../outputFormatters/index.js";
|
|
5
|
+
import { sendNotification } from "../../../utils/notify.js";
|
|
6
|
+
const templateId = config.get('notifyTemplateId');
|
|
7
|
+
export async function submit(request, model, emailAddress, items, submitResponse) {
|
|
8
|
+
const logTags = ['submit', 'email'];
|
|
9
|
+
const {
|
|
10
|
+
path
|
|
11
|
+
} = request;
|
|
12
|
+
const formStatus = checkFormStatus(path);
|
|
13
|
+
|
|
14
|
+
// Get submission email personalisation
|
|
15
|
+
request.logger.info(logTags, 'Getting personalisation data');
|
|
16
|
+
const formName = escapeMarkdown(model.name);
|
|
17
|
+
const subject = formStatus.isPreview ? `TEST FORM SUBMISSION: ${formName}` : `Form submission: ${formName}`;
|
|
18
|
+
const outputAudience = model.def.output?.audience ?? 'human';
|
|
19
|
+
const outputVersion = model.def.output?.version ?? '1';
|
|
20
|
+
const outputFormatter = getFormatter(outputAudience, outputVersion);
|
|
21
|
+
let body = outputFormatter(items, model, submitResponse, formStatus);
|
|
22
|
+
|
|
23
|
+
// GOV.UK Notify transforms quotes into curly quotes, so we can't just send the raw payload
|
|
24
|
+
// This is logic specific to Notify, so we include the logic here rather than in the formatter
|
|
25
|
+
if (outputAudience === 'machine') {
|
|
26
|
+
body = Buffer.from(body).toString('base64');
|
|
27
|
+
}
|
|
28
|
+
request.logger.info(logTags, 'Sending email');
|
|
29
|
+
try {
|
|
30
|
+
// Send submission email
|
|
31
|
+
await sendNotification({
|
|
32
|
+
templateId,
|
|
33
|
+
emailAddress,
|
|
34
|
+
personalisation: {
|
|
35
|
+
subject,
|
|
36
|
+
body
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
request.logger.info(logTags, 'Email sent successfully');
|
|
40
|
+
} catch (err) {
|
|
41
|
+
request.logger.error(logTags, 'Error sending email', err);
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=notifyService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifyService.js","names":["config","escapeMarkdown","checkFormStatus","getFormatter","sendNotification","templateId","get","submit","request","model","emailAddress","items","submitResponse","logTags","path","formStatus","logger","info","formName","name","subject","isPreview","outputAudience","def","output","audience","outputVersion","version","outputFormatter","body","Buffer","from","toString","personalisation","err","error"],"sources":["../../../../../src/server/plugins/engine/services/notifyService.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { escapeMarkdown } from '~/src/server/plugins/engine/components/helpers.js'\nimport { checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { type DetailItem } from '~/src/server/plugins/engine/models/types.js'\nimport { getFormatter } from '~/src/server/plugins/engine/outputFormatters/index.js'\nimport { type FormRequestPayload } from '~/src/server/routes/types.js'\nimport { sendNotification } from '~/src/server/utils/notify.js'\n\nconst templateId = config.get('notifyTemplateId')\n\nexport async function submit(\n request: FormRequestPayload,\n model: FormModel,\n emailAddress: string,\n items: DetailItem[],\n submitResponse: SubmitResponsePayload\n) {\n const logTags = ['submit', 'email']\n const { path } = request\n const formStatus = checkFormStatus(path)\n\n // Get submission email personalisation\n request.logger.info(logTags, 'Getting personalisation data')\n\n const formName = escapeMarkdown(model.name)\n const subject = formStatus.isPreview\n ? `TEST FORM SUBMISSION: ${formName}`\n : `Form submission: ${formName}`\n\n const outputAudience = model.def.output?.audience ?? 'human'\n const outputVersion = model.def.output?.version ?? '1'\n\n const outputFormatter = getFormatter(outputAudience, outputVersion)\n let body = outputFormatter(items, model, submitResponse, formStatus)\n\n // GOV.UK Notify transforms quotes into curly quotes, so we can't just send the raw payload\n // This is logic specific to Notify, so we include the logic here rather than in the formatter\n if (outputAudience === 'machine') {\n body = Buffer.from(body).toString('base64')\n }\n\n request.logger.info(logTags, 'Sending email')\n\n try {\n // Send submission email\n await sendNotification({\n templateId,\n emailAddress,\n personalisation: {\n subject,\n body\n }\n })\n\n request.logger.info(logTags, 'Email sent successfully')\n } catch (err) {\n request.logger.error(logTags, 'Error sending email', err)\n\n throw err\n }\n}\n"],"mappings":"AAEA,SAASA,MAAM;AACf,SAASC,cAAc;AACvB,SAASC,eAAe;AAGxB,SAASC,YAAY;AAErB,SAASC,gBAAgB;AAEzB,MAAMC,UAAU,GAAGL,MAAM,CAACM,GAAG,CAAC,kBAAkB,CAAC;AAEjD,OAAO,eAAeC,MAAMA,CAC1BC,OAA2B,EAC3BC,KAAgB,EAChBC,YAAoB,EACpBC,KAAmB,EACnBC,cAAqC,EACrC;EACA,MAAMC,OAAO,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC;EACnC,MAAM;IAAEC;EAAK,CAAC,GAAGN,OAAO;EACxB,MAAMO,UAAU,GAAGb,eAAe,CAACY,IAAI,CAAC;;EAExC;EACAN,OAAO,CAACQ,MAAM,CAACC,IAAI,CAACJ,OAAO,EAAE,8BAA8B,CAAC;EAE5D,MAAMK,QAAQ,GAAGjB,cAAc,CAACQ,KAAK,CAACU,IAAI,CAAC;EAC3C,MAAMC,OAAO,GAAGL,UAAU,CAACM,SAAS,GAChC,yBAAyBH,QAAQ,EAAE,GACnC,oBAAoBA,QAAQ,EAAE;EAElC,MAAMI,cAAc,GAAGb,KAAK,CAACc,GAAG,CAACC,MAAM,EAAEC,QAAQ,IAAI,OAAO;EAC5D,MAAMC,aAAa,GAAGjB,KAAK,CAACc,GAAG,CAACC,MAAM,EAAEG,OAAO,IAAI,GAAG;EAEtD,MAAMC,eAAe,GAAGzB,YAAY,CAACmB,cAAc,EAAEI,aAAa,CAAC;EACnE,IAAIG,IAAI,GAAGD,eAAe,CAACjB,KAAK,EAAEF,KAAK,EAAEG,cAAc,EAAEG,UAAU,CAAC;;EAEpE;EACA;EACA,IAAIO,cAAc,KAAK,SAAS,EAAE;IAChCO,IAAI,GAAGC,MAAM,CAACC,IAAI,CAACF,IAAI,CAAC,CAACG,QAAQ,CAAC,QAAQ,CAAC;EAC7C;EAEAxB,OAAO,CAACQ,MAAM,CAACC,IAAI,CAACJ,OAAO,EAAE,eAAe,CAAC;EAE7C,IAAI;IACF;IACA,MAAMT,gBAAgB,CAAC;MACrBC,UAAU;MACVK,YAAY;MACZuB,eAAe,EAAE;QACfb,OAAO;QACPS;MACF;IACF,CAAC,CAAC;IAEFrB,OAAO,CAACQ,MAAM,CAACC,IAAI,CAACJ,OAAO,EAAE,yBAAyB,CAAC;EACzD,CAAC,CAAC,OAAOqB,GAAG,EAAE;IACZ1B,OAAO,CAACQ,MAAM,CAACmB,KAAK,CAACtB,OAAO,EAAE,qBAAqB,EAAEqB,GAAG,CAAC;IAEzD,MAAMA,GAAG;EACX;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { config } from "../../../../config/index.js";
|
|
2
|
+
import { getJson, postJson } from "../../../services/httpService.js";
|
|
3
|
+
const uploaderUrl = config.get('uploaderUrl');
|
|
4
|
+
const submissionUrl = config.get('submissionUrl');
|
|
5
|
+
const uploaderBucketName = config.get('uploaderBucketName');
|
|
6
|
+
const stagingPrefix = config.get('stagingPrefix');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Initiates a CDP file upload
|
|
10
|
+
* @param {string} path - the path of the page in the form
|
|
11
|
+
* @param {string} retrievalKey - the retrieval key for the files
|
|
12
|
+
* @param {string} [mimeTypes] - the csv string of accepted mimeTypes
|
|
13
|
+
*/
|
|
14
|
+
export async function initiateUpload(path, retrievalKey, mimeTypes) {
|
|
15
|
+
const postJsonByType = /** @type {typeof postJson<UploadInitiateResponse>} */postJson;
|
|
16
|
+
const payload = {
|
|
17
|
+
redirect: path,
|
|
18
|
+
callback: `${submissionUrl}/file`,
|
|
19
|
+
s3Bucket: uploaderBucketName,
|
|
20
|
+
s3Path: stagingPrefix,
|
|
21
|
+
metadata: {
|
|
22
|
+
retrievalKey
|
|
23
|
+
},
|
|
24
|
+
mimeTypes: mimeTypes?.split(',').map(type => type.trim()).filter(type => type !== '')
|
|
25
|
+
// maxFileSize: 25 * 1000 * 1000
|
|
26
|
+
};
|
|
27
|
+
const {
|
|
28
|
+
payload: initiate
|
|
29
|
+
} = await postJsonByType(`${uploaderUrl}/initiate`, {
|
|
30
|
+
payload
|
|
31
|
+
});
|
|
32
|
+
return initiate;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get the status of a CDP file upload
|
|
37
|
+
* @param {string} uploadId - the ID of the upload
|
|
38
|
+
*/
|
|
39
|
+
export async function getUploadStatus(uploadId) {
|
|
40
|
+
const getJsonByType = /** @type {typeof getJson<UploadStatusResponse>} */
|
|
41
|
+
getJson;
|
|
42
|
+
const {
|
|
43
|
+
payload: status
|
|
44
|
+
} = await getJsonByType(`${uploaderUrl}/status/${uploadId}`);
|
|
45
|
+
return status;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @import { UploadInitiateResponse, UploadStatusResponse } from '~/src/server/plugins/engine/types.js'
|
|
50
|
+
*/
|
|
51
|
+
//# sourceMappingURL=uploadService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploadService.js","names":["config","getJson","postJson","uploaderUrl","get","submissionUrl","uploaderBucketName","stagingPrefix","initiateUpload","path","retrievalKey","mimeTypes","postJsonByType","payload","redirect","callback","s3Bucket","s3Path","metadata","split","map","type","trim","filter","initiate","getUploadStatus","uploadId","getJsonByType","status"],"sources":["../../../../../src/server/plugins/engine/services/uploadService.js"],"sourcesContent":["import { config } from '~/src/config/index.js'\nimport { getJson, postJson } from '~/src/server/services/httpService.js'\n\nconst uploaderUrl = config.get('uploaderUrl')\nconst submissionUrl = config.get('submissionUrl')\nconst uploaderBucketName = config.get('uploaderBucketName')\nconst stagingPrefix = config.get('stagingPrefix')\n\n/**\n * Initiates a CDP file upload\n * @param {string} path - the path of the page in the form\n * @param {string} retrievalKey - the retrieval key for the files\n * @param {string} [mimeTypes] - the csv string of accepted mimeTypes\n */\nexport async function initiateUpload(path, retrievalKey, mimeTypes) {\n const postJsonByType =\n /** @type {typeof postJson<UploadInitiateResponse>} */ (postJson)\n\n const payload = {\n redirect: path,\n callback: `${submissionUrl}/file`,\n s3Bucket: uploaderBucketName,\n s3Path: stagingPrefix,\n metadata: {\n retrievalKey\n },\n mimeTypes: mimeTypes\n ?.split(',')\n .map((type) => type.trim())\n .filter((type) => type !== '')\n // maxFileSize: 25 * 1000 * 1000\n }\n\n const { payload: initiate } = await postJsonByType(\n `${uploaderUrl}/initiate`,\n { payload }\n )\n\n return initiate\n}\n\n/**\n * Get the status of a CDP file upload\n * @param {string} uploadId - the ID of the upload\n */\nexport async function getUploadStatus(uploadId) {\n const getJsonByType = /** @type {typeof getJson<UploadStatusResponse>} */ (\n getJson\n )\n\n const { payload: status } = await getJsonByType(\n `${uploaderUrl}/status/${uploadId}`\n )\n\n return status\n}\n\n/**\n * @import { UploadInitiateResponse, UploadStatusResponse } from '~/src/server/plugins/engine/types.js'\n */\n"],"mappings":"AAAA,SAASA,MAAM;AACf,SAASC,OAAO,EAAEC,QAAQ;AAE1B,MAAMC,WAAW,GAAGH,MAAM,CAACI,GAAG,CAAC,aAAa,CAAC;AAC7C,MAAMC,aAAa,GAAGL,MAAM,CAACI,GAAG,CAAC,eAAe,CAAC;AACjD,MAAME,kBAAkB,GAAGN,MAAM,CAACI,GAAG,CAAC,oBAAoB,CAAC;AAC3D,MAAMG,aAAa,GAAGP,MAAM,CAACI,GAAG,CAAC,eAAe,CAAC;;AAEjD;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeI,cAAcA,CAACC,IAAI,EAAEC,YAAY,EAAEC,SAAS,EAAE;EAClE,MAAMC,cAAc,GAClB,sDAAwDV,QAAS;EAEnE,MAAMW,OAAO,GAAG;IACdC,QAAQ,EAAEL,IAAI;IACdM,QAAQ,EAAE,GAAGV,aAAa,OAAO;IACjCW,QAAQ,EAAEV,kBAAkB;IAC5BW,MAAM,EAAEV,aAAa;IACrBW,QAAQ,EAAE;MACRR;IACF,CAAC;IACDC,SAAS,EAAEA,SAAS,EAChBQ,KAAK,CAAC,GAAG,CAAC,CACXC,GAAG,CAAEC,IAAI,IAAKA,IAAI,CAACC,IAAI,CAAC,CAAC,CAAC,CAC1BC,MAAM,CAAEF,IAAI,IAAKA,IAAI,KAAK,EAAE;IAC/B;EACF,CAAC;EAED,MAAM;IAAER,OAAO,EAAEW;EAAS,CAAC,GAAG,MAAMZ,cAAc,CAChD,GAAGT,WAAW,WAAW,EACzB;IAAEU;EAAQ,CACZ,CAAC;EAED,OAAOW,QAAQ;AACjB;;AAEA;AACA;AACA;AACA;AACA,OAAO,eAAeC,eAAeA,CAACC,QAAQ,EAAE;EAC9C,MAAMC,aAAa,GAAG;EACpB1B,OACD;EAED,MAAM;IAAEY,OAAO,EAAEe;EAAO,CAAC,GAAG,MAAMD,aAAa,CAC7C,GAAGxB,WAAW,WAAWuB,QAAQ,EACnC,CAAC;EAED,OAAOE,MAAM;AACf;;AAEA;AACA;AACA","ignoreList":[]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form submission state stores the following in Redis:
|
|
3
|
+
* Props containing user's submitted values as `{ [inputId]: value }` or as `{ [sectionName]: { [inputName]: value } }`
|
|
4
|
+
* a) . e.g:
|
|
5
|
+
* ```ts
|
|
6
|
+
* {
|
|
7
|
+
* _C9PRHmsgt: 'Ben',
|
|
8
|
+
* WfLk9McjzX: 'Music',
|
|
9
|
+
* IK7jkUFCBL: 'Royal Academy of Music'
|
|
10
|
+
* }
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* b)
|
|
14
|
+
* ```ts
|
|
15
|
+
* {
|
|
16
|
+
* checkBeforeYouStart: { ukPassport: true },
|
|
17
|
+
* applicantDetails: {
|
|
18
|
+
* numberOfApplicants: 1,
|
|
19
|
+
* phoneNumber: '77777777',
|
|
20
|
+
* emailAddress: 'aaa@aaa.com'
|
|
21
|
+
* },
|
|
22
|
+
* applicantOneDetails: {
|
|
23
|
+
* firstName: 'a',
|
|
24
|
+
* middleName: 'a',
|
|
25
|
+
* lastName: 'a',
|
|
26
|
+
* address: { addressLine1: 'a', addressLine2: 'a', town: 'a', postcode: 'a' }
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Form submission state
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Form POST for question pages
|
|
38
|
+
* (after Joi has converted value types)
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
export let UploadStatus = /*#__PURE__*/function (UploadStatus) {
|
|
42
|
+
UploadStatus["initiated"] = "initiated";
|
|
43
|
+
UploadStatus["pending"] = "pending";
|
|
44
|
+
UploadStatus["ready"] = "ready";
|
|
45
|
+
return UploadStatus;
|
|
46
|
+
}({});
|
|
47
|
+
export let FileStatus = /*#__PURE__*/function (FileStatus) {
|
|
48
|
+
FileStatus["complete"] = "complete";
|
|
49
|
+
FileStatus["rejected"] = "rejected";
|
|
50
|
+
FileStatus["pending"] = "pending";
|
|
51
|
+
return FileStatus;
|
|
52
|
+
}({});
|
|
53
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","names":["UploadStatus","FileStatus"],"sources":["../../../../src/server/plugins/engine/types.ts"],"sourcesContent":["import {\n type ComponentDef,\n type Item,\n type List,\n type Page\n} from '@defra/forms-model'\nimport { type ValidationErrorItem } from 'joi'\n\nimport { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type Component } from '~/src/server/plugins/engine/components/helpers.js'\nimport {\n type BackLink,\n type ComponentText,\n type ComponentViewModel\n} from '~/src/server/plugins/engine/components/types.js'\nimport { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport { type PageControllerClass } from '~/src/server/plugins/engine/pageControllers/helpers.js'\nimport { type ViewContext } from '~/src/server/plugins/nunjucks/types.js'\nimport { type FormAction, type FormRequest } from '~/src/server/routes/types.js'\n\n/**\n * Form submission state stores the following in Redis:\n * Props containing user's submitted values as `{ [inputId]: value }` or as `{ [sectionName]: { [inputName]: value } }`\n * a) . e.g:\n * ```ts\n * {\n * _C9PRHmsgt: 'Ben',\n * WfLk9McjzX: 'Music',\n * IK7jkUFCBL: 'Royal Academy of Music'\n * }\n * ```\n *\n * b)\n * ```ts\n * {\n * checkBeforeYouStart: { ukPassport: true },\n * applicantDetails: {\n * numberOfApplicants: 1,\n * phoneNumber: '77777777',\n * emailAddress: 'aaa@aaa.com'\n * },\n * applicantOneDetails: {\n * firstName: 'a',\n * middleName: 'a',\n * lastName: 'a',\n * address: { addressLine1: 'a', addressLine2: 'a', town: 'a', postcode: 'a' }\n * }\n * }\n * ```\n */\n\n/**\n * Form submission state\n */\nexport type FormSubmissionState = {\n upload?: Record<string, TempFileState>\n} & FormState\n\nexport interface FormSubmissionError\n extends Pick<ValidationErrorItem, 'context' | 'path'> {\n href: string // e.g: '#dateField__day'\n name: string // e.g: 'dateField__day'\n text: string // e.g: 'Date field must be a real date'\n}\n\nexport interface FormParams {\n action?: FormAction\n confirm?: true\n crumb?: string\n itemId?: string\n}\n\n/**\n * Form POST for question pages\n * (after Joi has converted value types)\n */\nexport type FormPayload = FormParams & Partial<Record<string, FormValue>>\n\nexport type FormValue =\n | Item['value']\n | Item['value'][]\n | UploadState\n | RepeatListState\n | undefined\n\nexport type FormState = Partial<Record<string, FormStateValue>>\nexport type FormStateValue = Exclude<FormValue, undefined> | null\n\nexport interface FormValidationResult<\n ValueType extends FormPayload | FormSubmissionState\n> {\n value: ValueType\n errors: FormSubmissionError[] | undefined\n}\n\nexport interface FormContext {\n /**\n * Evaluation form state only (filtered by visited paths),\n * with values formatted for condition evaluation using\n * {@link FormComponent.getContextValueFromState}\n */\n evaluationState: FormState\n\n /**\n * Relevant form state only (filtered by visited paths)\n */\n relevantState: FormState\n\n /**\n * Relevant pages only (filtered by visited paths)\n */\n relevantPages: PageControllerClass[]\n\n /**\n * Form submission payload (single page)\n */\n payload: FormPayload\n\n /**\n * Form submission state (entire form)\n */\n state: FormSubmissionState\n\n /**\n * Validation errors (entire form)\n */\n errors?: FormSubmissionError[]\n\n /**\n * Visited paths evaluated from form state\n */\n paths: string[]\n\n /**\n * Preview URL direct access is allowed\n */\n isForceAccess: boolean\n\n /**\n * Miscellaneous extra data from event responses\n */\n data: object\n\n pageDefMap: Map<string, Page>\n listDefMap: Map<string, List>\n componentDefMap: Map<string, ComponentDef>\n pageMap: Map<string, PageControllerClass>\n componentMap: Map<string, Component>\n}\n\nexport type FormContextRequest = (\n | {\n method: 'get'\n payload?: undefined\n }\n | {\n method: 'post'\n payload: FormPayload\n }\n | {\n method: FormRequest['method']\n payload?: object | undefined\n }\n) &\n Pick<FormRequest, 'app' | 'method' | 'params' | 'path' | 'query' | 'url'>\n\nexport interface UploadInitiateResponse {\n uploadId: string\n uploadUrl: string\n statusUrl: string\n}\n\nexport enum UploadStatus {\n initiated = 'initiated',\n pending = 'pending',\n ready = 'ready'\n}\n\nexport enum FileStatus {\n complete = 'complete',\n rejected = 'rejected',\n pending = 'pending'\n}\n\nexport type UploadState = FileState[]\n\nexport type FileUpload = {\n fileId: string\n filename: string\n contentLength: number\n} & (\n | {\n fileStatus: FileStatus.complete | FileStatus.rejected | FileStatus.pending\n errorMessage?: string\n }\n | {\n fileStatus: FileStatus.complete\n errorMessage?: undefined\n }\n)\n\nexport interface FileUploadMetadata {\n retrievalKey: string\n}\n\nexport type UploadStatusResponse =\n | {\n uploadStatus: UploadStatus.initiated\n metadata: FileUploadMetadata\n form: { file?: undefined }\n }\n | {\n uploadStatus: UploadStatus.pending | UploadStatus.ready\n metadata: FileUploadMetadata\n form: { file: FileUpload }\n numberOfRejectedFiles?: number\n }\n | {\n uploadStatus: UploadStatus.ready\n metadata: FileUploadMetadata\n form: { file: FileUpload }\n numberOfRejectedFiles: 0\n }\n\nexport type UploadStatusFileResponse = Exclude<\n UploadStatusResponse,\n { uploadStatus: UploadStatus.initiated }\n>\n\nexport interface FileState {\n uploadId: string\n status: UploadStatusFileResponse\n}\n\nexport interface TempFileState {\n upload?: UploadInitiateResponse\n files: UploadState\n}\n\nexport interface RepeatItemState extends FormPayload {\n itemId: string\n}\n\nexport type RepeatListState = RepeatItemState[]\n\nexport interface CheckAnswers {\n title?: ComponentText\n summaryList: SummaryList\n}\n\nexport interface SummaryList {\n classes?: string\n rows: SummaryListRow[]\n}\n\nexport interface SummaryListRow {\n key: ComponentText\n value: ComponentText\n actions?: { items: SummaryListAction[] }\n}\n\nexport type SummaryListAction = ComponentText & {\n href: string\n visuallyHiddenText: string\n}\n\nexport interface PageViewModelBase extends Partial<ViewContext> {\n page: PageController\n name?: string\n pageTitle: string\n sectionTitle?: string\n showTitle: boolean\n isStartPage: boolean\n backLink?: BackLink\n feedbackLink?: string\n serviceUrl: string\n phaseTag?: string\n}\n\nexport interface ItemDeletePageViewModel extends PageViewModelBase {\n context: FormContext\n itemTitle: string\n confirmation?: ComponentText\n buttonConfirm: ComponentText\n buttonCancel: ComponentText\n}\n\nexport interface FormPageViewModel extends PageViewModelBase {\n components: ComponentViewModel[]\n context: FormContext\n errors?: FormSubmissionError[]\n hasMissingNotificationEmail?: boolean\n}\n\nexport interface RepeaterSummaryPageViewModel extends PageViewModelBase {\n context: FormContext\n errors?: FormSubmissionError[]\n checkAnswers: CheckAnswers[]\n repeatTitle: string\n}\n\nexport interface FeaturedFormPageViewModel extends FormPageViewModel {\n formAction?: string\n formComponent: ComponentViewModel\n componentsBefore: ComponentViewModel[]\n uploadId: string | undefined\n proxyUrl: string | null\n}\n\nexport type PageViewModel =\n | PageViewModelBase\n | ItemDeletePageViewModel\n | FormPageViewModel\n | RepeaterSummaryPageViewModel\n | FeaturedFormPageViewModel\n"],"mappings":"AAoBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAmBA;AACA;AACA;AACA;;AAiGA,WAAYA,YAAY,0BAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAA,OAAZA,YAAY;AAAA;AAMxB,WAAYC,UAAU,0BAAVA,UAAU;EAAVA,UAAU;EAAVA,UAAU;EAAVA,UAAU;EAAA,OAAVA,UAAU;AAAA","ignoreList":[]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{% if params.errorMessage %}
|
|
2
|
+
<div class="govuk-form-group govuk-form-group--error govuk-!-margin-bottom-0">
|
|
3
|
+
<div class="govuk-!-margin-bottom-3">{{ params.name }}</div>
|
|
4
|
+
<p class="govuk-error-message">{{ params.errorMessage }}</p>
|
|
5
|
+
</div>
|
|
6
|
+
{% else %}
|
|
7
|
+
{{ params.name }}
|
|
8
|
+
{% endif %}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{% from "govuk/components/summary-list/macro.njk" import govukSummaryList -%}
|
|
2
|
+
|
|
3
|
+
{% macro FileUploadField(component) %}
|
|
4
|
+
{% set upload = component.model.upload %}
|
|
5
|
+
|
|
6
|
+
<div id="uploadedFilesContainer">
|
|
7
|
+
<h2 class="govuk-heading-m">Uploaded files</h2>
|
|
8
|
+
{% if upload.count %}
|
|
9
|
+
<p class="govuk-body">{{upload.count}} file{{ "s" if upload.count > 1}} uploaded</p>
|
|
10
|
+
<p class="govuk-body">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<div class="govuk-visually-hidden" aria-live="polite" id="statusInformation">
|
|
14
|
+
{{upload.count}} file{{ "s" if upload.count > 1}} uploaded
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
{% if upload.summaryList.rows | length %}
|
|
18
|
+
{{ govukSummaryList(upload.summaryList) }}
|
|
19
|
+
{% endif %}
|
|
20
|
+
{% else %}
|
|
21
|
+
<p class="govuk-body">{{upload.count}} files uploaded</p>
|
|
22
|
+
{% endif %}
|
|
23
|
+
</div>
|
|
24
|
+
{% endmacro %}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{% macro List(component) %}
|
|
2
|
+
{% set params = component.model %}
|
|
3
|
+
|
|
4
|
+
<div class="govuk-form-group">
|
|
5
|
+
{% if params.content.title %}
|
|
6
|
+
<h2 class="govuk-heading-m govuk-!-margin-bottom-3">
|
|
7
|
+
{{ params.content.title }}
|
|
8
|
+
</h2>
|
|
9
|
+
{% endif %}
|
|
10
|
+
|
|
11
|
+
{% if params.content.text %}
|
|
12
|
+
<p class="govuk-body">
|
|
13
|
+
{{ params.content.text }}
|
|
14
|
+
</p>
|
|
15
|
+
{% endif %}
|
|
16
|
+
|
|
17
|
+
{% if params.type == 'numbered' %}
|
|
18
|
+
<ol class="govuk-list govuk-list--number {%- if params.classes %} {{ params.classes }}{% endif %}">
|
|
19
|
+
{% else %}
|
|
20
|
+
<ul class="govuk-list govuk-list--bullet {%- if params.classes %} {{ params.classes }}{% endif %}">
|
|
21
|
+
{% endif %}
|
|
22
|
+
{% for item in params.items %}
|
|
23
|
+
<li>
|
|
24
|
+
{{ item.text }}
|
|
25
|
+
{% if item.hint.text | length %}
|
|
26
|
+
<br><span class="govuk-hint govuk-!-display-inline-block">{{ item.hint.text }}</span>
|
|
27
|
+
{% endif %}
|
|
28
|
+
</li>
|
|
29
|
+
{% endfor %}
|
|
30
|
+
{% if params.type == 'numbered' %}
|
|
31
|
+
</ol>
|
|
32
|
+
{% else %}
|
|
33
|
+
</ul>
|
|
34
|
+
{% endif %}
|
|
35
|
+
</div>
|
|
36
|
+
{% endmacro %}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{% from "govuk/components/textarea/macro.njk" import govukTextarea %}
|
|
2
|
+
{% from "govuk/components/character-count/macro.njk" import govukCharacterCount %}
|
|
3
|
+
|
|
4
|
+
{% macro MultilineTextField(component) %}
|
|
5
|
+
{% if component.model.isCharacterOrWordCount == true %}
|
|
6
|
+
{{ govukCharacterCount(component.model) }}
|
|
7
|
+
{% else %}
|
|
8
|
+
{{ govukTextarea(component.model) }}
|
|
9
|
+
{% endif %}
|
|
10
|
+
{% endmacro %}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{% from "partials/components.html" import componentList %}
|
|
2
|
+
{% from "govuk/components/fieldset/macro.njk" import govukFieldset %}
|
|
3
|
+
{% from "govuk/components/hint/macro.njk" import govukHint %}
|
|
4
|
+
|
|
5
|
+
{% macro UkAddressField(component) %}
|
|
6
|
+
{% set fieldset = component.model.fieldset %}
|
|
7
|
+
{% set addressFieldHtml = componentList(component.model.components) %}
|
|
8
|
+
|
|
9
|
+
{% if component.model.hint %}
|
|
10
|
+
{% set addressHintHtml %}
|
|
11
|
+
{{ govukHint({
|
|
12
|
+
id: component.model.name + "-hint",
|
|
13
|
+
text: component.model.hint.text
|
|
14
|
+
} if fieldset else component.model.hint) }}
|
|
15
|
+
{% endset %}
|
|
16
|
+
|
|
17
|
+
{% set addressFieldHtml = addressHintHtml + addressFieldHtml %}
|
|
18
|
+
{% endif %}
|
|
19
|
+
|
|
20
|
+
{{ govukFieldset({
|
|
21
|
+
legend: fieldset.legend,
|
|
22
|
+
attributes: fieldset.attributes,
|
|
23
|
+
html: addressFieldHtml
|
|
24
|
+
}) if fieldset else addressFieldHtml }}
|
|
25
|
+
{% endmacro %}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{% extends "index.html" %}
|
|
2
|
+
|
|
3
|
+
{% from "govuk/components/button/macro.njk" import govukButton %}
|
|
4
|
+
{% from "govuk/components/file-upload/macro.njk" import govukFileUpload %}
|
|
5
|
+
{% from "govuk/components/warning-text/macro.njk" import govukWarningText %}
|
|
6
|
+
|
|
7
|
+
{% block form %}
|
|
8
|
+
{{ componentList(componentsBefore) }}
|
|
9
|
+
|
|
10
|
+
<div class="govuk-error-summary-container"></div>
|
|
11
|
+
|
|
12
|
+
<form method="post" {%- if formAction and not context.isForceAccess %} action="{{ formAction }}" enctype="multipart/form-data" data-upload-id="{{ uploadId }}" {% if proxyUrl %}data-proxy-url="{{ proxyUrl }}"{% endif %} {%- endif %} novalidate>
|
|
13
|
+
{{ govukFileUpload(formComponent.model) }}
|
|
14
|
+
|
|
15
|
+
{% if formAction %}
|
|
16
|
+
{{ govukButton({
|
|
17
|
+
text: "Upload file",
|
|
18
|
+
classes: "govuk-button--secondary upload-file-button",
|
|
19
|
+
preventDoubleClick: true
|
|
20
|
+
}) }}
|
|
21
|
+
{% else %}
|
|
22
|
+
{{ govukWarningText({
|
|
23
|
+
text: "You have reached the maximum number of files. Please remove a file to upload more.",
|
|
24
|
+
iconFallbackText: "Warning"
|
|
25
|
+
}) }}
|
|
26
|
+
{% endif %}
|
|
27
|
+
</form>
|
|
28
|
+
|
|
29
|
+
{{ super() }}
|
|
30
|
+
|
|
31
|
+
<div class="govuk-summary-list-container"></div>
|
|
32
|
+
|
|
33
|
+
{% endblock %}
|
|
34
|
+
|
|
35
|
+
{% block bodyEnd %}
|
|
36
|
+
{{ super() }}
|
|
37
|
+
<script type="module" nonce="{{ cspNonce }}">
|
|
38
|
+
import { initFileUpload } from '{{ getAssetPath("file-upload.js") }}';
|
|
39
|
+
if (document.readyState === 'loading') {
|
|
40
|
+
document.addEventListener('DOMContentLoaded', initFileUpload);
|
|
41
|
+
} else {
|
|
42
|
+
initFileUpload();
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
{% endblock %}
|