@planning-inspectorate/dynamic-forms 3.21.0 → 3.23.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/README.md +52 -1
- package/docs/Dynamic Sections.md +47 -0
- package/package.json +1 -1
- package/src/components/manage-list/question.d.ts.map +1 -1
- package/src/components/manage-list/question.js +5 -0
- package/src/components/manage-list/question.test.js +3 -1
- package/src/components/multi-field-input/question.d.ts.map +1 -1
- package/src/components/multi-field-input/question.js +7 -5
- package/src/components/multi-field-input/question.test.js +126 -213
- package/src/components/number-entry/index.njk +2 -3
- package/src/components/number-entry/question.d.ts +3 -2
- package/src/components/number-entry/question.d.ts.map +1 -1
- package/src/components/number-entry/question.js +25 -2
- package/src/components/number-entry/question.test.js +65 -0
- package/src/components/text-entry-redact/question.d.ts.map +1 -1
- package/src/components/text-entry-redact/question.js +3 -1
- package/src/components/text-entry-redact/question.test.js +9 -0
- package/src/components/unit-option-entry/question.d.ts.map +1 -1
- package/src/components/unit-option-entry/question.js +3 -1
- package/src/components/unit-option-entry/question.test.js +9 -0
- package/src/controller.d.ts +15 -3
- package/src/controller.d.ts.map +1 -1
- package/src/controller.js +19 -11
- package/src/controller.test.js +182 -153
- package/src/dynamic-section.d.ts +40 -0
- package/src/dynamic-section.d.ts.map +1 -0
- package/src/dynamic-section.js +51 -0
- package/src/dynamic-section.test.js +113 -0
- package/src/index.d.ts +2 -1
- package/src/index.js +2 -1
- package/src/index.test.js +3 -0
- package/src/journey/journey.d.ts +10 -0
- package/src/journey/journey.d.ts.map +1 -1
- package/src/journey/journey.js +15 -0
- package/src/lib/answer-utils.d.ts +22 -0
- package/src/lib/answer-utils.d.ts.map +1 -0
- package/src/lib/answer-utils.js +34 -0
- package/src/{components/manage-list/utils.test.js → lib/answer-utils.test.js} +9 -11
- package/src/lib/session-answer-store.d.ts.map +1 -1
- package/src/lib/session-answer-store.js +14 -6
- package/src/lib/session-answer-store.test.js +43 -0
- package/src/middleware/redirect-to-unanswered-question.d.ts.map +1 -1
- package/src/middleware/redirect-to-unanswered-question.js +4 -3
- package/src/middleware/redirect-to-unanswered-question.test.js +32 -0
- package/src/questions/question.d.ts +8 -3
- package/src/questions/question.d.ts.map +1 -1
- package/src/questions/question.js +16 -6
- package/src/questions/question.test.js +19 -0
- package/src/section.d.ts +19 -0
- package/src/section.d.ts.map +1 -1
- package/src/section.js +50 -9
- package/src/section.test.js +9 -0
- package/test/dynamic-journey.test.js +372 -0
- package/typedefs/question-props.d.ts +3 -2
- package/typedefs/question-types.d.ts +3 -0
- package/src/components/manage-list/utils.d.ts +0 -18
- package/src/components/manage-list/utils.d.ts.map +0 -1
- package/src/components/manage-list/utils.js +0 -35
|
@@ -14,4 +14,69 @@ describe('number-entry', () => {
|
|
|
14
14
|
|
|
15
15
|
assert.strictEqual(question.capitaliseAnswer, true);
|
|
16
16
|
});
|
|
17
|
+
|
|
18
|
+
it('should accept Affix objects for prefix and suffix', () => {
|
|
19
|
+
const PREFIX = { text: '£', classes: 'govuk-!-font-weight-bold' };
|
|
20
|
+
const SUFFIX = { text: 'kg' };
|
|
21
|
+
|
|
22
|
+
const question = new NumberEntryQuestion({
|
|
23
|
+
title: 'Question',
|
|
24
|
+
question: 'Question',
|
|
25
|
+
fieldName: 'question',
|
|
26
|
+
url: 'Question',
|
|
27
|
+
prefix: PREFIX,
|
|
28
|
+
suffix: SUFFIX
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
assert.strictEqual(question.prefix, PREFIX);
|
|
32
|
+
assert.strictEqual(question.suffix, SUFFIX);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should convert string suffix to Affix object and warn about deprecation', (t) => {
|
|
36
|
+
const warnMock = t.mock.method(console, 'warn', () => {});
|
|
37
|
+
|
|
38
|
+
const question = new NumberEntryQuestion({
|
|
39
|
+
title: 'Question',
|
|
40
|
+
question: 'Question',
|
|
41
|
+
fieldName: 'question',
|
|
42
|
+
url: 'Question',
|
|
43
|
+
suffix: 'kg'
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
assert.deepStrictEqual(question.suffix, { text: 'kg' });
|
|
47
|
+
assert.strictEqual(warnMock.mock.calls.length, 1);
|
|
48
|
+
assert.match(warnMock.mock.calls[0].arguments[0], /suffix.*deprecated/);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should leave prefix and suffix undefined when not provided', () => {
|
|
52
|
+
const question = new NumberEntryQuestion({
|
|
53
|
+
title: 'Question',
|
|
54
|
+
question: 'Question',
|
|
55
|
+
fieldName: 'question',
|
|
56
|
+
url: 'Question'
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
assert.strictEqual(question.prefix, undefined);
|
|
60
|
+
assert.strictEqual(question.suffix, undefined);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should add prefix and suffix to the view model', () => {
|
|
64
|
+
const PREFIX = { text: '£' };
|
|
65
|
+
const SUFFIX = { text: 'kg' };
|
|
66
|
+
|
|
67
|
+
const question = new NumberEntryQuestion({
|
|
68
|
+
title: 'Question',
|
|
69
|
+
question: 'Question',
|
|
70
|
+
fieldName: 'question',
|
|
71
|
+
url: 'Question',
|
|
72
|
+
prefix: PREFIX,
|
|
73
|
+
suffix: SUFFIX
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const viewModel = { question: {} };
|
|
77
|
+
question.addCustomDataToViewModel(viewModel);
|
|
78
|
+
|
|
79
|
+
assert.strictEqual(viewModel.question.prefix, PREFIX);
|
|
80
|
+
assert.strictEqual(viewModel.question.suffix, SUFFIX);
|
|
81
|
+
});
|
|
17
82
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"question.d.ts","sourceRoot":"","sources":["question.js"],"names":[],"mappings":"AAGA,+BAAgC,QAAG,CAAC;AACpC,mCAAoC,GAAG,CAAC;AAExC;;GAEG;AACH;IACC;;OAEG;IACH,gLAFW,OAAO,+BAA+B,EAAE,6BAA6B,EAwB/E;IAPA,yFAA0C;IAC1C,0BAAkB;IAClB,qDAAsE;IACtE,iDAA8D;IAC9D,uCAA0C;IAC1C,gCAA8B;IAC9B,2CAAkD;IAkBnD,+NAOC;IAED,yCAEC;IAYD;;OAEG;IACH,
|
|
1
|
+
{"version":3,"file":"question.d.ts","sourceRoot":"","sources":["question.js"],"names":[],"mappings":"AAGA,+BAAgC,QAAG,CAAC;AACpC,mCAAoC,GAAG,CAAC;AAExC;;GAEG;AACH;IACC;;OAEG;IACH,gLAFW,OAAO,+BAA+B,EAAE,6BAA6B,EAwB/E;IAPA,yFAA0C;IAC1C,0BAAkB;IAClB,qDAAsE;IACtE,iDAA8D;IAC9D,uCAA0C;IAC1C,gCAA8B;IAC9B,2CAAkD;IAkBnD,+NAOC;IAED,yCAEC;IAYD;;OAEG;IACH,iJAyBC;CACD;;yBAxGwB,WAAW"}
|
|
@@ -77,7 +77,9 @@ export class TextEntryRedactQuestion extends Question {
|
|
|
77
77
|
* returns the formatted answers values to be used to build task list elements
|
|
78
78
|
*/
|
|
79
79
|
formatAnswerForSummary(sectionSegment, journey, answer, capitals = true) {
|
|
80
|
-
|
|
80
|
+
// get the response/answers for the section we're in - which might be a dynamic section
|
|
81
|
+
const response = journey.responseForSection(sectionSegment);
|
|
82
|
+
const redacted = response.answers[this.fieldName + 'Redacted'];
|
|
81
83
|
let toShow;
|
|
82
84
|
if (this.onlyShowRedactedValueForSummary) {
|
|
83
85
|
toShow = redacted;
|
|
@@ -211,6 +211,9 @@ describe('./src/dynamic-forms/components/text-entry-redact/question.js', () => {
|
|
|
211
211
|
getCurrentQuestionUrl: () => {
|
|
212
212
|
return '/redacted-comment';
|
|
213
213
|
},
|
|
214
|
+
responseForSection() {
|
|
215
|
+
return this.response;
|
|
216
|
+
},
|
|
214
217
|
response: {
|
|
215
218
|
answers: {}
|
|
216
219
|
}
|
|
@@ -248,6 +251,9 @@ describe('./src/dynamic-forms/components/text-entry-redact/question.js', () => {
|
|
|
248
251
|
getCurrentQuestionUrl: () => {
|
|
249
252
|
return '/redacted-comment';
|
|
250
253
|
},
|
|
254
|
+
responseForSection() {
|
|
255
|
+
return this.response;
|
|
256
|
+
},
|
|
251
257
|
response: {
|
|
252
258
|
answers: {}
|
|
253
259
|
}
|
|
@@ -284,6 +290,9 @@ describe('./src/dynamic-forms/components/text-entry-redact/question.js', () => {
|
|
|
284
290
|
getCurrentQuestionUrl: () => {
|
|
285
291
|
return '/redacted-comment';
|
|
286
292
|
},
|
|
293
|
+
responseForSection() {
|
|
294
|
+
return this.response;
|
|
295
|
+
},
|
|
287
296
|
response: {
|
|
288
297
|
answers: {}
|
|
289
298
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"question.d.ts","sourceRoot":"","sources":["question.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;IAIC;;;OAGG;IACH,uEAHW,OAAO,+BAA+B,EAAE,6BAA6B,oBACrE,MAAM,CAAC,MAAM,WAAW,EAoBlC;IAzBD,gCAAgC;IAChC,SADW,KAAK,CAAC,UAAU,CAAC,CACpB;IAoBP,6BAAgD;IAEhD,0BAAkB;IAClB,yBAA+C;IAGhD;;;;;;;;;;;;OAYG;IACH,kCAXW,OAAO,kBAAkB,EAAE,OAAO,WAClC,OAAO,UAAU,EAAE,OAAO,mBAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACvB,OAAO,+BAA+B,EAAE,+BAA+B,GACrE,OAAO,+BAA+B,EAAE,iBAAiB,GAAG;QACpE,QAAQ,EAAE,OAAO,+BAA+B,EAAE,iBAAiB,CAAC,UAAU,CAAC,GAAG;YAChF,OAAO,EAAC,UAAU,EAAE,CAAA;SACrB,CAAA;KACF,CAmDH;IAED;;;;;OAKG,CACH,mBAJW,OAAO,SAAS,EAAE,OAAO,mBACzB,eAAe,GACb,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAgCzD;IAED;;OAEG;IACH,
|
|
1
|
+
{"version":3,"file":"question.d.ts","sourceRoot":"","sources":["question.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;IAIC;;;OAGG;IACH,uEAHW,OAAO,+BAA+B,EAAE,6BAA6B,oBACrE,MAAM,CAAC,MAAM,WAAW,EAoBlC;IAzBD,gCAAgC;IAChC,SADW,KAAK,CAAC,UAAU,CAAC,CACpB;IAoBP,6BAAgD;IAEhD,0BAAkB;IAClB,yBAA+C;IAGhD;;;;;;;;;;;;OAYG;IACH,kCAXW,OAAO,kBAAkB,EAAE,OAAO,WAClC,OAAO,UAAU,EAAE,OAAO,mBAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACvB,OAAO,+BAA+B,EAAE,+BAA+B,GACrE,OAAO,+BAA+B,EAAE,iBAAiB,GAAG;QACpE,QAAQ,EAAE,OAAO,+BAA+B,EAAE,iBAAiB,CAAC,UAAU,CAAC,GAAG;YAChF,OAAO,EAAC,UAAU,EAAE,CAAA;SACrB,CAAA;KACF,CAmDH;IAED;;;;;OAKG,CACH,mBAJW,OAAO,SAAS,EAAE,OAAO,mBACzB,eAAe,GACb,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAgCzD;IAED;;OAEG;IACH,6HAeC;CACD;;;;;;;;;;yBAvKY;IACR,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAA;CACH;yBA5BsB,6BAA6B"}
|
|
@@ -169,7 +169,9 @@ export class UnitOptionEntryQuestion extends Question {
|
|
|
169
169
|
const selectedOption = this.options.find((option) => option.value === answer);
|
|
170
170
|
const conversionFactor =
|
|
171
171
|
(!conditionalIsJustHTML(selectedOption?.conditional) && selectedOption?.conditional.conversionFactor) || 1;
|
|
172
|
-
|
|
172
|
+
// get the response/answers for the section we're in - which might be a dynamic section
|
|
173
|
+
const response = journey.responseForSection(sectionSegment);
|
|
174
|
+
const unconvertedAnswer = response.answers[this.conditionalFieldName];
|
|
173
175
|
|
|
174
176
|
const answerQuantity = Number(unconvertedAnswer) / conversionFactor;
|
|
175
177
|
if (isNaN(answerQuantity)) throw new Error('Conditional answer had an unexpected type');
|
|
@@ -75,6 +75,9 @@ describe('./src/dynamic-forms/components/unit-option-entry/question.js', () => {
|
|
|
75
75
|
[CONDITIONAL_FIELDNAME]: '1.123456789'
|
|
76
76
|
}
|
|
77
77
|
},
|
|
78
|
+
responseForSection() {
|
|
79
|
+
return this.response;
|
|
80
|
+
},
|
|
78
81
|
getCurrentQuestionUrl: mock.fn()
|
|
79
82
|
};
|
|
80
83
|
const result = unitOptionEntryQuestion.formatAnswerForSummary('test', journey, 'ha');
|
|
@@ -87,6 +90,9 @@ describe('./src/dynamic-forms/components/unit-option-entry/question.js', () => {
|
|
|
87
90
|
[CONDITIONAL_FIELDNAME]: '1'
|
|
88
91
|
}
|
|
89
92
|
},
|
|
93
|
+
responseForSection() {
|
|
94
|
+
return this.response;
|
|
95
|
+
},
|
|
90
96
|
getCurrentQuestionUrl: mock.fn()
|
|
91
97
|
};
|
|
92
98
|
const result = unitOptionEntryQuestion.formatAnswerForSummary('test', journey, 'ha');
|
|
@@ -99,6 +105,9 @@ describe('./src/dynamic-forms/components/unit-option-entry/question.js', () => {
|
|
|
99
105
|
[CONDITIONAL_FIELDNAME]: 'hello'
|
|
100
106
|
}
|
|
101
107
|
},
|
|
108
|
+
responseForSection() {
|
|
109
|
+
return this.response;
|
|
110
|
+
},
|
|
102
111
|
getCurrentQuestionUrl: mock.fn()
|
|
103
112
|
};
|
|
104
113
|
assert.throws(() => {
|
package/src/controller.d.ts
CHANGED
|
@@ -20,6 +20,9 @@ export function question(req: import("express-serve-static-core").Request<import
|
|
|
20
20
|
* @property {boolean} isManageListItem
|
|
21
21
|
* @property {string} [manageListQuestionFieldName]
|
|
22
22
|
* @property {boolean} [manageListItemRemove]
|
|
23
|
+
* @property {boolean} isDynamicSection is this save action for a question within a DynamicSection?
|
|
24
|
+
* @property {string} [dynamicSectionId] if this is within a DynamicSection, what is the section ID (segment)
|
|
25
|
+
* @property {string} [dynamicSectionFieldName] if this is within a DynamicSection, what is the fieldName for the array?
|
|
23
26
|
* @property {Object<string, any>} data
|
|
24
27
|
*/
|
|
25
28
|
/**
|
|
@@ -31,9 +34,6 @@ export function question(req: import("express-serve-static-core").Request<import
|
|
|
31
34
|
* @returns {import('express').Handler}
|
|
32
35
|
*/
|
|
33
36
|
export function buildSave(saveData: SaveDataFn, redirectToTaskListOnSuccess?: boolean): import("express").Handler;
|
|
34
|
-
export type Journey = import("./journey/journey.js").Journey;
|
|
35
|
-
export type Question = import("./questions/question.js").Question;
|
|
36
|
-
export type Section = import("./section.js").Section;
|
|
37
37
|
export type SectionView = {
|
|
38
38
|
heading: string;
|
|
39
39
|
status: string;
|
|
@@ -62,6 +62,18 @@ export type SaveParams = {
|
|
|
62
62
|
isManageListItem: boolean;
|
|
63
63
|
manageListQuestionFieldName?: string | undefined;
|
|
64
64
|
manageListItemRemove?: boolean | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* is this save action for a question within a DynamicSection?
|
|
67
|
+
*/
|
|
68
|
+
isDynamicSection: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* if this is within a DynamicSection, what is the section ID (segment)
|
|
71
|
+
*/
|
|
72
|
+
dynamicSectionId?: string | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* if this is within a DynamicSection, what is the fieldName for the array?
|
|
75
|
+
*/
|
|
76
|
+
dynamicSectionFieldName?: string | undefined;
|
|
65
77
|
data: {
|
|
66
78
|
[x: string]: any;
|
|
67
79
|
};
|
package/src/controller.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["controller.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["controller.js"],"names":[],"mappings":"AAyDA;;;GAGG;AACH,qCAHW,MAAM,GACJ,OAAO,SAAS,EAAE,OAAO,CAIrC;AAED;;;;;GAKG;AACH,0BALW,OAAO,SAAS,EAAE,OAAO,OACzB,OAAO,SAAS,EAAE,QAAQ,eAC1B,MAAM,YACN,MAAM,iBAmEhB;;AAmDD;;;;;;;;;;;;;GAaG;AAEH;;GAEG;AAEH;;;;GAIG;AACH,oCAJW,UAAU,gCACV,OAAO,GACL,OAAO,SAAS,EAAE,OAAO,CA4FrC;;aApSa,MAAM;YACN,MAAM;UAEjB;QAAiC,IAAI,EAA1B,KAAK,CAAE,OAAO,CAAC;KAC5B;;;SAIa;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;WAChB;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;;eAC1B,OAAO,+BAA+B,EAAE,UAAU,EAAE;;;;SA0K7D,OAAO,SAAS,EAAE,OAAO;SACzB,OAAO,SAAS,EAAE,QAAQ;eAC1B,MAAM;iBACN,MAAM;sBACN,OAAO;;;;;;sBAGP,OAAO;;;;;;;;;;;;;yBAOR,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC"}
|
package/src/controller.js
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { SECTION_STATUS } from './section.js';
|
|
2
2
|
import questionUtils from './components/utils/question-utils.js';
|
|
3
|
-
import {
|
|
3
|
+
import { answerObjectForListItemSaving } from '#src/lib/answer-utils.js';
|
|
4
4
|
import { booleanToYesNoValue } from '#src/components/boolean/question.js';
|
|
5
5
|
import { MANAGE_LIST_ACTIONS } from '#src/components/manage-list/manage-list-actions.js';
|
|
6
6
|
import { toArray } from '#src/lib/utils.js';
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {import('./journey/journey.js').Journey} Journey
|
|
10
|
-
* @typedef {import('./questions/question.js').Question} Question
|
|
11
|
-
* @typedef {import('./section.js').Section} Section
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
8
|
/**
|
|
15
9
|
* @typedef {Object} SectionView
|
|
16
10
|
* @property {string} heading
|
|
@@ -77,7 +71,7 @@ export function buildList(viewData = {}) {
|
|
|
77
71
|
*/
|
|
78
72
|
export async function list(req, res, pageCaption, viewData) {
|
|
79
73
|
//render check your answers view
|
|
80
|
-
/** @type {Journey} */
|
|
74
|
+
/** @type {import('./journey/journey.js').Journey} */
|
|
81
75
|
const journey = res.locals.journey;
|
|
82
76
|
/** @type {import("./journey/journey-response.js").JourneyResponse} */
|
|
83
77
|
const journeyResponse = res.locals.journeyResponse;
|
|
@@ -92,6 +86,9 @@ export async function list(req, res, pageCaption, viewData) {
|
|
|
92
86
|
const status = section.getStatus(journeyResponse);
|
|
93
87
|
const sectionView = buildSectionViewModel(section.name, status);
|
|
94
88
|
|
|
89
|
+
// answers for this section may be within an array, for example dynamic sections
|
|
90
|
+
const response = section.getResponse(journeyResponse);
|
|
91
|
+
|
|
95
92
|
// update completed count
|
|
96
93
|
if (status === SECTION_STATUS.COMPLETE) {
|
|
97
94
|
summaryListData.completedSectionCount++;
|
|
@@ -104,11 +101,13 @@ export async function list(req, res, pageCaption, viewData) {
|
|
|
104
101
|
continue;
|
|
105
102
|
}
|
|
106
103
|
|
|
107
|
-
if (!question.shouldDisplay(
|
|
104
|
+
if (!question.shouldDisplay(response)) {
|
|
108
105
|
continue;
|
|
109
106
|
}
|
|
110
107
|
|
|
111
|
-
|
|
108
|
+
// answers here may be from an array for dynamic sections
|
|
109
|
+
// this is handled by section.responseForSection above
|
|
110
|
+
const answers = response.answers;
|
|
112
111
|
let answer = answers[question.fieldName];
|
|
113
112
|
const conditionalAnswer = questionUtils.getConditionalAnswer(answers, question, answer);
|
|
114
113
|
if (conditionalAnswer) {
|
|
@@ -195,6 +194,9 @@ export async function question(req, res) {
|
|
|
195
194
|
* @property {boolean} isManageListItem
|
|
196
195
|
* @property {string} [manageListQuestionFieldName]
|
|
197
196
|
* @property {boolean} [manageListItemRemove]
|
|
197
|
+
* @property {boolean} isDynamicSection is this save action for a question within a DynamicSection?
|
|
198
|
+
* @property {string} [dynamicSectionId] if this is within a DynamicSection, what is the section ID (segment)
|
|
199
|
+
* @property {string} [dynamicSectionFieldName] if this is within a DynamicSection, what is the fieldName for the array?
|
|
198
200
|
* @property {Object<string, any>} data
|
|
199
201
|
*/
|
|
200
202
|
|
|
@@ -229,6 +231,7 @@ export function buildSave(saveData, redirectToTaskListOnSuccess) {
|
|
|
229
231
|
return res.redirect(journey.taskListUrl);
|
|
230
232
|
}
|
|
231
233
|
}
|
|
234
|
+
const isDynamicSection = section.isDynamicSection;
|
|
232
235
|
|
|
233
236
|
try {
|
|
234
237
|
// check for validation errors
|
|
@@ -248,6 +251,9 @@ export function buildSave(saveData, redirectToTaskListOnSuccess) {
|
|
|
248
251
|
isManageListItem: question.isInManageListSection,
|
|
249
252
|
manageListQuestionFieldName: manageListQuestion?.fieldName,
|
|
250
253
|
manageListItemRemove: req.params?.manageListAction === MANAGE_LIST_ACTIONS.REMOVE,
|
|
254
|
+
isDynamicSection,
|
|
255
|
+
dynamicSectionId: isDynamicSection ? section.segment : undefined,
|
|
256
|
+
dynamicSectionFieldName: isDynamicSection ? section.fieldName : undefined,
|
|
251
257
|
data
|
|
252
258
|
});
|
|
253
259
|
|
|
@@ -264,7 +270,9 @@ export function buildSave(saveData, redirectToTaskListOnSuccess) {
|
|
|
264
270
|
// as question.shouldDisplay checks the response and is used to determine the next question
|
|
265
271
|
let answers = journeyResponse.answers;
|
|
266
272
|
if (question.isInManageListSection) {
|
|
267
|
-
answers =
|
|
273
|
+
answers = answerObjectForListItemSaving(journeyResponse, manageListQuestion, req.params.manageListItemId);
|
|
274
|
+
} else if (isDynamicSection) {
|
|
275
|
+
answers = answerObjectForListItemSaving(journeyResponse, section, section.segment);
|
|
268
276
|
}
|
|
269
277
|
for (const [k, v] of Object.entries(data?.answers || {})) {
|
|
270
278
|
if (typeof v === 'boolean') {
|