@planning-inspectorate/dynamic-forms 3.3.3 → 3.4.0
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/.azure/pipelines/azure-pipelines-pr.yml +4 -0
- package/.azure/pipelines/release.yml +4 -0
- package/.gitattributes +2 -0
- package/README.md +20 -9
- package/package.json +13 -5
- package/src/components/address/question.js +1 -10
- package/src/components/boolean/question.js +1 -1
- package/src/components/checkbox/question.js +2 -6
- package/src/components/date/question.js +1 -8
- package/src/components/date-period/question.js +1 -8
- package/src/components/email/question.js +4 -4
- package/src/components/manage-list/question.test.js +4 -19
- package/src/components/multi-field-input/question.js +3 -3
- package/src/components/multi-field-input/question.test.js +1 -1
- package/src/components/number-entry/question.js +1 -5
- package/src/components/radio/question.js +1 -1
- package/src/components/select/question.js +1 -1
- package/src/components/single-line-input/question.js +0 -8
- package/src/components/text-entry/question.js +4 -4
- package/src/components/text-entry-redact/index.njk +15 -11
- package/src/components/text-entry-redact/question.js +6 -16
- package/src/components/unit-option-entry/question.js +4 -11
- package/src/components/utils/component-types.js +18 -0
- package/src/index.js +72 -25
- package/src/middleware/redirect-to-unanswered-question.test.js +1 -1
- package/src/questions/options-question.js +5 -12
- package/src/questions/question-types.d.ts +3 -3
- package/src/questions/question.js +6 -6
- package/src/questions/questions.js +1 -1
- package/test/check-your-answers.test.js +3 -8
- package/test/conditional-journey.test.js +431 -0
- package/test/questions.test.js +15 -28
- package/test/snapshots/secret-wish.html +15 -11
- package/test/utils/question-test-utils.js +52 -4
- package/test/utils/test-server.js +1 -0
- package/test/utils/utils.js +16 -1
- package/tsconfig.json +9 -1
- package/types/commitlint.config.d.ts +7 -0
- package/types/commitlint.config.d.ts.map +1 -0
- package/types/eslint.config.d.ts +95 -0
- package/types/eslint.config.d.ts.map +1 -0
- package/types/src/components/address/question.d.ts +31 -0
- package/types/src/components/address/question.d.ts.map +1 -0
- package/types/src/components/address/question.test.d.ts +2 -0
- package/types/src/components/address/question.test.d.ts.map +1 -0
- package/types/src/components/boolean/question.d.ts +47 -0
- package/types/src/components/boolean/question.d.ts.map +1 -0
- package/types/src/components/boolean/question.test.d.ts +2 -0
- package/types/src/components/boolean/question.test.d.ts.map +1 -0
- package/types/src/components/checkbox/question.d.ts +49 -0
- package/types/src/components/checkbox/question.d.ts.map +1 -0
- package/types/src/components/checkbox/question.test.d.ts +2 -0
- package/types/src/components/checkbox/question.test.d.ts.map +1 -0
- package/types/src/components/date/question.d.ts +22 -0
- package/types/src/components/date/question.d.ts.map +1 -0
- package/types/src/components/date/question.test.d.ts +2 -0
- package/types/src/components/date/question.test.d.ts.map +1 -0
- package/types/src/components/date-period/question.d.ts +29 -0
- package/types/src/components/date-period/question.d.ts.map +1 -0
- package/types/src/components/date-period/question.test.d.ts +2 -0
- package/types/src/components/date-period/question.test.d.ts.map +1 -0
- package/types/src/components/date-time/question.d.ts +24 -0
- package/types/src/components/date-time/question.d.ts.map +1 -0
- package/types/src/components/date-time/question.test.d.ts +2 -0
- package/types/src/components/date-time/question.test.d.ts.map +1 -0
- package/types/src/components/email/question.d.ts +30 -0
- package/types/src/components/email/question.d.ts.map +1 -0
- package/types/src/components/email/question.test.d.ts +2 -0
- package/types/src/components/email/question.test.d.ts.map +1 -0
- package/types/src/components/identifier/question.d.ts +15 -0
- package/types/src/components/identifier/question.d.ts.map +1 -0
- package/types/src/components/identifier/question.test.d.ts +2 -0
- package/types/src/components/identifier/question.test.d.ts.map +1 -0
- package/types/src/components/manage-list/manage-list-section.d.ts +16 -0
- package/types/src/components/manage-list/manage-list-section.d.ts.map +1 -0
- package/types/src/components/manage-list/manage-list-section.test.d.ts +2 -0
- package/types/src/components/manage-list/manage-list-section.test.d.ts.map +1 -0
- package/types/src/components/manage-list/question.d.ts +41 -0
- package/types/src/components/manage-list/question.d.ts.map +1 -0
- package/types/src/components/manage-list/question.test.d.ts +2 -0
- package/types/src/components/manage-list/question.test.d.ts.map +1 -0
- package/types/src/components/manage-list/utils.d.ts +18 -0
- package/types/src/components/manage-list/utils.d.ts.map +1 -0
- package/types/src/components/manage-list/utils.test.d.ts +2 -0
- package/types/src/components/manage-list/utils.test.d.ts.map +1 -0
- package/types/src/components/multi-field-input/question.d.ts +106 -0
- package/types/src/components/multi-field-input/question.d.ts.map +1 -0
- package/types/src/components/multi-field-input/question.test.d.ts +2 -0
- package/types/src/components/multi-field-input/question.test.d.ts.map +1 -0
- package/types/src/components/number-entry/question.d.ts +37 -0
- package/types/src/components/number-entry/question.d.ts.map +1 -0
- package/types/src/components/radio/question.d.ts +53 -0
- package/types/src/components/radio/question.d.ts.map +1 -0
- package/types/src/components/radio/question.test.d.ts +2 -0
- package/types/src/components/radio/question.test.d.ts.map +1 -0
- package/types/src/components/select/question.d.ts +51 -0
- package/types/src/components/select/question.d.ts.map +1 -0
- package/types/src/components/select/question.test.d.ts +2 -0
- package/types/src/components/select/question.test.d.ts.map +1 -0
- package/types/src/components/single-line-input/question.d.ts +18 -0
- package/types/src/components/single-line-input/question.d.ts.map +1 -0
- package/types/src/components/single-line-input/question.test.d.ts +2 -0
- package/types/src/components/single-line-input/question.test.d.ts.map +1 -0
- package/types/src/components/text-entry/question.d.ts +34 -0
- package/types/src/components/text-entry/question.d.ts.map +1 -0
- package/types/src/components/text-entry/question.test.d.ts +2 -0
- package/types/src/components/text-entry/question.test.d.ts.map +1 -0
- package/types/src/components/text-entry-redact/question.d.ts +42 -0
- package/types/src/components/text-entry-redact/question.d.ts.map +1 -0
- package/types/src/components/text-entry-redact/question.test.d.ts +2 -0
- package/types/src/components/text-entry-redact/question.test.d.ts.map +1 -0
- package/types/src/components/unit-option-entry/question.d.ts +83 -0
- package/types/src/components/unit-option-entry/question.d.ts.map +1 -0
- package/types/src/components/unit-option-entry/question.test.d.ts +2 -0
- package/types/src/components/unit-option-entry/question.test.d.ts.map +1 -0
- package/types/src/components/utils/component-types.d.ts +19 -0
- package/types/src/components/utils/component-types.d.ts.map +1 -0
- package/types/src/components/utils/persisted-number-answer.d.ts +2 -0
- package/types/src/components/utils/persisted-number-answer.d.ts.map +1 -0
- package/types/src/components/utils/question-has-answer.d.ts +17 -0
- package/types/src/components/utils/question-has-answer.d.ts.map +1 -0
- package/types/src/components/utils/question-has-answer.test.d.ts +2 -0
- package/types/src/components/utils/question-has-answer.test.d.ts.map +1 -0
- package/types/src/components/utils/question-utils.d.ts +15 -0
- package/types/src/components/utils/question-utils.d.ts.map +1 -0
- package/types/src/components/utils/question-utils.test.d.ts +2 -0
- package/types/src/components/utils/question-utils.test.d.ts.map +1 -0
- package/types/src/controller.d.ts +78 -0
- package/types/src/controller.d.ts.map +1 -0
- package/types/src/controller.test.d.ts +2 -0
- package/types/src/controller.test.d.ts.map +1 -0
- package/types/src/index.d.ts +54 -0
- package/types/src/index.d.ts.map +1 -0
- package/types/src/journey/journey-response.d.ts +32 -0
- package/types/src/journey/journey-response.d.ts.map +1 -0
- package/types/src/journey/journey-response.test.d.ts +2 -0
- package/types/src/journey/journey-response.test.d.ts.map +1 -0
- package/types/src/journey/journey.d.ts +144 -0
- package/types/src/journey/journey.d.ts.map +1 -0
- package/types/src/journey/journey.test.d.ts +2 -0
- package/types/src/journey/journey.test.d.ts.map +1 -0
- package/types/src/lib/address-utils.d.ts +6 -0
- package/types/src/lib/address-utils.d.ts.map +1 -0
- package/types/src/lib/address-utils.test.d.ts +2 -0
- package/types/src/lib/address-utils.test.d.ts.map +1 -0
- package/types/src/lib/address.d.ts +43 -0
- package/types/src/lib/address.d.ts.map +1 -0
- package/types/src/lib/address.test.d.ts +2 -0
- package/types/src/lib/address.test.d.ts.map +1 -0
- package/types/src/lib/date-utils.d.ts +60 -0
- package/types/src/lib/date-utils.d.ts.map +1 -0
- package/types/src/lib/date-utils.test.d.ts +2 -0
- package/types/src/lib/date-utils.test.d.ts.map +1 -0
- package/types/src/lib/session-answer-store.d.ts +84 -0
- package/types/src/lib/session-answer-store.d.ts.map +1 -0
- package/types/src/lib/session-answer-store.test.d.ts +2 -0
- package/types/src/lib/session-answer-store.test.d.ts.map +1 -0
- package/types/src/lib/utils.d.ts +19 -0
- package/types/src/lib/utils.d.ts.map +1 -0
- package/types/src/lib/utils.test.d.ts +2 -0
- package/types/src/lib/utils.test.d.ts.map +1 -0
- package/types/src/lib/uuid.d.ts +7 -0
- package/types/src/lib/uuid.d.ts.map +1 -0
- package/types/src/lib/uuid.test.d.ts +2 -0
- package/types/src/lib/uuid.test.d.ts.map +1 -0
- package/types/src/middleware/build-get-journey.d.ts +6 -0
- package/types/src/middleware/build-get-journey.d.ts.map +1 -0
- package/types/src/middleware/redirect-to-unanswered-question.d.ts +12 -0
- package/types/src/middleware/redirect-to-unanswered-question.d.ts.map +1 -0
- package/types/src/middleware/redirect-to-unanswered-question.test.d.ts +2 -0
- package/types/src/middleware/redirect-to-unanswered-question.test.d.ts.map +1 -0
- package/types/src/questions/create-questions.d.ts +21 -0
- package/types/src/questions/create-questions.d.ts.map +1 -0
- package/types/src/questions/options-question.d.ts +74 -0
- package/types/src/questions/options-question.d.ts.map +1 -0
- package/types/src/questions/options-question.test.d.ts +2 -0
- package/types/src/questions/options-question.test.d.ts.map +1 -0
- package/types/src/questions/question.d.ts +274 -0
- package/types/src/questions/question.d.ts.map +1 -0
- package/types/src/questions/question.test.d.ts +2 -0
- package/types/src/questions/question.test.d.ts.map +1 -0
- package/types/src/questions/questions.d.ts +3 -0
- package/types/src/questions/questions.d.ts.map +1 -0
- package/types/src/section.d.ts +107 -0
- package/types/src/section.d.ts.map +1 -0
- package/types/src/section.test.d.ts +2 -0
- package/types/src/section.test.d.ts.map +1 -0
- package/types/src/validator/address-validator.d.ts +41 -0
- package/types/src/validator/address-validator.d.ts.map +1 -0
- package/types/src/validator/address-validator.test.d.ts +2 -0
- package/types/src/validator/address-validator.test.d.ts.map +1 -0
- package/types/src/validator/base-validator.d.ts +11 -0
- package/types/src/validator/base-validator.d.ts.map +1 -0
- package/types/src/validator/base-validator.test.d.ts +2 -0
- package/types/src/validator/base-validator.test.d.ts.map +1 -0
- package/types/src/validator/conditional-required-validator.d.ts +24 -0
- package/types/src/validator/conditional-required-validator.d.ts.map +1 -0
- package/types/src/validator/conditional-required-validator.test.d.ts +2 -0
- package/types/src/validator/conditional-required-validator.test.d.ts.map +1 -0
- package/types/src/validator/confirmation-checkbox-validator.d.ts +27 -0
- package/types/src/validator/confirmation-checkbox-validator.d.ts.map +1 -0
- package/types/src/validator/confirmation-checkbox-validator.test.d.ts +2 -0
- package/types/src/validator/confirmation-checkbox-validator.test.d.ts.map +1 -0
- package/types/src/validator/coordinates-validator.d.ts +22 -0
- package/types/src/validator/coordinates-validator.d.ts.map +1 -0
- package/types/src/validator/coordinates-validator.test.d.ts +2 -0
- package/types/src/validator/coordinates-validator.test.d.ts.map +1 -0
- package/types/src/validator/date-period-validator.d.ts +63 -0
- package/types/src/validator/date-period-validator.d.ts.map +1 -0
- package/types/src/validator/date-period-validator.test.d.ts +2 -0
- package/types/src/validator/date-period-validator.test.d.ts.map +1 -0
- package/types/src/validator/date-time-validator.d.ts +26 -0
- package/types/src/validator/date-time-validator.d.ts.map +1 -0
- package/types/src/validator/date-time-validator.test.d.ts +2 -0
- package/types/src/validator/date-time-validator.test.d.ts.map +1 -0
- package/types/src/validator/date-validator.d.ts +48 -0
- package/types/src/validator/date-validator.d.ts.map +1 -0
- package/types/src/validator/date-validator.test.d.ts +2 -0
- package/types/src/validator/date-validator.test.d.ts.map +1 -0
- package/types/src/validator/document-upload-validator.d.ts +10 -0
- package/types/src/validator/document-upload-validator.d.ts.map +1 -0
- package/types/src/validator/document-upload-validator.test.d.ts +2 -0
- package/types/src/validator/document-upload-validator.test.d.ts.map +1 -0
- package/types/src/validator/email-validator.d.ts +73 -0
- package/types/src/validator/email-validator.d.ts.map +1 -0
- package/types/src/validator/email-validator.test.d.ts +2 -0
- package/types/src/validator/email-validator.test.d.ts.map +1 -0
- package/types/src/validator/multi-field-input-validator.d.ts +70 -0
- package/types/src/validator/multi-field-input-validator.d.ts.map +1 -0
- package/types/src/validator/multi-field-input-validator.test.d.ts +2 -0
- package/types/src/validator/multi-field-input-validator.test.d.ts.map +1 -0
- package/types/src/validator/numeric-validator.d.ts +49 -0
- package/types/src/validator/numeric-validator.d.ts.map +1 -0
- package/types/src/validator/numeric-validator.test.d.ts +2 -0
- package/types/src/validator/numeric-validator.test.d.ts.map +1 -0
- package/types/src/validator/required-validator.d.ts +22 -0
- package/types/src/validator/required-validator.d.ts.map +1 -0
- package/types/src/validator/required-validator.test.d.ts +2 -0
- package/types/src/validator/required-validator.test.d.ts.map +1 -0
- package/types/src/validator/same-answer-validator.d.ts +18 -0
- package/types/src/validator/same-answer-validator.d.ts.map +1 -0
- package/types/src/validator/same-answer-validator.test.d.ts +2 -0
- package/types/src/validator/same-answer-validator.test.d.ts.map +1 -0
- package/types/src/validator/string-validator.d.ts +58 -0
- package/types/src/validator/string-validator.d.ts.map +1 -0
- package/types/src/validator/string-validator.test.d.ts +2 -0
- package/types/src/validator/string-validator.test.d.ts.map +1 -0
- package/types/src/validator/unit-option-entry-validator.d.ts +40 -0
- package/types/src/validator/unit-option-entry-validator.d.ts.map +1 -0
- package/types/src/validator/unit-option-entry-validator.test.d.ts +2 -0
- package/types/src/validator/unit-option-entry-validator.test.d.ts.map +1 -0
- package/types/src/validator/valid-option-validator.d.ts +22 -0
- package/types/src/validator/valid-option-validator.d.ts.map +1 -0
- package/types/src/validator/valid-option-validator.test.d.ts +2 -0
- package/types/src/validator/valid-option-validator.test.d.ts.map +1 -0
- package/types/src/validator/validation-error-handler.d.ts +20 -0
- package/types/src/validator/validation-error-handler.d.ts.map +1 -0
- package/types/src/validator/validation-error-handler.test.d.ts +2 -0
- package/types/src/validator/validation-error-handler.test.d.ts.map +1 -0
- package/types/src/validator/validator.d.ts +5 -0
- package/types/src/validator/validator.d.ts.map +1 -0
- package/types/src/validator/validator.test.d.ts +2 -0
- package/types/src/validator/validator.test.d.ts.map +1 -0
- package/types/test/mock/journey.d.ts +3 -0
- package/types/test/mock/journey.d.ts.map +1 -0
- package/types/test/mock/uuid.d.ts +7 -0
- package/types/test/mock/uuid.d.ts.map +1 -0
- package/types/test/utils/nunjucks.d.ts +2 -0
- package/types/test/utils/nunjucks.d.ts.map +1 -0
- package/types/test/utils/utils.d.ts +32 -0
- package/types/test/utils/utils.d.ts.map +1 -0
- package/src/lib/address.d.ts +0 -7
package/.gitattributes
ADDED
package/README.md
CHANGED
|
@@ -146,7 +146,7 @@ to add conditions to questions in multiple ways.
|
|
|
146
146
|
The simplest condition applies to just one question:
|
|
147
147
|
|
|
148
148
|
```javascript
|
|
149
|
-
import { whenQuestionHasAnswer } from '@
|
|
149
|
+
import { whenQuestionHasAnswer } from '@planning-inspectorate/dynamic-forms';
|
|
150
150
|
|
|
151
151
|
new Section('section-key', 'Section title')
|
|
152
152
|
.addQuestion(questions.q1)
|
|
@@ -206,10 +206,12 @@ Email validation is provided through the `EmailValidator` class and `EmailQuesti
|
|
|
206
206
|
#### Basic Usage
|
|
207
207
|
|
|
208
208
|
```javascript
|
|
209
|
-
import {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
import {
|
|
210
|
+
COMPONENT_TYPES,
|
|
211
|
+
createQuestions,
|
|
212
|
+
questionClasses,
|
|
213
|
+
EmailValidator
|
|
214
|
+
} from '@planning-inspectorate/dynamic-forms';
|
|
213
215
|
|
|
214
216
|
// Define question configuration
|
|
215
217
|
const questionProps = {
|
|
@@ -260,10 +262,12 @@ const businessEmailValidator = new EmailValidator({
|
|
|
260
262
|
You can also configure a single line input with email-specific attributes:
|
|
261
263
|
|
|
262
264
|
```javascript
|
|
263
|
-
import {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
265
|
+
import {
|
|
266
|
+
COMPONENT_TYPES,
|
|
267
|
+
createQuestions,
|
|
268
|
+
questionClasses,
|
|
269
|
+
EmailValidator
|
|
270
|
+
} from '@planning-inspectorate/dynamic-forms';
|
|
267
271
|
|
|
268
272
|
const questionProps = {
|
|
269
273
|
contactEmail: {
|
|
@@ -290,6 +294,13 @@ Commits must follow conventional commits, and the commit types will be used by s
|
|
|
290
294
|
|
|
291
295
|
The package will be released automatically using semantic-release, on merge to main. This will include a git tag for the release, and publishing to NPM.
|
|
292
296
|
|
|
297
|
+
### Type safety
|
|
298
|
+
We use JSDocs to describe the types used. This is helpful for the JavaScript developers, and *crucial* for this project being compatible with TypeScript. Type declarations for TypeScript users are auto-generated by `tsc` to create type declarations. So please:
|
|
299
|
+
1. Add JSDocs annotations to your code, use `@import` or an inline import, i.e. `@param {import('#section').Section} section`. Avoid a top-level import, e.g. `@typedef {import('../validator/base-validator.js')} BaseValidator` - this seems to create confusion when the compiler auto-generates the type declarations.
|
|
300
|
+
2. Maintain `index.js`. If you're adding code that users of this module will import, please make it is being exported in `index.js`.
|
|
301
|
+
|
|
302
|
+
Thank you for your co-operation and contributions!
|
|
303
|
+
|
|
293
304
|
### Tests
|
|
294
305
|
|
|
295
306
|
There are some lightweight tests in the `test` directory which sets up a basic journey and checks the rendering for each question as well as redirect logic.
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planning-inspectorate/dynamic-forms",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "This package is for building GDS forms using a configuration-based approach.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"types": "./types/src/index.d.ts",
|
|
7
8
|
"repository": {
|
|
8
9
|
"type": "git",
|
|
9
10
|
"url": "git+https://github.com/Planning-Inspectorate/dynamic-forms.git"
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"lint": "npx eslint .",
|
|
14
15
|
"format": "prettier --write .",
|
|
15
16
|
"format-check": "prettier --check .",
|
|
17
|
+
"generate-types": "npx tsc --project tsconfig.json",
|
|
16
18
|
"prepare": "node .husky/install.mjs",
|
|
17
19
|
"test": "node --test",
|
|
18
20
|
"test-coverage": "node --test --experimental-test-coverage"
|
|
@@ -26,21 +28,27 @@
|
|
|
26
28
|
},
|
|
27
29
|
"imports": {
|
|
28
30
|
"#question-types": "./src/questions/question-types.d.ts",
|
|
29
|
-
"#src/*": "./src/*",
|
|
30
31
|
"#test/*": "./test/*",
|
|
31
|
-
"#
|
|
32
|
+
"#base-validator": "./src/validator/base-validator.js",
|
|
33
|
+
"#journey": "./src/journey/journey.js",
|
|
34
|
+
"#journey-response": "./src/journey/journey-response.js",
|
|
35
|
+
"#question": "./src/questions/question.js",
|
|
36
|
+
"#section": "./src/section.js",
|
|
37
|
+
"#src/*": "./src/*"
|
|
32
38
|
},
|
|
33
39
|
"devDependencies": {
|
|
34
40
|
"@commitlint/cli": "^20.0.0",
|
|
35
41
|
"@commitlint/config-conventional": "^20.0.0",
|
|
42
|
+
"@eslint/js": "^10.0.1",
|
|
36
43
|
"body-parser": "^2.2.0",
|
|
37
44
|
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
38
45
|
"cookie-parser": "^1.4.7",
|
|
39
|
-
"eslint": "^
|
|
46
|
+
"eslint": "^10.0.0",
|
|
40
47
|
"eslint-config-prettier": "^10.1.5",
|
|
41
48
|
"express": "^5.1.0",
|
|
42
49
|
"express-session": "^1.18.2",
|
|
43
|
-
"
|
|
50
|
+
"globals": "^17.3.0",
|
|
51
|
+
"govuk-frontend": "^6.0.0",
|
|
44
52
|
"husky": "^9.1.7",
|
|
45
53
|
"lint-staged": "^16.1.2",
|
|
46
54
|
"prettier": "^3.6.2",
|
|
@@ -5,15 +5,6 @@ import { Address } from '../../lib/address.js';
|
|
|
5
5
|
import { nl2br } from '../../lib/utils.js';
|
|
6
6
|
import AddressValidator from '../../validator/address-validator.js';
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {import('../../journey/journey-response.js').JourneyResponse} JourneyResponse
|
|
10
|
-
* @typedef {import('../../journey/journey.js').Journey} Journey
|
|
11
|
-
* @typedef {import('../../section.js').Section} Section
|
|
12
|
-
* @typedef {import('../../questions/question.js').QuestionViewModel} QuestionViewModel
|
|
13
|
-
* @typedef {import('appeals-service-api').Api.SubmissionAddress} SubmissionAddress
|
|
14
|
-
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
8
|
export default class AddressQuestion extends Question {
|
|
18
9
|
/**
|
|
19
10
|
* @param {import('#question-types').QuestionParameters} params
|
|
@@ -74,7 +65,7 @@ export default class AddressQuestion extends Question {
|
|
|
74
65
|
/**
|
|
75
66
|
* Get the data to save from the request, returns an object of answers
|
|
76
67
|
* @param {import('express').Request} req
|
|
77
|
-
* @param {JourneyResponse} journeyResponse
|
|
68
|
+
* @param {import('#journey-response').JourneyResponse} journeyResponse
|
|
78
69
|
* @returns {Promise<{answers: Record<string, unknown>}>}
|
|
79
70
|
*/ //eslint-disable-next-line no-unused-vars -- journeyResponse kept for other questions to use
|
|
80
71
|
async getDataToSave(req, journeyResponse) {
|
|
@@ -44,7 +44,7 @@ export default class BooleanQuestion extends RadioQuestion {
|
|
|
44
44
|
* @param {string} [params.html]
|
|
45
45
|
* @param {string} [params.interfaceType]
|
|
46
46
|
* @param {Array.<import('../../questions/options-question.js').Option>} [params.options]
|
|
47
|
-
* @param {Array.<import('
|
|
47
|
+
* @param {Array.<import('#base-validator').BaseValidator>} [params.validators]
|
|
48
48
|
* @param {boolean} [params.editable]
|
|
49
49
|
*/
|
|
50
50
|
constructor({
|
|
@@ -3,10 +3,6 @@ import questionUtils from '../utils/question-utils.js';
|
|
|
3
3
|
|
|
4
4
|
const defaultOptionJoinString = ',';
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* @typedef {import('../../journey/journey.js').Journey} Journey
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
6
|
/**
|
|
11
7
|
* @typedef ConditionalAnswerObject
|
|
12
8
|
* @type {object}
|
|
@@ -24,7 +20,7 @@ export default class CheckboxQuestion extends OptionsQuestion {
|
|
|
24
20
|
* @param {string} [params.pageTitle]
|
|
25
21
|
* @param {string} [params.description]
|
|
26
22
|
* @param {Array.<import('../../questions/options-question.js').Option>} params.options
|
|
27
|
-
* @param {Array.<import('
|
|
23
|
+
* @param {Array.<import('#base-validator').BaseValidator>} [params.validators]
|
|
28
24
|
*/
|
|
29
25
|
constructor({ title, question, fieldName, url, pageTitle, description, options, validators }) {
|
|
30
26
|
super({
|
|
@@ -45,7 +41,7 @@ export default class CheckboxQuestion extends OptionsQuestion {
|
|
|
45
41
|
/**
|
|
46
42
|
* returns the formatted answers values to be used to build task list elements
|
|
47
43
|
* @param {string | ConditionalAnswerObject } answer will be a single value string, a comma-separated string representing multiple values (one of which may be a conditional) or a single ConditionalAnswerObject
|
|
48
|
-
* @param {Journey} journey
|
|
44
|
+
* @param {import('#journey').Journey} journey
|
|
49
45
|
* @param {String} sectionSegment
|
|
50
46
|
* @returns {Array.<Object>}
|
|
51
47
|
*/
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { formatDateForDisplay, parseDateInput } from '../../lib/date-utils.js';
|
|
2
2
|
import { Question } from '../../questions/question.js';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* @typedef {import('../../questions/question.js').QuestionViewModel} QuestionViewModel
|
|
6
|
-
* @typedef {import('../../journey/journey.js').Journey} Journey
|
|
7
|
-
* @typedef {import('../../journey/journey-response.js').JourneyResponse} JourneyResponse
|
|
8
|
-
* @typedef {import('../../section').Section} Section
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
4
|
const DEFAULT_DATE_FORMAT = 'd MMMM yyyy';
|
|
12
5
|
|
|
13
6
|
/**
|
|
@@ -29,7 +22,7 @@ export default class DateQuestion extends Question {
|
|
|
29
22
|
/**
|
|
30
23
|
* Get the data to save from the request, returns an object of answers
|
|
31
24
|
* @param {import('express').Request} req
|
|
32
|
-
* @param {JourneyResponse} journeyResponse - current journey response, modified with the new answers
|
|
25
|
+
* @param {import('#journey-response').JourneyResponse} journeyResponse - current journey response, modified with the new answers
|
|
33
26
|
* @returns {Promise.<Object>}
|
|
34
27
|
*/ //eslint-disable-next-line no-unused-vars -- journeyResponse kept for other questions to use
|
|
35
28
|
async getDataToSave(req, journeyResponse) {
|
|
@@ -3,13 +3,6 @@ import { Question } from '#question';
|
|
|
3
3
|
import { nl2br } from '../../lib/utils.js';
|
|
4
4
|
import escape from 'escape-html';
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* @typedef {import('../../questions/question.js').QuestionViewModel} QuestionViewModel
|
|
8
|
-
* @typedef {import('../../journey/journey.js').Journey} Journey
|
|
9
|
-
* @typedef {import('../../journey/journey-response.js').JourneyResponse} JourneyResponse
|
|
10
|
-
* @typedef {import('../../section').Section} Section
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
6
|
const DEFAULT_DATE_FORMAT = 'HH:mm d MMMM yyyy';
|
|
14
7
|
|
|
15
8
|
/**
|
|
@@ -38,7 +31,7 @@ export default class DatePeriodQuestion extends Question {
|
|
|
38
31
|
/**
|
|
39
32
|
* Get the data to save from the request, returns an object of answers
|
|
40
33
|
* @param {import('express').Request} req
|
|
41
|
-
* @param {JourneyResponse} journeyResponse - current journey response, modified with the new answers
|
|
34
|
+
* @param {import('#journey-response').JourneyResponse} journeyResponse - current journey response, modified with the new answers
|
|
42
35
|
* @returns {Promise.<Object>}
|
|
43
36
|
*/ //eslint-disable-next-line no-unused-vars -- journeyResponse kept for other questions to use
|
|
44
37
|
async getDataToSave(req, journeyResponse) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import SingleLineInputQuestion from '../single-line-input/question.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @typedef {import('
|
|
5
|
-
* @typedef {import('
|
|
6
|
-
* @typedef {import('
|
|
4
|
+
* @typedef {import('#question').QuestionViewModel} QuestionViewModel
|
|
5
|
+
* @typedef {import('#journey').Journey} Journey
|
|
6
|
+
* @typedef {import('#journey-response').JourneyResponse} JourneyResponse
|
|
7
7
|
* @typedef {import('../../section').Section} Section
|
|
8
8
|
* @typedef {import('../../validator/base-validator')} BaseValidator
|
|
9
9
|
*/
|
|
@@ -44,7 +44,7 @@ export default class EmailQuestion extends SingleLineInputQuestion {
|
|
|
44
44
|
* Override formatAnswerForSummary to prevent capitalization of email addresses
|
|
45
45
|
* Email addresses should remain in their original case (typically lowercase)
|
|
46
46
|
* @param {string} sectionSegment
|
|
47
|
-
* @param {import('
|
|
47
|
+
* @param {import('#journey').Journey} journey
|
|
48
48
|
* @param {string} answer
|
|
49
49
|
* @returns {Array}
|
|
50
50
|
*/
|
|
@@ -5,8 +5,7 @@ import { ManageListSection } from '#src/components/manage-list/manage-list-secti
|
|
|
5
5
|
import { mockJourney } from '#test/mock/journey.js';
|
|
6
6
|
import { mockRandomUUID } from '#test/mock/uuid.js';
|
|
7
7
|
import { configureNunjucksTestEnv } from '#test/utils/nunjucks.js';
|
|
8
|
-
import
|
|
9
|
-
import { snapshotsDir } from '#test/utils/utils.js';
|
|
8
|
+
import { assertSnapshot } from '#test/utils/utils.js';
|
|
10
9
|
|
|
11
10
|
describe('components/manage-list/question', () => {
|
|
12
11
|
const TITLE = 'Things';
|
|
@@ -96,13 +95,7 @@ describe('components/manage-list/question', () => {
|
|
|
96
95
|
const { q } = questionWithManageQuestions(ctx, { showAnswersInSummary: true });
|
|
97
96
|
const answerForSummary = q.formatAnswerForSummary('section-1', mockJourney(), [{}, {}, {}]);
|
|
98
97
|
assert.strictEqual(answerForSummary.length, 1);
|
|
99
|
-
ctx.
|
|
100
|
-
answerForSummary[0].value.replaceAll('\r\n', '\n'),
|
|
101
|
-
path.join(snapshotsDir(), 'manage-list-answer-summary.html'),
|
|
102
|
-
{
|
|
103
|
-
serializers: [(v) => v]
|
|
104
|
-
}
|
|
105
|
-
);
|
|
98
|
+
assertSnapshot(ctx, answerForSummary[0].value, 'manage-list-answer-summary.html');
|
|
106
99
|
});
|
|
107
100
|
|
|
108
101
|
it('should render with answers', (ctx) => {
|
|
@@ -114,9 +107,7 @@ describe('components/manage-list/question', () => {
|
|
|
114
107
|
};
|
|
115
108
|
q.renderAction(res, viewModel);
|
|
116
109
|
assert.strictEqual(res.render.mock.callCount(), 1);
|
|
117
|
-
ctx
|
|
118
|
-
serializers: [(v) => v]
|
|
119
|
-
});
|
|
110
|
+
assertSnapshot(ctx, res.render.mock.calls[0].result, 'manage-list-render.html');
|
|
120
111
|
});
|
|
121
112
|
|
|
122
113
|
it('should render with answers & questions', (ctx) => {
|
|
@@ -130,13 +121,7 @@ describe('components/manage-list/question', () => {
|
|
|
130
121
|
};
|
|
131
122
|
q.renderAction(res, viewModel);
|
|
132
123
|
assert.strictEqual(res.render.mock.callCount(), 1);
|
|
133
|
-
ctx.
|
|
134
|
-
res.render.mock.calls[0].result,
|
|
135
|
-
path.join(snapshotsDir(), 'manage-list-render-questions.html'),
|
|
136
|
-
{
|
|
137
|
-
serializers: [(v) => v]
|
|
138
|
-
}
|
|
139
|
-
);
|
|
124
|
+
assertSnapshot(ctx, res.render.mock.calls[0].result, 'manage-list-render-questions.html');
|
|
140
125
|
});
|
|
141
126
|
|
|
142
127
|
describe('getDataToSave', () => {
|
|
@@ -3,9 +3,9 @@ import escape from 'escape-html';
|
|
|
3
3
|
import { nl2br } from '../../lib/utils.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* @typedef {import('
|
|
7
|
-
* @typedef {import('
|
|
8
|
-
* @typedef {import('
|
|
6
|
+
* @typedef {import('#question').QuestionViewModel} QuestionViewModel
|
|
7
|
+
* @typedef {import('#journey').Journey} Journey
|
|
8
|
+
* @typedef {import('#journey-response').JourneyResponse} JourneyResponse
|
|
9
9
|
* @typedef {import('../../section').Section} Section
|
|
10
10
|
* @typedef {import('../../validator/base-validator')} BaseValidator
|
|
11
11
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert';
|
|
3
3
|
import MultiFieldInputQuestion from './question.js';
|
|
4
|
-
import { Journey } from '
|
|
4
|
+
import { Journey } from '#journey';
|
|
5
5
|
|
|
6
6
|
const TITLE = 'title';
|
|
7
7
|
const QUESTION = 'Question?';
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { Question } from '#question';
|
|
2
2
|
import { getPersistedNumberAnswer } from '../utils/persisted-number-answer.js';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* @typedef {import('../../journey/journey.js').Journey} Journey
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
4
|
export default class NumberEntryQuestion extends Question {
|
|
9
5
|
/**
|
|
10
6
|
* @param {import('#question-types').QuestionParameters} params
|
|
@@ -36,7 +32,7 @@ export default class NumberEntryQuestion extends Question {
|
|
|
36
32
|
/**
|
|
37
33
|
* returns the formatted answers values to be used to build task list elements
|
|
38
34
|
* @param {Object} answer
|
|
39
|
-
* @param {Journey} journey
|
|
35
|
+
* @param {import('#journey').Journey} journey
|
|
40
36
|
* @param {String} sectionSegment
|
|
41
37
|
* @returns {Array<{
|
|
42
38
|
* key: string;
|
|
@@ -15,7 +15,7 @@ export default class RadioQuestion extends OptionsQuestion {
|
|
|
15
15
|
* @param {string} [params.html]
|
|
16
16
|
* @param {string} [params.legend] - optional legend, used instead of h1
|
|
17
17
|
* @param {Array.<import('../../questions/options-question.js').Option>} params.options
|
|
18
|
-
* @param {Array.<import('
|
|
18
|
+
* @param {Array.<import('#base-validator').BaseValidator>} [params.validators]
|
|
19
19
|
* @param {boolean} [params.editable]
|
|
20
20
|
* @param {Object<string, any>} [params.viewData]
|
|
21
21
|
* @param {import('../../questions/question-types.js').ActionLink} [params.actionLink]
|
|
@@ -16,7 +16,7 @@ export default class SelectQuestion extends OptionsQuestion {
|
|
|
16
16
|
* @param {string} [params.legend] - optional legend, used instead of h1
|
|
17
17
|
* @param {Array.<import('../../questions/options-question.js').Option>} params.options
|
|
18
18
|
* @param {Object<string, any>} [params.viewData]
|
|
19
|
-
* @param {Array.<import('
|
|
19
|
+
* @param {Array.<import('#base-validator').BaseValidator>} [params.validators]
|
|
20
20
|
*/
|
|
21
21
|
constructor({
|
|
22
22
|
title,
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import { Question } from '#question';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {import('../../questions/question.js').QuestionViewModel} QuestionViewModel
|
|
5
|
-
* @typedef {import('../../journey/journey.js').Journey} Journey
|
|
6
|
-
* @typedef {import('../../journey/journey-response.js').JourneyResponse} JourneyResponse
|
|
7
|
-
* @typedef {import('../../section').Section} Section
|
|
8
|
-
* @typedef {import('../../validator/base-validator')} BaseValidator
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
3
|
/**
|
|
12
4
|
* @class
|
|
13
5
|
*/
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Question } from '#question';
|
|
2
2
|
/**
|
|
3
|
-
* @
|
|
4
|
-
* @
|
|
5
|
-
* @
|
|
6
|
-
* @
|
|
3
|
+
* @import {QuestionViewModel} from '#question'
|
|
4
|
+
* @import {Journey} from '#journey'
|
|
5
|
+
* @import {JourneyResponse} from '#journey-response'
|
|
6
|
+
* @import {Section} from '#section'
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
}) }}
|
|
124
124
|
|
|
125
125
|
{{ govukButton({
|
|
126
|
-
text: "
|
|
126
|
+
text: "Remove all redactions",
|
|
127
127
|
classes: "govuk-button--secondary",
|
|
128
128
|
id: "redact-undo-all",
|
|
129
129
|
type: "button"
|
|
@@ -192,16 +192,20 @@
|
|
|
192
192
|
showError('No changes to undo');
|
|
193
193
|
}
|
|
194
194
|
});
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
195
|
+
redactUndoAll.addEventListener('click', () => {
|
|
196
|
+
const unredated = unredactedText.dataset.original;
|
|
197
|
+
if (history.length === 0 && textArea.value === unredated) {
|
|
198
|
+
showError('No changes to undo');
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
hideError();
|
|
202
|
+
textArea.value = unredated || '';
|
|
203
|
+
history.length = 0;
|
|
204
|
+
|
|
205
|
+
for (const rejectLink of rejectLinks) {
|
|
206
|
+
rejectLink.text = 'Accept';
|
|
207
|
+
}
|
|
208
|
+
});
|
|
205
209
|
for (const rejectLink of rejectLinks) {
|
|
206
210
|
rejectLink.addEventListener('click', () => {
|
|
207
211
|
const index = parseInt(rejectLink.getAttribute('data-redact').replace('suggestion-reject-', ''));
|
|
@@ -1,21 +1,6 @@
|
|
|
1
1
|
import { Question } from '#question';
|
|
2
2
|
import { nl2br } from '../../lib/utils.js';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* @typedef {import('../../questions/question.js').QuestionViewModel} QuestionViewModel
|
|
6
|
-
* @typedef {import('../../journey/journey.js').Journey} Journey
|
|
7
|
-
* @typedef {import('../../journey/journey-response.js').JourneyResponse} JourneyResponse
|
|
8
|
-
* @typedef {import('../../section').Section} Section
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @typedef {Object} TextEntryCheckbox
|
|
13
|
-
* @property {string} header
|
|
14
|
-
* @property {string} text
|
|
15
|
-
* @property {string} name
|
|
16
|
-
* @property {string} [errorMessage]
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
4
|
export const REDACT_CHARACTER = '█';
|
|
20
5
|
export const TRUNCATED_MAX_LENGTH = 500;
|
|
21
6
|
|
|
@@ -25,7 +10,7 @@ export const TRUNCATED_MAX_LENGTH = 500;
|
|
|
25
10
|
export default class TextEntryRedactQuestion extends Question {
|
|
26
11
|
/**
|
|
27
12
|
* @param {import('#question-types').QuestionParameters} params
|
|
28
|
-
* @param {TextEntryCheckbox} [params.textEntryCheckbox]
|
|
13
|
+
* @param {import('../text-entry/question.js').TextEntryCheckbox} [params.textEntryCheckbox]
|
|
29
14
|
* @param {string|undefined} [params.label] if defined this show as a label for the input and the question will just be a standard h1
|
|
30
15
|
* @param {boolean} [params.onlyShowRedactedValueForSummary] whether to only show redacted value for summary
|
|
31
16
|
* @param {boolean} [params.useRedactedFieldNameForSave] whether to use the redacted field name when saving answers
|
|
@@ -57,6 +42,11 @@ export default class TextEntryRedactQuestion extends Question {
|
|
|
57
42
|
this.shouldTruncateSummary = shouldTruncateSummary;
|
|
58
43
|
}
|
|
59
44
|
|
|
45
|
+
/**
|
|
46
|
+
* @param {import('express').Request} req
|
|
47
|
+
* @param {import('#journey-response').JourneyResponse} journeyResponse
|
|
48
|
+
* @returns {Promise<{answers: Record<string, unknown>}>}
|
|
49
|
+
*/
|
|
60
50
|
async getDataToSave(req, journeyResponse) {
|
|
61
51
|
if (this.useRedactedFieldNameForSave) {
|
|
62
52
|
const fieldName = this.fieldName + 'Redacted';
|
|
@@ -4,13 +4,6 @@ import { conditionalIsJustHTML } from '../utils/question-utils.js';
|
|
|
4
4
|
|
|
5
5
|
const defaultOptionJoinString = ',';
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {import('../../questions/question.js').QuestionViewModel} QuestionViewModel
|
|
9
|
-
* @typedef {import('../../journey/journey.js').Journey} Journey
|
|
10
|
-
* @typedef {import('../../journey/journey-response.js').JourneyResponse} JourneyResponse
|
|
11
|
-
* @typedef {import('../../section').Section} Section
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
7
|
/**
|
|
15
8
|
* UnitOptions are the options displayed in the radio format - in this case the value
|
|
16
9
|
* represents the unit.
|
|
@@ -67,13 +60,13 @@ export default class UnitOptionEntryQuestion extends Question {
|
|
|
67
60
|
|
|
68
61
|
/**
|
|
69
62
|
* gets the view model for this question
|
|
70
|
-
* @param {Section} section - the current section
|
|
71
|
-
* @param {Journey} journey - the journey we are in
|
|
63
|
+
* @param {import('../../section').Section} section - the current section
|
|
64
|
+
* @param {import('#journey').Journey} journey - the journey we are in
|
|
72
65
|
* @param {Record<string, unknown>} [customViewData] additional data to send to view
|
|
73
66
|
* @param {Record<string, unknown>} [payload]
|
|
74
67
|
* @param {import('#src/questions/question-types.d.ts').PrepQuestionForRenderingOptions} options
|
|
75
|
-
* @returns {QuestionViewModel & {
|
|
76
|
-
* question: QuestionViewModel['question'] & {
|
|
68
|
+
* @returns {import('#question').QuestionViewModel & {
|
|
69
|
+
* question: import('#question').QuestionViewModel['question'] & {
|
|
77
70
|
* options:UnitOption[]
|
|
78
71
|
* }
|
|
79
72
|
* }}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const COMPONENT_TYPES = Object.freeze({
|
|
2
|
+
CHECKBOX: 'checkbox',
|
|
3
|
+
BOOLEAN: 'boolean',
|
|
4
|
+
RADIO: 'radio',
|
|
5
|
+
DATE: 'date',
|
|
6
|
+
DATE_PERIOD: 'date-period',
|
|
7
|
+
DATE_TIME: 'date-time',
|
|
8
|
+
TEXT_ENTRY: 'text-entry',
|
|
9
|
+
TEXT_ENTRY_REDACT: 'text-entry-redact',
|
|
10
|
+
SELECT: 'select',
|
|
11
|
+
SINGLE_LINE_INPUT: 'single-line-input',
|
|
12
|
+
MULTI_FIELD_INPUT: 'multi-field-input',
|
|
13
|
+
NUMBER: 'number',
|
|
14
|
+
ADDRESS: 'site-address',
|
|
15
|
+
UNIT_OPTION: 'unit-option',
|
|
16
|
+
EMAIL: 'email',
|
|
17
|
+
MANAGE_LIST: 'manage-list'
|
|
18
|
+
});
|