@defra/forms-engine-plugin 0.1.10 → 0.1.12
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/file-upload.min.js +1 -1
- package/.public/javascripts/file-upload.min.js.map +1 -1
- package/.public/stylesheets/application.min.css +1 -1
- package/.public/stylesheets/application.min.css.map +1 -1
- package/.server/client/javascripts/file-upload.js +45 -4
- package/.server/client/javascripts/file-upload.js.map +1 -1
- package/.server/client/stylesheets/application.scss +10 -0
- package/.server/config/index.js +3 -14
- package/.server/config/index.js.map +1 -1
- package/.server/server/constants.js +2 -0
- package/.server/server/constants.js.map +1 -1
- package/.server/server/devserver/dxt-devtool-baselayout.html +71 -0
- package/.server/server/forms/register-as-a-unicorn-breeder.json +393 -0
- package/.server/server/forms/register-as-a-unicorn-breeder.yaml +251 -0
- package/.server/server/index.js +12 -17
- package/.server/server/index.js.map +1 -1
- package/.server/server/plugins/engine/components/AutocompleteField.js +2 -0
- package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
- package/.server/server/plugins/engine/components/CheckboxesField.js +3 -4
- package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
- package/.server/server/plugins/engine/components/ComponentCollection.js +37 -16
- package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
- package/.server/server/plugins/engine/components/DatePartsField.js +36 -2
- package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
- package/.server/server/plugins/engine/components/EmailAddressField.js +19 -3
- package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
- package/.server/server/plugins/engine/components/FileUploadField.js +44 -4
- package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
- package/.server/server/plugins/engine/components/FormComponent.js +14 -2
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/ListFormComponent.js +16 -3
- package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/Markdown.js +24 -0
- package/.server/server/plugins/engine/components/Markdown.js.map +1 -0
- package/.server/server/plugins/engine/components/MonthYearField.js +30 -2
- package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
- package/.server/server/plugins/engine/components/MultilineTextField.js +32 -3
- package/.server/server/plugins/engine/components/MultilineTextField.js.map +1 -1
- package/.server/server/plugins/engine/components/NumberField.js +28 -3
- package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
- package/.server/server/plugins/engine/components/SelectionControlField.js +14 -0
- package/.server/server/plugins/engine/components/SelectionControlField.js.map +1 -1
- package/.server/server/plugins/engine/components/TelephoneNumberField.js +19 -3
- package/.server/server/plugins/engine/components/TelephoneNumberField.js.map +1 -1
- package/.server/server/plugins/engine/components/TextField.js +22 -3
- package/.server/server/plugins/engine/components/TextField.js.map +1 -1
- package/.server/server/plugins/engine/components/UkAddressField.js +29 -0
- package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
- package/.server/server/plugins/engine/components/YesNoField.js +18 -0
- package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers.js +16 -0
- package/.server/server/plugins/engine/components/helpers.js.map +1 -1
- package/.server/server/plugins/engine/components/index.js +1 -0
- package/.server/server/plugins/engine/components/index.js.map +1 -1
- package/.server/server/plugins/engine/configureEnginePlugin.js +19 -3
- package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
- package/.server/server/plugins/engine/helpers.js +38 -18
- package/.server/server/plugins/engine/helpers.js.map +1 -1
- package/.server/server/plugins/engine/models/FormModel.js +60 -2
- package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
- package/.server/server/plugins/engine/models/SummaryViewModel.js +3 -2
- package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js +1 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/PageController.js +13 -5
- package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +2 -2
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +19 -5
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.js +6 -11
- package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
- package/.server/server/plugins/engine/plugin.js +32 -20
- package/.server/server/plugins/engine/plugin.js.map +1 -1
- package/.server/server/plugins/engine/services/formsService.js +15 -29
- package/.server/server/plugins/engine/services/formsService.js.map +1 -1
- package/.server/server/plugins/engine/services/localFormsService.js +52 -0
- package/.server/server/plugins/engine/services/localFormsService.js.map +1 -0
- package/.server/server/plugins/engine/services/notifyService.js +1 -4
- package/.server/server/plugins/engine/services/notifyService.js.map +1 -1
- package/.server/server/plugins/engine/services/uploadService.js +5 -3
- package/.server/server/plugins/engine/services/uploadService.js.map +1 -1
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/plugins/engine/views/components/html.html +1 -1
- package/.server/server/plugins/engine/views/components/markdown.html +5 -0
- package/.server/server/plugins/engine/views/confirmation.html +1 -1
- package/.server/server/plugins/engine/views/file-upload.html +1 -1
- package/.server/server/plugins/engine/views/index.html +1 -1
- package/.server/server/plugins/engine/views/item-delete.html +1 -1
- package/.server/server/plugins/engine/views/repeat-list-summary.html +1 -1
- package/.server/server/plugins/engine/views/summary.html +8 -2
- package/.server/server/plugins/errorPages.js +4 -26
- package/.server/server/plugins/errorPages.js.map +1 -1
- package/.server/server/plugins/nunjucks/context.js +43 -33
- package/.server/server/plugins/nunjucks/context.js.map +1 -1
- package/.server/server/plugins/nunjucks/context.test.js +23 -28
- package/.server/server/plugins/nunjucks/context.test.js.map +1 -1
- package/.server/server/plugins/nunjucks/enviroment.test.js +6 -3
- package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
- package/.server/server/plugins/nunjucks/types.js +3 -4
- package/.server/server/plugins/nunjucks/types.js.map +1 -1
- package/.server/server/routes/index.js +0 -1
- package/.server/server/routes/index.js.map +1 -1
- package/.server/server/utils/type-utils.js +8 -0
- package/.server/server/utils/type-utils.js.map +1 -0
- package/.server/typings/hapi/index.d.js.map +1 -1
- package/.server/typings/joi/index.d.js.map +1 -1
- package/package.json +4 -3
- package/src/client/javascripts/file-upload.js +60 -4
- package/src/client/stylesheets/application.scss +10 -0
- package/src/config/index.ts +4 -17
- package/src/server/constants.js +2 -0
- package/src/server/devserver/dxt-devtool-baselayout.html +71 -0
- package/src/server/forms/register-as-a-unicorn-breeder.json +393 -0
- package/src/server/forms/register-as-a-unicorn-breeder.yaml +251 -0
- package/src/server/index.test.ts +38 -66
- package/src/server/index.ts +15 -17
- package/src/server/plugins/engine/components/AutocompleteField.test.ts +71 -3
- package/src/server/plugins/engine/components/AutocompleteField.ts +6 -2
- package/src/server/plugins/engine/components/CheckboxesField.test.ts +40 -8
- package/src/server/plugins/engine/components/CheckboxesField.ts +7 -3
- package/src/server/plugins/engine/components/ComponentCollection.ts +45 -18
- package/src/server/plugins/engine/components/DatePartsField.test.ts +13 -4
- package/src/server/plugins/engine/components/DatePartsField.ts +29 -8
- package/src/server/plugins/engine/components/EmailAddressField.test.ts +51 -1
- package/src/server/plugins/engine/components/EmailAddressField.ts +17 -2
- package/src/server/plugins/engine/components/FileUploadField.test.ts +53 -0
- package/src/server/plugins/engine/components/FileUploadField.ts +52 -3
- package/src/server/plugins/engine/components/FormComponent.ts +24 -2
- package/src/server/plugins/engine/components/ListFormComponent.ts +16 -2
- package/src/server/plugins/engine/components/Markdown.test.ts +48 -0
- package/src/server/plugins/engine/components/Markdown.ts +29 -0
- package/src/server/plugins/engine/components/MonthYearField.test.ts +35 -0
- package/src/server/plugins/engine/components/MonthYearField.ts +34 -9
- package/src/server/plugins/engine/components/MultilineTextField.test.ts +83 -5
- package/src/server/plugins/engine/components/MultilineTextField.ts +37 -2
- package/src/server/plugins/engine/components/NumberField.test.ts +24 -2
- package/src/server/plugins/engine/components/NumberField.ts +23 -3
- package/src/server/plugins/engine/components/RadiosField.test.ts +10 -1
- package/src/server/plugins/engine/components/SelectField.test.ts +2 -1
- package/src/server/plugins/engine/components/SelectionControlField.ts +14 -0
- package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +30 -2
- package/src/server/plugins/engine/components/TelephoneNumberField.ts +17 -2
- package/src/server/plugins/engine/components/TextField.test.ts +33 -1
- package/src/server/plugins/engine/components/TextField.ts +17 -2
- package/src/server/plugins/engine/components/UkAddressField.test.ts +46 -3
- package/src/server/plugins/engine/components/UkAddressField.ts +28 -0
- package/src/server/plugins/engine/components/YesNoField.test.ts +9 -1
- package/src/server/plugins/engine/components/YesNoField.ts +24 -0
- package/src/server/plugins/engine/components/helpers.test.ts +24 -0
- package/src/server/plugins/engine/components/helpers.ts +39 -0
- package/src/server/plugins/engine/components/index.ts +1 -0
- package/src/server/plugins/engine/configureEnginePlugin.ts +32 -4
- package/src/server/plugins/engine/helpers.test.ts +71 -20
- package/src/server/plugins/engine/helpers.ts +46 -19
- package/src/server/plugins/engine/models/FormModel.test.ts +91 -1
- package/src/server/plugins/engine/models/FormModel.ts +86 -3
- package/src/server/plugins/engine/models/SummaryViewModel.test.ts +46 -7
- package/src/server/plugins/engine/models/SummaryViewModel.ts +7 -3
- package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +1 -2
- package/src/server/plugins/engine/outputFormatters/human/v1.ts +1 -1
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +1 -0
- package/src/server/plugins/engine/pageControllers/PageController.test.ts +9 -6
- package/src/server/plugins/engine/pageControllers/PageController.ts +15 -5
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +2 -2
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +21 -6
- package/src/server/plugins/engine/pageControllers/validationOptions.ts +31 -17
- package/src/server/plugins/engine/plugin.ts +52 -22
- package/src/server/plugins/engine/services/formsService.js +17 -35
- package/src/server/plugins/engine/services/localFormsService.js +49 -0
- package/src/server/plugins/engine/services/notifyService.ts +1 -2
- package/src/server/plugins/engine/services/uploadService.js +10 -6
- package/src/server/plugins/engine/types.ts +10 -1
- package/src/server/plugins/engine/views/components/html.html +1 -1
- package/src/server/plugins/engine/views/components/markdown.html +5 -0
- package/src/server/plugins/engine/views/confirmation.html +1 -1
- package/src/server/plugins/engine/views/file-upload.html +1 -1
- package/src/server/plugins/engine/views/index.html +1 -1
- package/src/server/plugins/engine/views/item-delete.html +1 -1
- package/src/server/plugins/engine/views/repeat-list-summary.html +1 -1
- package/src/server/plugins/engine/views/summary.html +8 -2
- package/src/server/plugins/errorPages.ts +4 -26
- package/src/server/plugins/nunjucks/context.js +44 -34
- package/src/server/plugins/nunjucks/context.test.js +24 -27
- package/src/server/plugins/nunjucks/enviroment.test.js +9 -3
- package/src/server/plugins/nunjucks/types.js +3 -4
- package/src/server/routes/index.ts +0 -1
- package/src/server/utils/type-utils.ts +15 -0
- package/src/typings/hapi/index.d.ts +3 -9
- package/src/typings/joi/index.d.ts +8 -0
- package/.server/common/cookies.js +0 -55
- package/.server/common/cookies.js.map +0 -1
- package/.server/common/cookies.test.js +0 -15
- package/.server/common/cookies.test.js.map +0 -1
- package/.server/common/types.js +0 -6
- package/.server/common/types.js.map +0 -1
- package/.server/server/forms/README.md +0 -10
- package/.server/server/forms/report-a-terrorist.json +0 -270
- package/.server/server/forms/runner-components-test.json +0 -365
- package/.server/server/forms/test.json +0 -581
- package/.server/server/forms/test.yaml +0 -363
- package/.server/server/plugins/blankie.js +0 -29
- package/.server/server/plugins/blankie.js.map +0 -1
- package/.server/server/plugins/engine/services/formsService.test.js +0 -71
- package/.server/server/plugins/engine/services/formsService.test.js.map +0 -1
- package/.server/server/plugins/engine/views/layout.html +0 -199
- package/.server/server/plugins/router.js +0 -169
- package/.server/server/plugins/router.js.map +0 -1
- package/.server/server/routes/health.js +0 -15
- package/.server/server/routes/health.js.map +0 -1
- package/.server/server/routes/health.test.js +0 -32
- package/.server/server/routes/health.test.js.map +0 -1
- package/.server/server/utils/file-form-service.test.js +0 -52
- package/.server/server/utils/file-form-service.test.js.map +0 -1
- package/.server/server/views/404.html +0 -16
- package/.server/server/views/500.html +0 -19
- package/.server/server/views/help/accessibility-statement.html +0 -58
- package/.server/server/views/help/cookie-preferences.html +0 -57
- package/.server/server/views/help/cookies.html +0 -71
- package/.server/server/views/help/get-support.html +0 -37
- package/.server/server/views/help/privacy-notice.html +0 -68
- package/.server/server/views/help/terms-and-conditions.html +0 -83
- package/src/common/cookies.js +0 -58
- package/src/common/cookies.test.js +0 -23
- package/src/common/types.js +0 -5
- package/src/server/forms/README.md +0 -10
- package/src/server/forms/report-a-terrorist.json +0 -270
- package/src/server/forms/runner-components-test.json +0 -365
- package/src/server/forms/test.json +0 -581
- package/src/server/forms/test.yaml +0 -363
- package/src/server/plugins/blankie.test.ts +0 -73
- package/src/server/plugins/blankie.ts +0 -48
- package/src/server/plugins/engine/services/formsService.test.js +0 -90
- package/src/server/plugins/engine/views/layout.html +0 -199
- package/src/server/plugins/router.ts +0 -201
- package/src/server/routes/health.js +0 -13
- package/src/server/routes/health.test.js +0 -35
- package/src/server/routes/index.test.ts +0 -125
- package/src/server/utils/file-form-service.test.js +0 -79
- package/src/server/views/404.html +0 -16
- package/src/server/views/500.html +0 -19
- package/src/server/views/help/accessibility-statement.html +0 -58
- package/src/server/views/help/cookie-preferences.html +0 -57
- package/src/server/views/help/cookies.html +0 -71
- package/src/server/views/help/get-support.html +0 -37
- package/src/server/views/help/privacy-notice.html +0 -68
- package/src/server/views/help/terms-and-conditions.html +0 -83
|
@@ -42,7 +42,7 @@ export function format(
|
|
|
42
42
|
lines.push(`This is a test of the ${formName} ${formStatus.state} form.\n`)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
lines.push(
|
|
45
|
+
lines.push(`${formName} form received at ${escapeMarkdown(formattedNow)}.\n`)
|
|
46
46
|
lines.push('---\n')
|
|
47
47
|
|
|
48
48
|
items.forEach((item) => {
|
|
@@ -210,6 +210,7 @@ describe('FileUploadPageController', () => {
|
|
|
210
210
|
expect(getUploadStatusSpy).toHaveBeenCalledTimes(2)
|
|
211
211
|
expect(request.logger.info).toHaveBeenCalled()
|
|
212
212
|
|
|
213
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */
|
|
213
214
|
const logMsg = (request.logger.info as jest.Mock).mock.calls[0][0]
|
|
214
215
|
expect(logMsg).toEqual(expect.stringContaining('Waiting'))
|
|
215
216
|
expect(logMsg).toEqual(expect.stringContaining('some-id'))
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ResponseToolkit } from '@hapi/hapi'
|
|
2
2
|
|
|
3
|
+
import { FORM_PREFIX } from '~/src/server/constants.js'
|
|
3
4
|
import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
|
|
4
5
|
import { PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'
|
|
5
6
|
import { type FormRequest } from '~/src/server/routes/types.js'
|
|
@@ -10,6 +11,8 @@ describe('PageController', () => {
|
|
|
10
11
|
let controller1: PageController
|
|
11
12
|
let controller2: PageController
|
|
12
13
|
|
|
14
|
+
const testBasePath = `${FORM_PREFIX}/test`
|
|
15
|
+
|
|
13
16
|
beforeEach(() => {
|
|
14
17
|
const { pages } = definition
|
|
15
18
|
|
|
@@ -17,7 +20,7 @@ describe('PageController', () => {
|
|
|
17
20
|
const page2 = pages[1]
|
|
18
21
|
|
|
19
22
|
model = new FormModel(definition, {
|
|
20
|
-
basePath:
|
|
23
|
+
basePath: testBasePath
|
|
21
24
|
})
|
|
22
25
|
|
|
23
26
|
controller1 = new PageController(model, page1)
|
|
@@ -31,8 +34,8 @@ describe('PageController', () => {
|
|
|
31
34
|
})
|
|
32
35
|
|
|
33
36
|
it('returns href', () => {
|
|
34
|
-
expect(controller1).toHaveProperty('href',
|
|
35
|
-
expect(controller2).toHaveProperty('href',
|
|
37
|
+
expect(controller1).toHaveProperty('href', `${testBasePath}/licence`)
|
|
38
|
+
expect(controller2).toHaveProperty('href', `${testBasePath}/full-name`)
|
|
36
39
|
})
|
|
37
40
|
|
|
38
41
|
it('returns keys (empty)', () => {
|
|
@@ -99,11 +102,11 @@ describe('PageController', () => {
|
|
|
99
102
|
describe('Path methods', () => {
|
|
100
103
|
describe('Link href', () => {
|
|
101
104
|
it('prefixes paths into link hrefs', () => {
|
|
102
|
-
const href1 = controller1.getHref('
|
|
105
|
+
const href1 = controller1.getHref('')
|
|
103
106
|
const href2 = controller1.getHref('/page-one')
|
|
104
107
|
|
|
105
|
-
expect(href1).toBe(
|
|
106
|
-
expect(href2).toBe(
|
|
108
|
+
expect(href1).toBe(testBasePath)
|
|
109
|
+
expect(href2).toBe(`${testBasePath}/page-one`)
|
|
107
110
|
})
|
|
108
111
|
})
|
|
109
112
|
|
|
@@ -135,12 +135,22 @@ export class PageController {
|
|
|
135
135
|
return def.phaseBanner?.phase
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
getHref(path: string) {
|
|
139
|
-
const
|
|
138
|
+
getHref(path: string): string {
|
|
139
|
+
const basePath = this.model.basePath
|
|
140
140
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
if (path === '/') {
|
|
142
|
+
return `/${basePath}`
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// if ever the path is not prefixed with a slash, add it
|
|
146
|
+
const relativeTargetPath = path.startsWith('/') ? path.substring(1) : path
|
|
147
|
+
let finalPath = `/${basePath}`
|
|
148
|
+
if (relativeTargetPath) {
|
|
149
|
+
finalPath += `/${relativeTargetPath}`
|
|
150
|
+
}
|
|
151
|
+
finalPath = finalPath.replace(/\/{2,}/g, '/')
|
|
152
|
+
|
|
153
|
+
return finalPath
|
|
144
154
|
}
|
|
145
155
|
|
|
146
156
|
getStartPath() {
|
|
@@ -398,7 +398,7 @@ export class QuestionPageController extends PageController {
|
|
|
398
398
|
const { evaluationState } = context
|
|
399
399
|
|
|
400
400
|
const viewModel = this.getViewModel(request, context)
|
|
401
|
-
viewModel.errors = collection.
|
|
401
|
+
viewModel.errors = collection.getViewErrors(viewModel.errors)
|
|
402
402
|
|
|
403
403
|
/**
|
|
404
404
|
* Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it
|
|
@@ -498,7 +498,7 @@ export class QuestionPageController extends PageController {
|
|
|
498
498
|
*/
|
|
499
499
|
if (context.errors || isForceAccess) {
|
|
500
500
|
const viewModel = this.getViewModel(request, context)
|
|
501
|
-
viewModel.errors = collection.
|
|
501
|
+
viewModel.errors = collection.getViewErrors(viewModel.errors)
|
|
502
502
|
|
|
503
503
|
// Filter our components based on their conditions using our evaluated state
|
|
504
504
|
viewModel.components = this.filterConditionalComponents(
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
hasComponentsEvenIfNoNext,
|
|
3
|
+
type Page,
|
|
4
|
+
type SubmitPayload
|
|
5
|
+
} from '@defra/forms-model'
|
|
2
6
|
import Boom from '@hapi/boom'
|
|
3
7
|
import { type ResponseToolkit, type RouteOptions } from '@hapi/hapi'
|
|
4
8
|
|
|
9
|
+
import { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'
|
|
5
10
|
import { FileUploadField } from '~/src/server/plugins/engine/components/FileUploadField.js'
|
|
6
11
|
import { getAnswer } from '~/src/server/plugins/engine/components/helpers.js'
|
|
7
12
|
import {
|
|
@@ -30,15 +35,21 @@ import {
|
|
|
30
35
|
} from '~/src/server/routes/types.js'
|
|
31
36
|
|
|
32
37
|
export class SummaryPageController extends QuestionPageController {
|
|
33
|
-
declare pageDef:
|
|
38
|
+
declare pageDef: Page
|
|
34
39
|
|
|
35
40
|
/**
|
|
36
41
|
* The controller which is used when Page["controller"] is defined as "./pages/summary.js"
|
|
37
42
|
*/
|
|
38
43
|
|
|
39
|
-
constructor(model: FormModel, pageDef:
|
|
44
|
+
constructor(model: FormModel, pageDef: Page) {
|
|
40
45
|
super(model, pageDef)
|
|
41
46
|
this.viewName = 'summary'
|
|
47
|
+
|
|
48
|
+
// Components collection
|
|
49
|
+
this.collection = new ComponentCollection(
|
|
50
|
+
hasComponentsEvenIfNoNext(pageDef) ? pageDef.components : [],
|
|
51
|
+
{ model, page: this }
|
|
52
|
+
)
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
getSummaryViewModel(
|
|
@@ -47,11 +58,16 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
47
58
|
): SummaryViewModel {
|
|
48
59
|
const viewModel = new SummaryViewModel(request, this, context)
|
|
49
60
|
|
|
61
|
+
const { query } = request
|
|
62
|
+
const { payload, errors } = context
|
|
63
|
+
const components = this.collection.getViewModel(payload, errors, query)
|
|
64
|
+
|
|
50
65
|
// We already figure these out in the base page controller. Take them and apply them to our page-specific model.
|
|
51
66
|
// This is a stop-gap until we can add proper inheritance in place.
|
|
52
67
|
viewModel.backLink = this.getBackLink(request, context)
|
|
53
68
|
viewModel.feedbackLink = this.feedbackLink
|
|
54
69
|
viewModel.phaseTag = this.phaseTag
|
|
70
|
+
viewModel.components = components
|
|
55
71
|
|
|
56
72
|
return viewModel
|
|
57
73
|
}
|
|
@@ -96,7 +112,7 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
96
112
|
|
|
97
113
|
// Get the form metadata using the `slug` param
|
|
98
114
|
const { notificationEmail } = await getFormMetadata(params.slug)
|
|
99
|
-
const { isPreview } = checkFormStatus(request.
|
|
115
|
+
const { isPreview } = checkFormStatus(request.params)
|
|
100
116
|
const emailAddress = notificationEmail ?? this.model.def.outputEmail
|
|
101
117
|
|
|
102
118
|
checkEmailAddressForLiveFormSubmission(emailAddress, isPreview)
|
|
@@ -138,8 +154,7 @@ async function submitForm(
|
|
|
138
154
|
) {
|
|
139
155
|
await extendFileRetention(model, state, emailAddress)
|
|
140
156
|
|
|
141
|
-
const
|
|
142
|
-
const formStatus = checkFormStatus(path)
|
|
157
|
+
const formStatus = checkFormStatus(request.params)
|
|
143
158
|
const logTags = ['submit', 'submissionApi']
|
|
144
159
|
|
|
145
160
|
request.logger.info(logTags, 'Preparing email', formStatus)
|
|
@@ -1,32 +1,45 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
2
|
// Declaration above is needed for: https://github.com/hapijs/joi/issues/3064
|
|
3
3
|
|
|
4
|
-
import joi, {
|
|
4
|
+
import joi, {
|
|
5
|
+
type JoiExpression,
|
|
6
|
+
type LanguageMessages,
|
|
7
|
+
type LanguageMessagesExt,
|
|
8
|
+
type ReferenceOptions,
|
|
9
|
+
type ValidationOptions
|
|
10
|
+
} from 'joi'
|
|
5
11
|
import lowerFirst from 'lodash/lowerFirst.js'
|
|
6
12
|
|
|
7
13
|
const opts = {
|
|
8
14
|
functions: {
|
|
9
15
|
lowerFirst
|
|
10
16
|
}
|
|
11
|
-
}
|
|
17
|
+
} as ReferenceOptions
|
|
12
18
|
|
|
13
19
|
/**
|
|
14
20
|
* see @link https://joi.dev/api/?v=17.4.2#template-syntax for template syntax
|
|
15
21
|
*/
|
|
16
|
-
export const messageTemplate = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
export const messageTemplate: Record<string, JoiExpression> = {
|
|
23
|
+
required: joi.expression(
|
|
24
|
+
'Enter {{lowerFirst(#label)}}',
|
|
25
|
+
opts
|
|
26
|
+
) as JoiExpression,
|
|
27
|
+
selectRequired: joi.expression(
|
|
28
|
+
'Select {{lowerFirst(#label)}}',
|
|
29
|
+
opts
|
|
30
|
+
) as JoiExpression,
|
|
31
|
+
selectYesNoRequired: '{{#label}} - select yes or no',
|
|
21
32
|
max: '{{#label}} must be {{#limit}} characters or less',
|
|
22
33
|
min: '{{#label}} must be {{#limit}} characters or more',
|
|
23
|
-
|
|
24
|
-
pattern: joi.expression(
|
|
34
|
+
minMax: '{{#label}} must be between {{#min}} and {{#max}} characters',
|
|
35
|
+
pattern: joi.expression(
|
|
36
|
+
'Enter a valid {{lowerFirst(#label)}}',
|
|
37
|
+
opts
|
|
38
|
+
) as JoiExpression,
|
|
25
39
|
format: joi.expression(
|
|
26
40
|
'Enter {{lowerFirst(#label)}} in the correct format',
|
|
27
|
-
// @ts-expect-error - joi.expression options type issue
|
|
28
41
|
opts
|
|
29
|
-
),
|
|
42
|
+
) as JoiExpression,
|
|
30
43
|
number: '{{#label}} must be a number',
|
|
31
44
|
numberPrecision: '{{#label}} must have {{#limit}} or fewer decimal places',
|
|
32
45
|
numberInteger: '{{#label}} must be a whole number',
|
|
@@ -36,19 +49,17 @@ export const messageTemplate = {
|
|
|
36
49
|
|
|
37
50
|
// Nested fields use component title
|
|
38
51
|
|
|
39
|
-
|
|
40
|
-
objectRequired: joi.expression('Enter {{#label}}', opts),
|
|
52
|
+
objectRequired: joi.expression('Enter {{#label}}', opts) as JoiExpression,
|
|
41
53
|
objectMissing: joi.expression(
|
|
42
54
|
'{{#title}} must include a {{lowerFirst(#label)}}',
|
|
43
|
-
// @ts-expect-error - joi.expression options type issue
|
|
44
55
|
opts
|
|
45
|
-
),
|
|
56
|
+
) as JoiExpression,
|
|
46
57
|
dateFormat: '{{#title}} must be a real date',
|
|
47
58
|
dateMin: '{{#title}} must be the same as or after {{#limit}}',
|
|
48
59
|
dateMax: '{{#title}} must be the same as or before {{#limit}}'
|
|
49
60
|
}
|
|
50
61
|
|
|
51
|
-
export const messages:
|
|
62
|
+
export const messages: LanguageMessagesExt = {
|
|
52
63
|
'string.base': messageTemplate.required,
|
|
53
64
|
'string.min': messageTemplate.min,
|
|
54
65
|
'string.empty': messageTemplate.required,
|
|
@@ -77,9 +88,12 @@ export const messages: LanguageMessages = {
|
|
|
77
88
|
'date.max': messageTemplate.dateMax
|
|
78
89
|
}
|
|
79
90
|
|
|
91
|
+
export const messagesPre: LanguageMessages =
|
|
92
|
+
messages as unknown as LanguageMessages
|
|
93
|
+
|
|
80
94
|
export const validationOptions: ValidationOptions = {
|
|
81
95
|
abortEarly: false,
|
|
82
|
-
messages,
|
|
96
|
+
messages: messagesPre,
|
|
83
97
|
errors: {
|
|
84
98
|
wrap: {
|
|
85
99
|
array: false,
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { existsSync } from 'fs'
|
|
2
|
+
import { dirname, join } from 'path'
|
|
3
|
+
import { fileURLToPath } from 'url'
|
|
4
|
+
|
|
1
5
|
import { hasFormComponents, slugSchema } from '@defra/forms-model'
|
|
2
6
|
import Boom from '@hapi/boom'
|
|
3
7
|
import {
|
|
@@ -11,6 +15,7 @@ import vision from '@hapi/vision'
|
|
|
11
15
|
import { isEqual } from 'date-fns'
|
|
12
16
|
import Joi from 'joi'
|
|
13
17
|
import nunjucks, { type Environment } from 'nunjucks'
|
|
18
|
+
import resolvePkg from 'resolve'
|
|
14
19
|
|
|
15
20
|
import { PREVIEW_PATH_PREFIX } from '~/src/server/constants.js'
|
|
16
21
|
import {
|
|
@@ -25,7 +30,6 @@ import {
|
|
|
25
30
|
redirectPath
|
|
26
31
|
} from '~/src/server/plugins/engine/helpers.js'
|
|
27
32
|
import {
|
|
28
|
-
PLUGIN_PATH,
|
|
29
33
|
VIEW_PATH,
|
|
30
34
|
context,
|
|
31
35
|
prepareNunjucksEnvironment
|
|
@@ -65,6 +69,20 @@ import * as httpService from '~/src/server/services/httpService.js'
|
|
|
65
69
|
import { CacheService } from '~/src/server/services/index.js'
|
|
66
70
|
import { type Services } from '~/src/server/types.js'
|
|
67
71
|
|
|
72
|
+
export function findPackageRoot() {
|
|
73
|
+
const currentFileName = fileURLToPath(import.meta.url)
|
|
74
|
+
const currentDirectoryName = dirname(currentFileName)
|
|
75
|
+
|
|
76
|
+
let dir = currentDirectoryName
|
|
77
|
+
while (dir !== '/') {
|
|
78
|
+
if (existsSync(join(dir, 'package.json'))) {
|
|
79
|
+
return dir
|
|
80
|
+
}
|
|
81
|
+
dir = dirname(dir)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
throw new Error('package.json not found in parent directories')
|
|
85
|
+
}
|
|
68
86
|
export interface PluginOptions {
|
|
69
87
|
model?: FormModel
|
|
70
88
|
services?: Services
|
|
@@ -73,6 +91,13 @@ export interface PluginOptions {
|
|
|
73
91
|
viewPaths?: string[]
|
|
74
92
|
filters?: Record<string, FilterFunction>
|
|
75
93
|
pluginPath?: string
|
|
94
|
+
nunjucks: {
|
|
95
|
+
baseLayoutPath: string
|
|
96
|
+
paths: string[]
|
|
97
|
+
}
|
|
98
|
+
viewContext: (
|
|
99
|
+
request: FormRequest | FormRequestPayload | null
|
|
100
|
+
) => Record<string, unknown>
|
|
76
101
|
}
|
|
77
102
|
|
|
78
103
|
export const plugin = {
|
|
@@ -80,28 +105,32 @@ export const plugin = {
|
|
|
80
105
|
dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'],
|
|
81
106
|
multiple: true,
|
|
82
107
|
async register(server: Server, options: PluginOptions) {
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- hapi types are wrong
|
|
109
|
+
const prefix = server.realm.modifiers.route.prefix ?? ''
|
|
83
110
|
const {
|
|
84
111
|
model,
|
|
85
112
|
services = defaultServices,
|
|
86
113
|
controllers,
|
|
87
114
|
cacheName,
|
|
88
|
-
viewPaths,
|
|
89
115
|
filters,
|
|
90
|
-
|
|
116
|
+
nunjucks: nunjucksOptions,
|
|
117
|
+
viewContext
|
|
91
118
|
} = options
|
|
92
119
|
const { formsService } = services
|
|
93
120
|
const cacheService = new CacheService(server, cacheName)
|
|
94
121
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
122
|
+
const packageRoot = findPackageRoot()
|
|
123
|
+
const govukFrontendPath = dirname(
|
|
124
|
+
resolvePkg.sync('govuk-frontend/package.json')
|
|
125
|
+
)
|
|
99
126
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
127
|
+
const viewPathResolved = join(packageRoot, VIEW_PATH)
|
|
128
|
+
|
|
129
|
+
const paths = [
|
|
130
|
+
...nunjucksOptions.paths,
|
|
131
|
+
viewPathResolved,
|
|
132
|
+
join(govukFrontendPath, 'dist')
|
|
133
|
+
]
|
|
105
134
|
|
|
106
135
|
await server.register({
|
|
107
136
|
plugin: vision,
|
|
@@ -127,10 +156,7 @@ export const plugin = {
|
|
|
127
156
|
) => {
|
|
128
157
|
// Nunjucks also needs an additional path configuration
|
|
129
158
|
// to use the templates and macros from `govuk-frontend`
|
|
130
|
-
const environment = nunjucks.configure(
|
|
131
|
-
...path,
|
|
132
|
-
'node_modules/govuk-frontend/dist'
|
|
133
|
-
])
|
|
159
|
+
const environment = nunjucks.configure(paths)
|
|
134
160
|
|
|
135
161
|
// Applies custom filters and globals for nunjucks
|
|
136
162
|
// that are required by the `forms-engine-plugin`
|
|
@@ -142,12 +168,14 @@ export const plugin = {
|
|
|
142
168
|
}
|
|
143
169
|
}
|
|
144
170
|
},
|
|
145
|
-
path,
|
|
171
|
+
path: paths,
|
|
146
172
|
// Provides global context used with all templates
|
|
147
173
|
context
|
|
148
174
|
}
|
|
149
175
|
})
|
|
150
176
|
|
|
177
|
+
server.expose('baseLayoutPath', nunjucksOptions.baseLayoutPath)
|
|
178
|
+
server.expose('viewContext', viewContext)
|
|
151
179
|
server.expose('cacheService', cacheService)
|
|
152
180
|
|
|
153
181
|
server.app.model = model
|
|
@@ -167,9 +195,9 @@ export const plugin = {
|
|
|
167
195
|
return h.continue
|
|
168
196
|
}
|
|
169
197
|
|
|
170
|
-
const { params
|
|
198
|
+
const { params } = request
|
|
171
199
|
const { slug } = params
|
|
172
|
-
const { isPreview, state: formState } = checkFormStatus(
|
|
200
|
+
const { isPreview, state: formState } = checkFormStatus(params)
|
|
173
201
|
|
|
174
202
|
// Get the form metadata using the `slug` param
|
|
175
203
|
const metadata = await formsService.getFormMetadata(slug)
|
|
@@ -215,9 +243,11 @@ export const plugin = {
|
|
|
215
243
|
)
|
|
216
244
|
|
|
217
245
|
// Set up the basePath for the model
|
|
218
|
-
const basePath =
|
|
219
|
-
|
|
220
|
-
|
|
246
|
+
const basePath = (
|
|
247
|
+
isPreview
|
|
248
|
+
? `${prefix}${PREVIEW_PATH_PREFIX}/${formState}/${slug}`
|
|
249
|
+
: `${prefix}/${slug}`
|
|
250
|
+
).substring(1)
|
|
221
251
|
|
|
222
252
|
// Construct the form model
|
|
223
253
|
const model = new FormModel(
|
|
@@ -1,46 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { FormStatus } from '~/src/server/routes/types.js'
|
|
5
|
-
import { getJson } from '~/src/server/services/httpService.js'
|
|
1
|
+
const error = Error(
|
|
2
|
+
'Not implemented. Consider setting up a form loader or providing a service implementation.'
|
|
3
|
+
)
|
|
6
4
|
|
|
5
|
+
// eslint-disable-next-line jsdoc/require-returns-check
|
|
7
6
|
/**
|
|
8
|
-
*
|
|
9
|
-
* @param {string}
|
|
7
|
+
* Dummy function to get form metadata.
|
|
8
|
+
* @param {string} _slug - the slug of the form
|
|
9
|
+
* @returns {Promise<FormMetadata>}
|
|
10
10
|
*/
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const { payload: metadata } = await getJsonByType(
|
|
15
|
-
`${config.get('managerUrl')}/forms/slug/${slug}`
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
// Run it through the schema to coerce dates
|
|
19
|
-
const result = formMetadataSchema.validate(metadata)
|
|
20
|
-
|
|
21
|
-
if (result.error) {
|
|
22
|
-
throw result.error
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return result.value
|
|
11
|
+
export function getFormMetadata(_slug) {
|
|
12
|
+
throw error
|
|
26
13
|
}
|
|
27
14
|
|
|
15
|
+
// eslint-disable-next-line jsdoc/require-returns-check
|
|
28
16
|
/**
|
|
29
|
-
*
|
|
30
|
-
* @param {string}
|
|
31
|
-
* @param {FormStatus}
|
|
17
|
+
* Dummy function to get form metadata.
|
|
18
|
+
* @param {string} _id - the id of the form
|
|
19
|
+
* @param {FormStatus} _state - the state of the form
|
|
20
|
+
* @returns {Promise<FormDefinition | undefined>}
|
|
32
21
|
*/
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const suffix = state === FormStatus.Draft ? `/${state}` : ''
|
|
37
|
-
const { payload: definition } = await getJsonByType(
|
|
38
|
-
`${config.get('managerUrl')}/forms/${id}/definition${suffix}`
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
return definition
|
|
22
|
+
export function getFormDefinition(_id, _state) {
|
|
23
|
+
throw error
|
|
42
24
|
}
|
|
43
25
|
|
|
44
26
|
/**
|
|
45
|
-
* @import { FormDefinition, FormMetadata } from '@defra/forms-model'
|
|
27
|
+
* @import { FormStatus, FormDefinition, FormMetadata } from '@defra/forms-model'
|
|
46
28
|
*/
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { config } from '~/src/config/index.js'
|
|
2
|
+
import { FileFormService } from '~/src/server/utils/file-form-service.js'
|
|
3
|
+
|
|
4
|
+
// Create shared form metadata
|
|
5
|
+
const now = new Date()
|
|
6
|
+
const user = { id: 'user', displayName: 'Username' }
|
|
7
|
+
const author = {
|
|
8
|
+
createdAt: now,
|
|
9
|
+
createdBy: user,
|
|
10
|
+
updatedAt: now,
|
|
11
|
+
updatedBy: user
|
|
12
|
+
}
|
|
13
|
+
const metadata = {
|
|
14
|
+
organisation: 'Defra',
|
|
15
|
+
teamName: 'Team name',
|
|
16
|
+
teamEmail: 'team@defra.gov.uk',
|
|
17
|
+
submissionGuidance: "Thanks for your submission, we'll be in touch",
|
|
18
|
+
notificationEmail: config.get('submissionEmailAddress'),
|
|
19
|
+
...author,
|
|
20
|
+
live: author
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Return an function rather than the service directly. This is to prevent consumer applications
|
|
25
|
+
* blowing up as they won't have these files on disk. We can defer the execution until when it's
|
|
26
|
+
* needed, i.e. the createServer function of the devtool.
|
|
27
|
+
*/
|
|
28
|
+
export const formsService = async () => {
|
|
29
|
+
// Instantiate the file loader form service
|
|
30
|
+
const loader = new FileFormService()
|
|
31
|
+
|
|
32
|
+
// Add a Json form
|
|
33
|
+
await loader.addForm('src/server/forms/register-as-a-unicorn-breeder.json', {
|
|
34
|
+
...metadata,
|
|
35
|
+
id: '95e92559-968d-44ae-8666-2b1ad3dffd31',
|
|
36
|
+
title: 'Register as a unicorn breeder',
|
|
37
|
+
slug: 'register-as-a-unicorn-breeder'
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
// Add a Yaml form
|
|
41
|
+
await loader.addForm('src/server/forms/register-as-a-unicorn-breeder.yaml', {
|
|
42
|
+
...metadata,
|
|
43
|
+
id: '641aeafd-13dd-40fa-9186-001703800efb',
|
|
44
|
+
title: 'Register as a unicorn breeder (yaml)',
|
|
45
|
+
slug: 'register-as-a-unicorn-breeder-yaml' // if we needed to validate any JSON logic, make it available for convenience
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
return loader.toFormsService()
|
|
49
|
+
}
|
|
@@ -19,8 +19,7 @@ export async function submit(
|
|
|
19
19
|
submitResponse: SubmitResponsePayload
|
|
20
20
|
) {
|
|
21
21
|
const logTags = ['submit', 'email']
|
|
22
|
-
const
|
|
23
|
-
const formStatus = checkFormStatus(path)
|
|
22
|
+
const formStatus = checkFormStatus(request.params)
|
|
24
23
|
|
|
25
24
|
// Get submission email personalisation
|
|
26
25
|
request.logger.info(logTags, 'Getting personalisation data')
|
|
@@ -10,12 +10,19 @@ const stagingPrefix = config.get('stagingPrefix')
|
|
|
10
10
|
* Initiates a CDP file upload
|
|
11
11
|
* @param {string} path - the path of the page in the form
|
|
12
12
|
* @param {string} retrievalKey - the retrieval key for the files
|
|
13
|
-
* @param {string} [
|
|
13
|
+
* @param {string} [mimeTypesCsv] - the csv string of accepted mimeTypes
|
|
14
14
|
*/
|
|
15
|
-
export async function initiateUpload(path, retrievalKey,
|
|
15
|
+
export async function initiateUpload(path, retrievalKey, mimeTypesCsv) {
|
|
16
16
|
const postJsonByType =
|
|
17
17
|
/** @type {typeof postJson<UploadInitiateResponse>} */ (postJson)
|
|
18
18
|
|
|
19
|
+
const mimeTypesList = mimeTypesCsv
|
|
20
|
+
?.split(',')
|
|
21
|
+
.map((type) => type.trim())
|
|
22
|
+
.filter((type) => type !== '')
|
|
23
|
+
|
|
24
|
+
const mimeTypes = mimeTypesList?.length ? mimeTypesList : undefined
|
|
25
|
+
|
|
19
26
|
const payload = {
|
|
20
27
|
redirect: path,
|
|
21
28
|
callback: `${submissionUrl}/file`,
|
|
@@ -24,10 +31,7 @@ export async function initiateUpload(path, retrievalKey, mimeTypes) {
|
|
|
24
31
|
metadata: {
|
|
25
32
|
retrievalKey
|
|
26
33
|
},
|
|
27
|
-
mimeTypes
|
|
28
|
-
?.split(',')
|
|
29
|
-
.map((type) => type.trim())
|
|
30
|
-
.filter((type) => type !== '')
|
|
34
|
+
mimeTypes
|
|
31
35
|
// maxFileSize: 25 * 1000 * 1000
|
|
32
36
|
}
|
|
33
37
|
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
type List,
|
|
5
5
|
type Page
|
|
6
6
|
} from '@defra/forms-model'
|
|
7
|
-
import { type ValidationErrorItem } from 'joi'
|
|
7
|
+
import { type JoiExpression, type ValidationErrorItem } from 'joi'
|
|
8
8
|
|
|
9
9
|
import { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'
|
|
10
10
|
import { type Component } from '~/src/server/plugins/engine/components/helpers.js'
|
|
@@ -316,3 +316,12 @@ export type PageViewModel =
|
|
|
316
316
|
| FeaturedFormPageViewModel
|
|
317
317
|
|
|
318
318
|
export type FilterFunction = (value: unknown) => unknown
|
|
319
|
+
export interface ErrorMessageTemplate {
|
|
320
|
+
type: string
|
|
321
|
+
template: JoiExpression
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export interface ErrorMessageTemplateList {
|
|
325
|
+
baseErrors: ErrorMessageTemplate[]
|
|
326
|
+
advancedSettingsErrors: ErrorMessageTemplate[]
|
|
327
|
+
}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
{% block bodyEnd %}
|
|
36
36
|
{{ super() }}
|
|
37
37
|
<script type="module" nonce="{{ cspNonce }}">
|
|
38
|
-
import { initFileUpload } from '{{
|
|
38
|
+
import { initFileUpload } from '{{ getDxtAssetPath("file-upload.js") }}';
|
|
39
39
|
if (document.readyState === 'loading') {
|
|
40
40
|
document.addEventListener('DOMContentLoaded', initFileUpload);
|
|
41
41
|
} else {
|