@planning-inspectorate/dynamic-forms 3.23.0 → 3.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -0
- package/package.json +1 -1
- package/src/controller.d.ts +31 -13
- package/src/controller.d.ts.map +1 -1
- package/src/controller.js +16 -5
- package/src/journey/journey-response.d.ts +6 -6
- package/src/journey/journey-response.d.ts.map +1 -1
- package/src/journey/journey-response.js +3 -3
- package/src/journey/journey.d.ts +12 -11
- package/src/journey/journey.d.ts.map +1 -1
- package/src/journey/journey.js +6 -5
- package/src/journey/journey.test.js +18 -0
- package/src/questions/options-question.d.ts +2 -2
- package/src/questions/options-question.d.ts.map +1 -1
- package/src/questions/options-question.js +1 -1
- package/typedefs/journey-types.d.ts +7 -0
package/README.md
CHANGED
|
@@ -39,6 +39,54 @@ All exports are named exports from the root module:
|
|
|
39
39
|
|
|
40
40
|
`import {COMPONENT_TYPES} from '@planning-inspectorate/dynamic-forms`
|
|
41
41
|
|
|
42
|
+
### Custom answer types
|
|
43
|
+
|
|
44
|
+
TypeScript consumers can supply an answer interface without an index signature. Both
|
|
45
|
+
`JourneyResponse` and `Journey` default to `JourneyAnswers` when no answer type is specified.
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { Journey, JourneyResponse } from '@planning-inspectorate/dynamic-forms';
|
|
49
|
+
import type { JourneyResponseLike } from '@planning-inspectorate/dynamic-forms';
|
|
50
|
+
|
|
51
|
+
interface HolidayAppViewModel {
|
|
52
|
+
holidayDestination: string;
|
|
53
|
+
holidayActivities: string[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const answers: HolidayAppViewModel = {
|
|
57
|
+
holidayDestination: 'beach',
|
|
58
|
+
holidayActivities: ['swimming', 'sightseeing']
|
|
59
|
+
};
|
|
60
|
+
const response = new JourneyResponse<HolidayAppViewModel>('holiday-journey', 'ref', answers);
|
|
61
|
+
const journey = new Journey<HolidayAppViewModel>({
|
|
62
|
+
journeyId: 'holiday-journey',
|
|
63
|
+
response,
|
|
64
|
+
makeBaseUrl: (currentResponse) => `/journey/${currentResponse.referenceId}`,
|
|
65
|
+
journeyTemplate: 'views/layout-journey.njk',
|
|
66
|
+
taskListTemplate: 'views/layout-check-your-answers.njk',
|
|
67
|
+
journeyTitle: 'Holiday Booking',
|
|
68
|
+
sections: []
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
journey.response.answers.holidayDestination; // string
|
|
72
|
+
|
|
73
|
+
// Plain objects are also accepted in the constructor and by setResponse.
|
|
74
|
+
const plainResponse: JourneyResponseLike<HolidayAppViewModel> = {
|
|
75
|
+
journeyId: 'holiday-journey',
|
|
76
|
+
referenceId: 'ref',
|
|
77
|
+
answers
|
|
78
|
+
};
|
|
79
|
+
journey.setResponse(plainResponse);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Answer types can also be inferred from the supplied response. `makeBaseUrl` and
|
|
83
|
+
`setResponse` retain the journey's answer type. Component, validator, controller,
|
|
84
|
+
and middleware APIs continue to use their existing default answer types.
|
|
85
|
+
|
|
86
|
+
Supply populated answers when using an interface with required properties:
|
|
87
|
+
`JourneyResponse` retains its existing empty-object fallback for null or missing
|
|
88
|
+
answers, which does not populate those properties.
|
|
89
|
+
|
|
42
90
|
### Components
|
|
43
91
|
|
|
44
92
|
Components available are exported via the `COMPONENT_TYPES` constant.
|
|
@@ -175,6 +223,41 @@ const update: SaveDataFn = async ({
|
|
|
175
223
|
}
|
|
176
224
|
```
|
|
177
225
|
|
|
226
|
+
`SaveDataFn` and `SaveParams` accept two optional generics: `TData` to type the `data` parameter, and `TLocals` to type `res.locals`. Both default to their current behaviour, so you only need to provide the ones you want to narrow. For example, to type `data`:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
type MyData = {
|
|
230
|
+
answers: {
|
|
231
|
+
myField: string;
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const update: SaveDataFn<MyData> = async ({data}) => {
|
|
236
|
+
const answers = data.answers; // typed as { myField: string }
|
|
237
|
+
|
|
238
|
+
console.log('saving', answers);
|
|
239
|
+
|
|
240
|
+
// TODO: map to database
|
|
241
|
+
// TODO: write to database
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
To type `res.locals` as well, pass `TLocals` as the second generic:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
type MyLocals = JourneyLocals & {
|
|
249
|
+
userId: string;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const update: SaveDataFn<MyData, MyLocals> = async ({data, res}) => {
|
|
253
|
+
const userId = res.locals.userId; // typed as string
|
|
254
|
+
|
|
255
|
+
console.log('saving', data.answers, 'for', userId);
|
|
256
|
+
|
|
257
|
+
// TODO: map to database
|
|
258
|
+
// TODO: write to database
|
|
259
|
+
}
|
|
260
|
+
```
|
|
178
261
|
|
|
179
262
|
### Conditions
|
|
180
263
|
|
package/package.json
CHANGED
package/src/controller.d.ts
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {{ journey: import('./journey/journey.js').Journey, journeyResponse: import('./journey/journey-response.js').JourneyResponse } & Record<string, any>} JourneyLocals
|
|
3
|
+
*/
|
|
1
4
|
/**
|
|
2
5
|
* @param {object} [viewData]
|
|
3
6
|
* @returns {import('express').Handler}
|
|
4
7
|
*/
|
|
5
8
|
export function buildList(viewData?: object): import("express").Handler;
|
|
6
9
|
/**
|
|
10
|
+
* @template {Record<string, any>} [TLocals=JourneyLocals]
|
|
7
11
|
* @param {import('express').Request} req
|
|
8
|
-
* @param {import('express').Response} res
|
|
12
|
+
* @param {import('express').Response<any, TLocals>} res
|
|
9
13
|
* @param {string} pageCaption
|
|
10
14
|
* @param {object} viewData
|
|
11
15
|
*/
|
|
12
|
-
export function list(req: import("express").Request, res: import("express").Response, pageCaption: string, viewData: object): Promise<void>;
|
|
16
|
+
export function list<TLocals extends Record<string, any> = JourneyLocals>(req: import("express").Request, res: import("express").Response<any, TLocals>, pageCaption: string, viewData: object): Promise<void>;
|
|
13
17
|
export function question(req: import("express-serve-static-core").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: import("express-serve-static-core").Response<any, Record<string, any>, number>, next: import("express-serve-static-core").NextFunction): unknown;
|
|
14
18
|
/**
|
|
19
|
+
* @template [TData=Object<string, any>]
|
|
20
|
+
* @template {Record<string, any>} [TLocals=JourneyLocals]
|
|
15
21
|
* @typedef {Object} SaveParams
|
|
16
22
|
* @property {import('express').Request} req
|
|
17
|
-
* @property {import('express').Response} res
|
|
23
|
+
* @property {import('express').Response<any, TLocals>} res
|
|
18
24
|
* @property {string} journeyId
|
|
19
25
|
* @property {string} referenceId
|
|
20
26
|
* @property {boolean} isManageListItem
|
|
@@ -23,17 +29,23 @@ export function question(req: import("express-serve-static-core").Request<import
|
|
|
23
29
|
* @property {boolean} isDynamicSection is this save action for a question within a DynamicSection?
|
|
24
30
|
* @property {string} [dynamicSectionId] if this is within a DynamicSection, what is the section ID (segment)
|
|
25
31
|
* @property {string} [dynamicSectionFieldName] if this is within a DynamicSection, what is the fieldName for the array?
|
|
26
|
-
* @property {
|
|
32
|
+
* @property {TData} data
|
|
27
33
|
*/
|
|
28
34
|
/**
|
|
29
|
-
* @
|
|
35
|
+
* @template [TData=Object<string, any>]
|
|
36
|
+
* @template {Record<string, any>} [TLocals=JourneyLocals]
|
|
37
|
+
* @typedef {(params: SaveParams<TData, TLocals>) => Promise<void>} SaveDataFn
|
|
30
38
|
*/
|
|
31
39
|
/**
|
|
32
|
-
* @
|
|
40
|
+
* @template [TData=Object<string, any>]
|
|
41
|
+
* @template {Record<string, any>} [TLocals=JourneyLocals]
|
|
42
|
+
* @param {SaveDataFn<TData, TLocals>} saveData
|
|
33
43
|
* @param {boolean} [redirectToTaskListOnSuccess] - optionally redirect to the task list after save instead of next question
|
|
34
44
|
* @returns {import('express').Handler}
|
|
35
45
|
*/
|
|
36
|
-
export function buildSave
|
|
46
|
+
export function buildSave<TData = {
|
|
47
|
+
[x: string]: any;
|
|
48
|
+
}, TLocals extends Record<string, any> = JourneyLocals>(saveData: SaveDataFn<TData, TLocals>, redirectToTaskListOnSuccess?: boolean): import("express").Handler;
|
|
37
49
|
export type SectionView = {
|
|
38
50
|
heading: string;
|
|
39
51
|
status: string;
|
|
@@ -54,9 +66,15 @@ export type RowView = {
|
|
|
54
66
|
items: import("#typedefs/question-types.d.ts").ActionView[];
|
|
55
67
|
} | undefined;
|
|
56
68
|
};
|
|
57
|
-
export type
|
|
69
|
+
export type JourneyLocals = {
|
|
70
|
+
journey: import("./journey/journey.js").Journey;
|
|
71
|
+
journeyResponse: import("./journey/journey-response.js").JourneyResponse;
|
|
72
|
+
} & Record<string, any>;
|
|
73
|
+
export type SaveParams<TData = {
|
|
74
|
+
[x: string]: any;
|
|
75
|
+
}, TLocals extends Record<string, any> = JourneyLocals> = {
|
|
58
76
|
req: import("express").Request;
|
|
59
|
-
res: import("express").Response
|
|
77
|
+
res: import("express").Response<any, TLocals>;
|
|
60
78
|
journeyId: string;
|
|
61
79
|
referenceId: string;
|
|
62
80
|
isManageListItem: boolean;
|
|
@@ -74,9 +92,9 @@ export type SaveParams = {
|
|
|
74
92
|
* if this is within a DynamicSection, what is the fieldName for the array?
|
|
75
93
|
*/
|
|
76
94
|
dynamicSectionFieldName?: string | undefined;
|
|
77
|
-
data:
|
|
78
|
-
[x: string]: any;
|
|
79
|
-
};
|
|
95
|
+
data: TData;
|
|
80
96
|
};
|
|
81
|
-
export type SaveDataFn =
|
|
97
|
+
export type SaveDataFn<TData = {
|
|
98
|
+
[x: string]: any;
|
|
99
|
+
}, TLocals extends Record<string, any> = JourneyLocals> = (params: SaveParams<TData, TLocals>) => Promise<void>;
|
|
82
100
|
//# sourceMappingURL=controller.d.ts.map
|
package/src/controller.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["controller.js"],"names":[],"mappings":"AAyDA;;GAEG;AAEH;;;GAGG;AACH,qCAHW,MAAM,GACJ,OAAO,SAAS,EAAE,OAAO,CAIrC;AAED;;;;;;GAMG;AACH,qBANoC,OAAO,SAA7B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAE,uBACvB,OAAO,SAAS,EAAE,OAAO,OACzB,OAAO,SAAS,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,eACxC,MAAM,YACN,MAAM,iBAmEhB;;AAmDD;;;;;;;;;;;;;;;GAeG;AAEH;;;;GAIG;AAEH;;;;;;GAMG;AACH,0BANc,KAAK;;GACiB,OAAO,SAA7B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAE,4BACvB,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,gCAC1B,OAAO,GACL,OAAO,SAAS,EAAE,OAAO,CA4FrC;;aA/Sa,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;;;4BAuC9D;IAAE,OAAO,EAAE,OAAO,sBAAsB,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,+BAA+B,EAAE,eAAe,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;uBAuIlJ,KAAK;;GACiB,OAAO,SAA7B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAE;SAEpB,OAAO,SAAS,EAAE,OAAO;SACzB,OAAO,SAAS,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;eACxC,MAAM;iBACN,MAAM;sBACN,OAAO;;;;;;sBAGP,OAAO;;;;;;;;;UAGP,KAAK;;uBAIL,KAAK;;GACiB,OAAO,SAA7B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAE,oBACrB,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC"}
|
package/src/controller.js
CHANGED
|
@@ -55,6 +55,10 @@ function buildSectionRowViewModel(key, value, action) {
|
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @typedef {{ journey: import('./journey/journey.js').Journey, journeyResponse: import('./journey/journey-response.js').JourneyResponse } & Record<string, any>} JourneyLocals
|
|
60
|
+
*/
|
|
61
|
+
|
|
58
62
|
/**
|
|
59
63
|
* @param {object} [viewData]
|
|
60
64
|
* @returns {import('express').Handler}
|
|
@@ -64,8 +68,9 @@ export function buildList(viewData = {}) {
|
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
/**
|
|
71
|
+
* @template {Record<string, any>} [TLocals=JourneyLocals]
|
|
67
72
|
* @param {import('express').Request} req
|
|
68
|
-
* @param {import('express').Response} res
|
|
73
|
+
* @param {import('express').Response<any, TLocals>} res
|
|
69
74
|
* @param {string} pageCaption
|
|
70
75
|
* @param {object} viewData
|
|
71
76
|
*/
|
|
@@ -186,9 +191,11 @@ export async function question(req, res) {
|
|
|
186
191
|
}
|
|
187
192
|
|
|
188
193
|
/**
|
|
194
|
+
* @template [TData=Object<string, any>]
|
|
195
|
+
* @template {Record<string, any>} [TLocals=JourneyLocals]
|
|
189
196
|
* @typedef {Object} SaveParams
|
|
190
197
|
* @property {import('express').Request} req
|
|
191
|
-
* @property {import('express').Response} res
|
|
198
|
+
* @property {import('express').Response<any, TLocals>} res
|
|
192
199
|
* @property {string} journeyId
|
|
193
200
|
* @property {string} referenceId
|
|
194
201
|
* @property {boolean} isManageListItem
|
|
@@ -197,15 +204,19 @@ export async function question(req, res) {
|
|
|
197
204
|
* @property {boolean} isDynamicSection is this save action for a question within a DynamicSection?
|
|
198
205
|
* @property {string} [dynamicSectionId] if this is within a DynamicSection, what is the section ID (segment)
|
|
199
206
|
* @property {string} [dynamicSectionFieldName] if this is within a DynamicSection, what is the fieldName for the array?
|
|
200
|
-
* @property {
|
|
207
|
+
* @property {TData} data
|
|
201
208
|
*/
|
|
202
209
|
|
|
203
210
|
/**
|
|
204
|
-
* @
|
|
211
|
+
* @template [TData=Object<string, any>]
|
|
212
|
+
* @template {Record<string, any>} [TLocals=JourneyLocals]
|
|
213
|
+
* @typedef {(params: SaveParams<TData, TLocals>) => Promise<void>} SaveDataFn
|
|
205
214
|
*/
|
|
206
215
|
|
|
207
216
|
/**
|
|
208
|
-
* @
|
|
217
|
+
* @template [TData=Object<string, any>]
|
|
218
|
+
* @template {Record<string, any>} [TLocals=JourneyLocals]
|
|
219
|
+
* @param {SaveDataFn<TData, TLocals>} saveData
|
|
209
220
|
* @param {boolean} [redirectToTaskListOnSuccess] - optionally redirect to the task list after save instead of next question
|
|
210
221
|
* @returns {import('express').Handler}
|
|
211
222
|
*/
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Defines a response to a journey, a set of Answers to the questions
|
|
3
3
|
* @class
|
|
4
|
-
* @template {object} [
|
|
4
|
+
* @template {object} [TAnswers=import("#typedefs/journey-types.d.ts").JourneyAnswers]
|
|
5
5
|
*/
|
|
6
|
-
export class JourneyResponse<
|
|
6
|
+
export class JourneyResponse<TAnswers extends object = import("#typedefs/journey-types.d.ts").JourneyAnswers> {
|
|
7
7
|
/**
|
|
8
8
|
* creates an instance of a JourneyResponse
|
|
9
9
|
* @param {string} journeyId
|
|
10
10
|
* @param {string} referenceId
|
|
11
|
-
* @param {
|
|
11
|
+
* @param {TAnswers | null} answers
|
|
12
12
|
* @param {string} [lpaCode]
|
|
13
13
|
*/
|
|
14
|
-
constructor(journeyId: string, referenceId: string, answers:
|
|
14
|
+
constructor(journeyId: string, referenceId: string, answers: TAnswers | null, lpaCode?: string);
|
|
15
15
|
/**
|
|
16
16
|
* @type {string} - reference id used in the url for the journey e.g. appeal id - provides a unique lookup for responses in combination with formId
|
|
17
17
|
*/
|
|
@@ -21,9 +21,9 @@ export class JourneyResponse<Answers extends object = import("#typedefs/journey-
|
|
|
21
21
|
*/
|
|
22
22
|
journeyId: string;
|
|
23
23
|
/**
|
|
24
|
-
* @type {
|
|
24
|
+
* @type {TAnswers} - answers to the journey
|
|
25
25
|
*/
|
|
26
|
-
answers:
|
|
26
|
+
answers: TAnswers;
|
|
27
27
|
LPACode: string | undefined;
|
|
28
28
|
}
|
|
29
29
|
//# sourceMappingURL=journey-response.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journey-response.d.ts","sourceRoot":"","sources":["journey-response.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,6BAFuB,
|
|
1
|
+
{"version":3,"file":"journey-response.d.ts","sourceRoot":"","sources":["journey-response.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,6BAFuB,QAAQ,SAAlB,MAAQ;IAkBpB;;;;;;OAMG;IACH,uBALW,MAAM,eACN,MAAM,WACN,QAAQ,GAAG,IAAI,YACf,MAAM,EAWhB;IA/BD;;OAEG;IACH,aAFU,MAAM,CAEJ;IAEZ;;OAEG;IACH,WAFU,MAAM,CAEN;IAEV;;OAEG;IACH,SAFU,QAAQ,CAEV;IAiBP,4BAAsB;CAEvB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Defines a response to a journey, a set of Answers to the questions
|
|
3
3
|
* @class
|
|
4
|
-
* @template {object} [
|
|
4
|
+
* @template {object} [TAnswers=import("#typedefs/journey-types.d.ts").JourneyAnswers]
|
|
5
5
|
*/
|
|
6
6
|
export class JourneyResponse {
|
|
7
7
|
/**
|
|
@@ -15,7 +15,7 @@ export class JourneyResponse {
|
|
|
15
15
|
journeyId;
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* @type {
|
|
18
|
+
* @type {TAnswers} - answers to the journey
|
|
19
19
|
*/
|
|
20
20
|
answers;
|
|
21
21
|
|
|
@@ -23,7 +23,7 @@ export class JourneyResponse {
|
|
|
23
23
|
* creates an instance of a JourneyResponse
|
|
24
24
|
* @param {string} journeyId
|
|
25
25
|
* @param {string} referenceId
|
|
26
|
-
* @param {
|
|
26
|
+
* @param {TAnswers | null} answers
|
|
27
27
|
* @param {string} [lpaCode]
|
|
28
28
|
*/
|
|
29
29
|
constructor(journeyId, referenceId, answers, lpaCode) {
|
package/src/journey/journey.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A journey (An entire set of questions required for a completion of a submission)
|
|
3
3
|
* @class
|
|
4
|
+
* @template {object} [TAnswers=import("#typedefs/journey-types.d.ts").JourneyAnswers]
|
|
4
5
|
*/
|
|
5
|
-
export class Journey {
|
|
6
|
+
export class Journey<TAnswers extends object = import("#typedefs/journey-types.d.ts").JourneyAnswers> {
|
|
6
7
|
/**
|
|
7
8
|
* creates an instance of a journey
|
|
8
9
|
* @param {object} options
|
|
9
10
|
* @param {string} options.journeyId - a unique, human-readable id for this journey
|
|
10
|
-
* @param {(response: import('
|
|
11
|
+
* @param {(response: import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>) => string} options.makeBaseUrl - base url of journey
|
|
11
12
|
* @param {string} [options.taskListUrl] - task list url - added to base url, can be left undefined
|
|
12
|
-
* @param {import('
|
|
13
|
+
* @param {import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>} options.response - user's response
|
|
13
14
|
* @param {string} options.journeyTemplate - template used for all views
|
|
14
15
|
* @param {string} options.taskListTemplate - path to njk view for listing page
|
|
15
16
|
* @param {string} [options.informationPageViewPath] - path to njk view for pdf summary page
|
|
@@ -20,9 +21,9 @@ export class Journey {
|
|
|
20
21
|
*/
|
|
21
22
|
constructor({ journeyId, makeBaseUrl, taskListUrl, response, journeyTemplate, taskListTemplate, informationPageViewPath, journeyTitle, returnToListing, sections, initialBackLink }: {
|
|
22
23
|
journeyId: string;
|
|
23
|
-
makeBaseUrl: (response: import("
|
|
24
|
+
makeBaseUrl: (response: import("#typedefs/journey-types.d.ts").JourneyResponseLike<TAnswers>) => string;
|
|
24
25
|
taskListUrl?: string | undefined;
|
|
25
|
-
response: import("
|
|
26
|
+
response: import("#typedefs/journey-types.d.ts").JourneyResponseLike<TAnswers>;
|
|
26
27
|
journeyTemplate: string;
|
|
27
28
|
taskListTemplate: string;
|
|
28
29
|
informationPageViewPath?: string | undefined;
|
|
@@ -35,12 +36,12 @@ export class Journey {
|
|
|
35
36
|
journeyId: string;
|
|
36
37
|
/** @type {Array.<import('../section.js').Section>} sections - sections within the journey */
|
|
37
38
|
sections: Array<import("../section.js").Section>;
|
|
38
|
-
/** @type {import('
|
|
39
|
-
response: import("
|
|
39
|
+
/** @type {import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>} response - the user's response to the journey so far */
|
|
40
|
+
response: import("#typedefs/journey-types.d.ts").JourneyResponseLike<TAnswers>;
|
|
40
41
|
/** @type {string} baseUrl - base url of the journey, gets prepended to question urls */
|
|
41
42
|
baseUrl: string;
|
|
42
|
-
/** @type {(journeyResponse: import('
|
|
43
|
-
makeBaseUrl: (journeyResponse: import("
|
|
43
|
+
/** @type {(journeyResponse: import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>) => string} makeBaseUrl - function to generate base url of the journey */
|
|
44
|
+
makeBaseUrl: (journeyResponse: import("#typedefs/journey-types.d.ts").JourneyResponseLike<TAnswers>) => string;
|
|
44
45
|
/** @type {string} taskListUrl - url that renders the task list */
|
|
45
46
|
taskListUrl: string;
|
|
46
47
|
/** @type {string} journeyTemplate - nunjucks template file used for */
|
|
@@ -138,9 +139,9 @@ export class Journey {
|
|
|
138
139
|
*/
|
|
139
140
|
isComplete(): boolean;
|
|
140
141
|
/**
|
|
141
|
-
* @param {import('
|
|
142
|
+
* @param {import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>} journeyResponse
|
|
142
143
|
*/
|
|
143
|
-
setResponse(journeyResponse: import("
|
|
144
|
+
setResponse(journeyResponse: import("#typedefs/journey-types.d.ts").JourneyResponseLike<TAnswers>): void;
|
|
144
145
|
#private;
|
|
145
146
|
}
|
|
146
147
|
//# sourceMappingURL=journey.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journey.d.ts","sourceRoot":"","sources":["journey.js"],"names":[],"mappings":"AAQA
|
|
1
|
+
{"version":3,"file":"journey.d.ts","sourceRoot":"","sources":["journey.js"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,qBAFuB,QAAQ,SAAlB,MAAQ;IA0BpB;;;;;;;;;;;;;;OAcG;IACH,qLAZG;QAAwB,SAAS,EAAzB,MAAM;QAC8F,WAAW,EAA/G,CAAC,QAAQ,EAAE,OAAO,8BAA8B,EAAE,mBAAmB,CAAC,QAAQ,CAAC,KAAK,MAAM;QACzE,WAAW;QACkD,QAAQ,EAAtF,OAAO,8BAA8B,EAAE,mBAAmB,CAAC,QAAQ,CAAC;QACpD,eAAe,EAA/B,MAAM;QACU,gBAAgB,EAAhC,MAAM;QACW,uBAAuB;QACxB,YAAY,EAA5B,MAAM;QACY,eAAe;QACU,QAAQ,EAAnD,OAAO,eAAe,EAAE,OAAO,EAAE;QAChB,eAAe;KAC1C,EAoDA;IAzFD,8EAA8E;IAC9E,WADW,MAAM,CACP;IACV,6FAA6F;IAC7F,UADW,KAAK,CAAE,OAAO,eAAe,EAAE,OAAO,CAAC,CACpC;IACd,wIAAwI;IACxI,UADW,OAAO,8BAA8B,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CACtE;IACT,wFAAwF;IACxF,SADW,MAAM,CACJ;IACb,2KAA2K;IAC3K,aADW,CAAC,eAAe,EAAE,OAAO,8BAA8B,EAAE,mBAAmB,CAAC,QAAQ,CAAC,KAAK,MAAM,CACrF;IACvB,kEAAkE;IAClE,aADW,MAAM,CACA;IACjB,uEAAuE;IACvE,iBADW,MAAM,CACI;IACrB,qFAAqF;IACrF,kBADW,MAAM,CACK;IACtB,4GAA4G;IAC5G,yBADW,MAAM,CACY;IAC7B,qFAAqF;IACrF,iBADW,OAAO,CACM;IACxB,2DAA2D;IAC3D,cADU,MAAM,CACH;IAmEZ,+BAA8C;IA2C/C;;;;OAIG;IACH,2BAHW,MAAM,GACJ,OAAO,eAAe,EAAE,OAAO,GAAG,SAAS,CAMvD;IAED;;;;;;OAMG;IACH,mCAFW,MAAM;;MAQhB;IA8BD;;;;OAIG;IACH,4BAHW,OAAO,8BAA8B,EAAE,WAAW,GAChD,OAAO,0BAA0B,EAAE,QAAQ,GAAG,SAAS,CAiBnE;IAED;;;;;;;OAOG;IACH,4CAJG;QAAoE,MAAM,EAAlE,OAAO,8BAA8B,EAAE,WAAW;QACU,kBAAkB;KACtF,GAAU,MAAM,GAAC,IAAI,CAWvB;IAED;;;;;;;;OAQG;IACH,4BALW,OAAO,SAAS,EAAE,QAAQ,UAC1B,OAAO,8BAA8B,EAAE,WAAW,kFAEhD,IAAI,CAKhB;IAED;;;;;;;;OAQG;IACH,2BANW,OAAO,8BAA8B,EAAE,WAAW,oCAE1D;QAA0B,OAAO;QACmC,kBAAkB;KACtF,GAAU,MAAM,GAAC,IAAI,CAyEvB;IAED;;;;;OAKG;IACH,wBAAyB,gBAJd,MAI4B,EAAE,iBAH9B,MAG6C,KAF3C,MAAM,CAqBjB;IAEF;;;;OAIG;IACH,sCAAuC,iBAH5B,MAG2C,KAFzC,MAAM,CAIjB;IAEF;;;;;;OAMG;IACH,0BAA2B,gBALhB,MAK8B,EAAE,iBAJhC,MAI+C,EAAE,UAHjD,MAGyD,KAFvD,MAAM,CAuBjB;IAEF;;;OAGG;IACH,cAFa,OAAO,CAInB;IAED;;OAEG;IACH,6BAFW,OAAO,8BAA8B,EAAE,mBAAmB,CAAC,QAAQ,CAAC,QAK9E;;CACD"}
|
package/src/journey/journey.js
CHANGED
|
@@ -9,17 +9,18 @@ import { MANAGE_LIST_ACTIONS } from '#src/components/manage-list/manage-list-act
|
|
|
9
9
|
/**
|
|
10
10
|
* A journey (An entire set of questions required for a completion of a submission)
|
|
11
11
|
* @class
|
|
12
|
+
* @template {object} [TAnswers=import("#typedefs/journey-types.d.ts").JourneyAnswers]
|
|
12
13
|
*/
|
|
13
14
|
export class Journey {
|
|
14
15
|
/** @type {string} journeyId - a unique, human-readable id for this journey */
|
|
15
16
|
journeyId;
|
|
16
17
|
/** @type {Array.<import('../section.js').Section>} sections - sections within the journey */
|
|
17
18
|
sections = [];
|
|
18
|
-
/** @type {import('
|
|
19
|
+
/** @type {import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>} response - the user's response to the journey so far */
|
|
19
20
|
response;
|
|
20
21
|
/** @type {string} baseUrl - base url of the journey, gets prepended to question urls */
|
|
21
22
|
baseUrl = '';
|
|
22
|
-
/** @type {(journeyResponse: import('
|
|
23
|
+
/** @type {(journeyResponse: import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>) => string} makeBaseUrl - function to generate base url of the journey */
|
|
23
24
|
makeBaseUrl = () => '';
|
|
24
25
|
/** @type {string} taskListUrl - url that renders the task list */
|
|
25
26
|
taskListUrl = '';
|
|
@@ -38,9 +39,9 @@ export class Journey {
|
|
|
38
39
|
* creates an instance of a journey
|
|
39
40
|
* @param {object} options
|
|
40
41
|
* @param {string} options.journeyId - a unique, human-readable id for this journey
|
|
41
|
-
* @param {(response: import('
|
|
42
|
+
* @param {(response: import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>) => string} options.makeBaseUrl - base url of journey
|
|
42
43
|
* @param {string} [options.taskListUrl] - task list url - added to base url, can be left undefined
|
|
43
|
-
* @param {import('
|
|
44
|
+
* @param {import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>} options.response - user's response
|
|
44
45
|
* @param {string} options.journeyTemplate - template used for all views
|
|
45
46
|
* @param {string} options.taskListTemplate - path to njk view for listing page
|
|
46
47
|
* @param {string} [options.informationPageViewPath] - path to njk view for pdf summary page
|
|
@@ -408,7 +409,7 @@ export class Journey {
|
|
|
408
409
|
}
|
|
409
410
|
|
|
410
411
|
/**
|
|
411
|
-
* @param {import('
|
|
412
|
+
* @param {import('#typedefs/journey-types.d.ts').JourneyResponseLike<TAnswers>} journeyResponse
|
|
412
413
|
*/
|
|
413
414
|
setResponse(journeyResponse) {
|
|
414
415
|
this.response = journeyResponse;
|
|
@@ -66,6 +66,24 @@ describe('Journey class', () => {
|
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
describe('constructor', () => {
|
|
69
|
+
it('should accept structural responses and retain them when updating the response', () => {
|
|
70
|
+
const response = {
|
|
71
|
+
journeyId: 'TEST',
|
|
72
|
+
referenceId: 'first',
|
|
73
|
+
answers: { holidayDestination: 'beach', holidayActivities: ['swimming', 'sightseeing'] }
|
|
74
|
+
};
|
|
75
|
+
constructorArgs.response = response;
|
|
76
|
+
constructorArgs.makeBaseUrl = (currentResponse) => `/journey/${currentResponse.referenceId}`;
|
|
77
|
+
const journey = new Journey(constructorArgs);
|
|
78
|
+
assert.strictEqual(journey.response, response);
|
|
79
|
+
assert.strictEqual(journey.baseUrl, '/journey/first');
|
|
80
|
+
|
|
81
|
+
const updatedResponse = { ...response, referenceId: 'second', LPACode: 'LPA' };
|
|
82
|
+
journey.setResponse(updatedResponse);
|
|
83
|
+
assert.strictEqual(journey.response, updatedResponse);
|
|
84
|
+
assert.strictEqual(journey.baseUrl, '/journey/second');
|
|
85
|
+
});
|
|
86
|
+
|
|
69
87
|
it('should throw if no arguments passed into constructor', () => {
|
|
70
88
|
assert.throws(() => new Journey({}), Error);
|
|
71
89
|
});
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* attributes?: Record<string, string>;
|
|
8
8
|
* behaviour?: 'exclusive';
|
|
9
9
|
* conditional?: {
|
|
10
|
-
* question
|
|
10
|
+
* question?: string;
|
|
11
11
|
* type: string;
|
|
12
12
|
* fieldName: string;
|
|
13
13
|
* inputClasses?: string;
|
|
@@ -57,7 +57,7 @@ export type Option = {
|
|
|
57
57
|
attributes?: Record<string, string>;
|
|
58
58
|
behaviour?: "exclusive";
|
|
59
59
|
conditional?: {
|
|
60
|
-
question
|
|
60
|
+
question?: string;
|
|
61
61
|
type: string;
|
|
62
62
|
fieldName: string;
|
|
63
63
|
inputClasses?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options-question.d.ts","sourceRoot":"","sources":["options-question.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;GAEG;AACH;;GAEG;AAEH;IAIC;;OAEG;IACH,oBAFW,yBAAyB,EAenC;IAnBD,4BAA4B;IAC5B,SADW,KAAK,CAAC,MAAM,CAAC,CAChB;IAiBP,yBAA+C;IAGhD;;;;;;;;OAQG;IACH,kCAPW,OAAO,UAAU,EAAE,OAAO,WAC1B,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,CAkDrE;CA2DD;;qBA1KY;IACR,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACb,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,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"options-question.d.ts","sourceRoot":"","sources":["options-question.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;GAEG;AACH;;GAEG;AAEH;IAIC;;OAEG;IACH,oBAFW,yBAAyB,EAenC;IAnBD,4BAA4B;IAC5B,SADW,KAAK,CAAC,MAAM,CAAC,CAChB;IAiBP,yBAA+C;IAGhD;;;;;;;;OAQG;IACH,kCAPW,OAAO,UAAU,EAAE,OAAO,WAC1B,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,CAkDrE;CA2DD;;qBA1KY;IACR,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACb,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,CAAC,EAAE;QACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,IAAI,CAAC,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,MAAM,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5D,MAAM,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC5D,CAAC;IACH,eAAe,CAAC,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;KACb,CAAA;CACH;+BAIU,OAAO,+BAA+B,EAAE,iBAAiB,GAAG;IAAE,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CAAE;wCAG/F,OAAO,+BAA+B,EAAE,kBAAkB,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAAE;yBAtC3E,eAAe"}
|
|
@@ -22,6 +22,13 @@ export interface JourneyAnswers {
|
|
|
22
22
|
[k: string]: unknown | ManageListAnswers[];
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export interface JourneyResponseLike<TAnswers = JourneyAnswers> {
|
|
26
|
+
journeyId: string;
|
|
27
|
+
referenceId: string;
|
|
28
|
+
answers: TAnswers;
|
|
29
|
+
LPACode: string | undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
25
32
|
export interface ManageListAnswers {
|
|
26
33
|
id: string;
|
|
27
34
|
[k: string]: unknown;
|