@defra/forms-engine-plugin 2.0.1 → 2.0.3
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/.server/server/plugins/engine/helpers.d.ts +1 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.d.ts +2 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js +1 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/index.d.ts +2 -1
- package/.server/server/plugins/engine/outputFormatters/index.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v1.d.ts +2 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v1.js +2 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v1.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +2 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js +3 -2
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +9 -2
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +4 -7
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/plugin.js +1 -2
- package/.server/server/plugins/engine/plugin.js.map +1 -1
- package/.server/server/plugins/engine/routes/questions.js +1 -1
- package/.server/server/plugins/engine/routes/questions.js.map +1 -1
- package/.server/server/plugins/engine/services/notifyService.d.ts +2 -1
- package/.server/server/plugins/engine/services/notifyService.js +2 -2
- package/.server/server/plugins/engine/services/notifyService.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +1 -1
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/services/cacheService.d.ts +0 -2
- package/.server/server/services/cacheService.js +1 -4
- package/.server/server/services/cacheService.js.map +1 -1
- package/.server/server/types.d.ts +2 -2
- package/.server/server/types.js.map +1 -1
- package/package.json +2 -2
- package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +3 -3
- package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -0
- package/src/server/plugins/engine/outputFormatters/index.ts +2 -0
- package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +40 -1
- package/src/server/plugins/engine/outputFormatters/machine/v1.ts +3 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +40 -1
- package/src/server/plugins/engine/outputFormatters/machine/v2.ts +4 -1
- package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +81 -16
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +13 -1
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +4 -4
- package/src/server/plugins/engine/plugin.ts +1 -2
- package/src/server/plugins/engine/routes/questions.ts +1 -1
- package/src/server/plugins/engine/services/notifyService.test.ts +26 -3
- package/src/server/plugins/engine/services/notifyService.ts +3 -1
- package/src/server/plugins/engine/types.ts +0 -1
- package/src/server/services/cacheService.test.ts +8 -2
- package/src/server/services/cacheService.ts +1 -13
- package/src/server/types.ts +2 -0
|
@@ -63,7 +63,7 @@ export declare function getCacheService(server: Server): import("../../services/
|
|
|
63
63
|
export declare function getSaveAndReturnHelpers(server: Server): {
|
|
64
64
|
keyGenerator: (request: FormRequest | FormRequestPayload | import("@hapi/hapi").Request<import("@hapi/hapi").ReqRefDefaults>) => string;
|
|
65
65
|
sessionHydrator: (request: FormRequest | FormRequestPayload | import("@hapi/hapi").Request<import("@hapi/hapi").ReqRefDefaults>) => Promise<import("~/src/server/plugins/engine/types.js").FormSubmissionState>;
|
|
66
|
-
sessionPersister: (
|
|
66
|
+
sessionPersister: (state: import("~/src/server/plugins/engine/types.js").FormSubmissionState, request: FormRequest | FormRequestPayload | import("@hapi/hapi").Request<import("@hapi/hapi").ReqRefDefaults>) => Promise<void>;
|
|
67
67
|
} | undefined;
|
|
68
68
|
export declare function getPluginOptions(server: Server): {
|
|
69
69
|
baseLayoutPath: string;
|
|
@@ -2,4 +2,5 @@ import { type SubmitResponsePayload } from '@defra/forms-model';
|
|
|
2
2
|
import { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js';
|
|
3
3
|
import { type FormModel } from '~/src/server/plugins/engine/models/index.js';
|
|
4
4
|
import { type DetailItem } from '~/src/server/plugins/engine/models/types.js';
|
|
5
|
-
|
|
5
|
+
import { type FormContext } from '~/src/server/plugins/engine/types.js';
|
|
6
|
+
export declare function format(_context: FormContext, items: DetailItem[], model: FormModel, submitResponse: SubmitResponsePayload, formStatus: ReturnType<typeof checkFormStatus>): string;
|
|
@@ -2,7 +2,7 @@ import { addDays, format as dateFormat } from 'date-fns';
|
|
|
2
2
|
import { config } from "../../../../../config/index.js";
|
|
3
3
|
import { escapeMarkdown, getAnswer } from "../../components/helpers.js";
|
|
4
4
|
const designerUrl = config.get('designerUrl');
|
|
5
|
-
export function format(items, model, submitResponse, formStatus) {
|
|
5
|
+
export function format(_context, items, model, submitResponse, formStatus) {
|
|
6
6
|
const {
|
|
7
7
|
files
|
|
8
8
|
} = submitResponse.result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v1.js","names":["addDays","format","dateFormat","config","escapeMarkdown","getAnswer","designerUrl","get","items","model","submitResponse","formStatus","files","result","formName","name","now","Date","formattedNow","fileExpiryDate","formattedExpiryDate","lines","push","isPreview","state","forEach","item","label","filename","fileId","repeaters","field","main","join"],"sources":["../../../../../../src/server/plugins/engine/outputFormatters/human/v1.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\nimport { addDays, format as dateFormat } from 'date-fns'\n\nimport { config } from '~/src/config/index.js'\nimport {\n escapeMarkdown,\n getAnswer\n} from '~/src/server/plugins/engine/components/helpers.js'\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { type DetailItem } from '~/src/server/plugins/engine/models/types.js'\n\nconst designerUrl = config.get('designerUrl')\n\nexport function format(\n items: DetailItem[],\n model: FormModel,\n submitResponse: SubmitResponsePayload,\n formStatus: ReturnType<typeof checkFormStatus>\n) {\n const { files } = submitResponse.result\n\n const formName = escapeMarkdown(model.name)\n\n /**\n * @todo Refactor this below but the code to\n * generate the question and answers works for now\n */\n const now = new Date()\n const formattedNow = `${dateFormat(now, 'h:mmaaa')} on ${dateFormat(now, 'd MMMM yyyy')}`\n\n const fileExpiryDate = addDays(now, 90)\n const formattedExpiryDate = `${dateFormat(fileExpiryDate, 'h:mmaaa')} on ${dateFormat(fileExpiryDate, 'eeee d MMMM yyyy')}`\n\n const lines: string[] = []\n\n lines.push(\n `^ For security reasons, the links in this email expire at ${escapeMarkdown(formattedExpiryDate)}\\n`\n )\n\n if (formStatus.isPreview) {\n lines.push(`This is a test of the ${formName} ${formStatus.state} form.\\n`)\n }\n\n lines.push(`${formName} form received at ${escapeMarkdown(formattedNow)}.\\n`)\n lines.push('---\\n')\n\n items.forEach((item) => {\n const label = escapeMarkdown(item.label)\n\n lines.push(`## ${label}\\n`)\n\n if ('subItems' in item) {\n const filename = escapeMarkdown(`Download ${label} (CSV)`)\n const fileId = files.repeaters[item.name]\n\n lines.push(`[${filename}](${designerUrl}/file-download/${fileId})\\n`)\n } else {\n lines.push(\n getAnswer(item.field, item.state, {\n format: 'email'\n })\n )\n }\n\n lines.push('---\\n')\n })\n\n const filename = escapeMarkdown('Download main form (CSV)')\n lines.push(`[${filename}](${designerUrl}/file-download/${files.main})\\n`)\n\n return lines.join('\\n')\n}\n"],"mappings":"AACA,SAASA,OAAO,EAAEC,MAAM,IAAIC,UAAU,QAAQ,UAAU;AAExD,SAASC,MAAM;AACf,SACEC,cAAc,EACdC,SAAS;
|
|
1
|
+
{"version":3,"file":"v1.js","names":["addDays","format","dateFormat","config","escapeMarkdown","getAnswer","designerUrl","get","_context","items","model","submitResponse","formStatus","files","result","formName","name","now","Date","formattedNow","fileExpiryDate","formattedExpiryDate","lines","push","isPreview","state","forEach","item","label","filename","fileId","repeaters","field","main","join"],"sources":["../../../../../../src/server/plugins/engine/outputFormatters/human/v1.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\nimport { addDays, format as dateFormat } from 'date-fns'\n\nimport { config } from '~/src/config/index.js'\nimport {\n escapeMarkdown,\n getAnswer\n} from '~/src/server/plugins/engine/components/helpers.js'\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { type DetailItem } from '~/src/server/plugins/engine/models/types.js'\nimport { type FormContext } from '~/src/server/plugins/engine/types.js'\n\nconst designerUrl = config.get('designerUrl')\n\nexport function format(\n _context: FormContext,\n items: DetailItem[],\n model: FormModel,\n submitResponse: SubmitResponsePayload,\n formStatus: ReturnType<typeof checkFormStatus>\n) {\n const { files } = submitResponse.result\n\n const formName = escapeMarkdown(model.name)\n\n /**\n * @todo Refactor this below but the code to\n * generate the question and answers works for now\n */\n const now = new Date()\n const formattedNow = `${dateFormat(now, 'h:mmaaa')} on ${dateFormat(now, 'd MMMM yyyy')}`\n\n const fileExpiryDate = addDays(now, 90)\n const formattedExpiryDate = `${dateFormat(fileExpiryDate, 'h:mmaaa')} on ${dateFormat(fileExpiryDate, 'eeee d MMMM yyyy')}`\n\n const lines: string[] = []\n\n lines.push(\n `^ For security reasons, the links in this email expire at ${escapeMarkdown(formattedExpiryDate)}\\n`\n )\n\n if (formStatus.isPreview) {\n lines.push(`This is a test of the ${formName} ${formStatus.state} form.\\n`)\n }\n\n lines.push(`${formName} form received at ${escapeMarkdown(formattedNow)}.\\n`)\n lines.push('---\\n')\n\n items.forEach((item) => {\n const label = escapeMarkdown(item.label)\n\n lines.push(`## ${label}\\n`)\n\n if ('subItems' in item) {\n const filename = escapeMarkdown(`Download ${label} (CSV)`)\n const fileId = files.repeaters[item.name]\n\n lines.push(`[${filename}](${designerUrl}/file-download/${fileId})\\n`)\n } else {\n lines.push(\n getAnswer(item.field, item.state, {\n format: 'email'\n })\n )\n }\n\n lines.push('---\\n')\n })\n\n const filename = escapeMarkdown('Download main form (CSV)')\n lines.push(`[${filename}](${designerUrl}/file-download/${files.main})\\n`)\n\n return lines.join('\\n')\n}\n"],"mappings":"AACA,SAASA,OAAO,EAAEC,MAAM,IAAIC,UAAU,QAAQ,UAAU;AAExD,SAASC,MAAM;AACf,SACEC,cAAc,EACdC,SAAS;AAOX,MAAMC,WAAW,GAAGH,MAAM,CAACI,GAAG,CAAC,aAAa,CAAC;AAE7C,OAAO,SAASN,MAAMA,CACpBO,QAAqB,EACrBC,KAAmB,EACnBC,KAAgB,EAChBC,cAAqC,EACrCC,UAA8C,EAC9C;EACA,MAAM;IAAEC;EAAM,CAAC,GAAGF,cAAc,CAACG,MAAM;EAEvC,MAAMC,QAAQ,GAAGX,cAAc,CAACM,KAAK,CAACM,IAAI,CAAC;;EAE3C;AACF;AACA;AACA;EACE,MAAMC,GAAG,GAAG,IAAIC,IAAI,CAAC,CAAC;EACtB,MAAMC,YAAY,GAAG,GAAGjB,UAAU,CAACe,GAAG,EAAE,SAAS,CAAC,OAAOf,UAAU,CAACe,GAAG,EAAE,aAAa,CAAC,EAAE;EAEzF,MAAMG,cAAc,GAAGpB,OAAO,CAACiB,GAAG,EAAE,EAAE,CAAC;EACvC,MAAMI,mBAAmB,GAAG,GAAGnB,UAAU,CAACkB,cAAc,EAAE,SAAS,CAAC,OAAOlB,UAAU,CAACkB,cAAc,EAAE,kBAAkB,CAAC,EAAE;EAE3H,MAAME,KAAe,GAAG,EAAE;EAE1BA,KAAK,CAACC,IAAI,CACR,6DAA6DnB,cAAc,CAACiB,mBAAmB,CAAC,IAClG,CAAC;EAED,IAAIT,UAAU,CAACY,SAAS,EAAE;IACxBF,KAAK,CAACC,IAAI,CAAC,yBAAyBR,QAAQ,IAAIH,UAAU,CAACa,KAAK,UAAU,CAAC;EAC7E;EAEAH,KAAK,CAACC,IAAI,CAAC,GAAGR,QAAQ,qBAAqBX,cAAc,CAACe,YAAY,CAAC,KAAK,CAAC;EAC7EG,KAAK,CAACC,IAAI,CAAC,OAAO,CAAC;EAEnBd,KAAK,CAACiB,OAAO,CAAEC,IAAI,IAAK;IACtB,MAAMC,KAAK,GAAGxB,cAAc,CAACuB,IAAI,CAACC,KAAK,CAAC;IAExCN,KAAK,CAACC,IAAI,CAAC,MAAMK,KAAK,IAAI,CAAC;IAE3B,IAAI,UAAU,IAAID,IAAI,EAAE;MACtB,MAAME,QAAQ,GAAGzB,cAAc,CAAC,YAAYwB,KAAK,QAAQ,CAAC;MAC1D,MAAME,MAAM,GAAGjB,KAAK,CAACkB,SAAS,CAACJ,IAAI,CAACX,IAAI,CAAC;MAEzCM,KAAK,CAACC,IAAI,CAAC,IAAIM,QAAQ,KAAKvB,WAAW,kBAAkBwB,MAAM,KAAK,CAAC;IACvE,CAAC,MAAM;MACLR,KAAK,CAACC,IAAI,CACRlB,SAAS,CAACsB,IAAI,CAACK,KAAK,EAAEL,IAAI,CAACF,KAAK,EAAE;QAChCxB,MAAM,EAAE;MACV,CAAC,CACH,CAAC;IACH;IAEAqB,KAAK,CAACC,IAAI,CAAC,OAAO,CAAC;EACrB,CAAC,CAAC;EAEF,MAAMM,QAAQ,GAAGzB,cAAc,CAAC,0BAA0B,CAAC;EAC3DkB,KAAK,CAACC,IAAI,CAAC,IAAIM,QAAQ,KAAKvB,WAAW,kBAAkBO,KAAK,CAACoB,IAAI,KAAK,CAAC;EAEzE,OAAOX,KAAK,CAACY,IAAI,CAAC,IAAI,CAAC;AACzB","ignoreList":[]}
|
|
@@ -2,6 +2,7 @@ import { type SubmitResponsePayload } from '@defra/forms-model';
|
|
|
2
2
|
import { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js';
|
|
3
3
|
import { type FormModel } from '~/src/server/plugins/engine/models/index.js';
|
|
4
4
|
import { type DetailItem } from '~/src/server/plugins/engine/models/types.js';
|
|
5
|
-
|
|
5
|
+
import { type FormContext } from '~/src/server/plugins/engine/types.js';
|
|
6
|
+
type Formatter = (context: FormContext, items: DetailItem[], model: FormModel, submitResponse: SubmitResponsePayload, formStatus: ReturnType<typeof checkFormStatus>) => string;
|
|
6
7
|
export declare function getFormatter(audience: string, version: string): Formatter;
|
|
7
8
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["format","formatHumanV1","formatMachineV1","formatMachineV2","formatters","human","machine","getFormatter","audience","version","versions","Error","formatter"],"sources":["../../../../../src/server/plugins/engine/outputFormatters/index.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\n\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { type DetailItem } from '~/src/server/plugins/engine/models/types.js'\nimport { format as formatHumanV1 } from '~/src/server/plugins/engine/outputFormatters/human/v1.js'\nimport { format as formatMachineV1 } from '~/src/server/plugins/engine/outputFormatters/machine/v1.js'\nimport { format as formatMachineV2 } from '~/src/server/plugins/engine/outputFormatters/machine/v2.js'\n\ntype Formatter = (\n items: DetailItem[],\n model: FormModel,\n submitResponse: SubmitResponsePayload,\n formStatus: ReturnType<typeof checkFormStatus>\n) => string\n\nconst formatters: Record<\n string,\n Record<string, Formatter | undefined> | undefined\n> = {\n human: {\n '1': formatHumanV1\n },\n machine: {\n '1': formatMachineV1,\n '2': formatMachineV2\n }\n}\n\nexport function getFormatter(audience: string, version: string) {\n const versions = formatters[audience]\n\n if (!versions) {\n throw new Error('Unknown audience')\n }\n\n const formatter = versions[version]\n\n if (!formatter) {\n throw new Error('Unknown version')\n }\n\n return formatter\n}\n"],"mappings":"AAKA,SAASA,MAAM,IAAIC,aAAa;AAChC,SAASD,MAAM,IAAIE,eAAe;AAClC,SAASF,MAAM,IAAIG,eAAe;
|
|
1
|
+
{"version":3,"file":"index.js","names":["format","formatHumanV1","formatMachineV1","formatMachineV2","formatters","human","machine","getFormatter","audience","version","versions","Error","formatter"],"sources":["../../../../../src/server/plugins/engine/outputFormatters/index.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\n\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { type DetailItem } from '~/src/server/plugins/engine/models/types.js'\nimport { format as formatHumanV1 } from '~/src/server/plugins/engine/outputFormatters/human/v1.js'\nimport { format as formatMachineV1 } from '~/src/server/plugins/engine/outputFormatters/machine/v1.js'\nimport { format as formatMachineV2 } from '~/src/server/plugins/engine/outputFormatters/machine/v2.js'\nimport { type FormContext } from '~/src/server/plugins/engine/types.js'\n\ntype Formatter = (\n context: FormContext,\n items: DetailItem[],\n model: FormModel,\n submitResponse: SubmitResponsePayload,\n formStatus: ReturnType<typeof checkFormStatus>\n) => string\n\nconst formatters: Record<\n string,\n Record<string, Formatter | undefined> | undefined\n> = {\n human: {\n '1': formatHumanV1\n },\n machine: {\n '1': formatMachineV1,\n '2': formatMachineV2\n }\n}\n\nexport function getFormatter(audience: string, version: string) {\n const versions = formatters[audience]\n\n if (!versions) {\n throw new Error('Unknown audience')\n }\n\n const formatter = versions[version]\n\n if (!formatter) {\n throw new Error('Unknown version')\n }\n\n return formatter\n}\n"],"mappings":"AAKA,SAASA,MAAM,IAAIC,aAAa;AAChC,SAASD,MAAM,IAAIE,eAAe;AAClC,SAASF,MAAM,IAAIG,eAAe;AAWlC,MAAMC,UAGL,GAAG;EACFC,KAAK,EAAE;IACL,GAAG,EAAEJ;EACP,CAAC;EACDK,OAAO,EAAE;IACP,GAAG,EAAEJ,eAAe;IACpB,GAAG,EAAEC;EACP;AACF,CAAC;AAED,OAAO,SAASI,YAAYA,CAACC,QAAgB,EAAEC,OAAe,EAAE;EAC9D,MAAMC,QAAQ,GAAGN,UAAU,CAACI,QAAQ,CAAC;EAErC,IAAI,CAACE,QAAQ,EAAE;IACb,MAAM,IAAIC,KAAK,CAAC,kBAAkB,CAAC;EACrC;EAEA,MAAMC,SAAS,GAAGF,QAAQ,CAACD,OAAO,CAAC;EAEnC,IAAI,CAACG,SAAS,EAAE;IACd,MAAM,IAAID,KAAK,CAAC,iBAAiB,CAAC;EACpC;EAEA,OAAOC,SAAS;AAClB","ignoreList":[]}
|
|
@@ -2,4 +2,5 @@ import { type SubmitResponsePayload } from '@defra/forms-model';
|
|
|
2
2
|
import { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js';
|
|
3
3
|
import { type FormModel } from '~/src/server/plugins/engine/models/index.js';
|
|
4
4
|
import { type DetailItem } from '~/src/server/plugins/engine/models/types.js';
|
|
5
|
-
|
|
5
|
+
import { type FormContext } from '~/src/server/plugins/engine/types.js';
|
|
6
|
+
export declare function format(context: FormContext, items: DetailItem[], model: FormModel, _submitResponse: SubmitResponsePayload, _formStatus: ReturnType<typeof checkFormStatus>): string;
|
|
@@ -2,13 +2,14 @@ import { config } from "../../../../../config/index.js";
|
|
|
2
2
|
import { getAnswer } from "../../components/helpers.js";
|
|
3
3
|
import { FileUploadField } from "../../components/index.js";
|
|
4
4
|
const designerUrl = config.get('designerUrl');
|
|
5
|
-
export function format(items, model, _submitResponse, _formStatus) {
|
|
5
|
+
export function format(context, items, model, _submitResponse, _formStatus) {
|
|
6
6
|
const now = new Date();
|
|
7
7
|
const categorisedData = categoriseData(items);
|
|
8
8
|
const data = {
|
|
9
9
|
meta: {
|
|
10
10
|
schemaVersion: '1',
|
|
11
11
|
timestamp: now.toISOString(),
|
|
12
|
+
referenceNumber: context.referenceNumber,
|
|
12
13
|
definition: model.def
|
|
13
14
|
},
|
|
14
15
|
data: categorisedData
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v1.js","names":["config","getAnswer","FileUploadField","designerUrl","get","format","items","model","_submitResponse","_formStatus","now","Date","categorisedData","categoriseData","data","meta","schemaVersion","timestamp","toISOString","definition","def","body","JSON","stringify","output","main","repeaters","files","forEach","item","name","extractRepeaters","isFileUploadFieldItem","extractFileUploads","field","state","subItems","inputRepeaterItem","outputRepeaterItem","repeaterComponent","push","fileUploadState","getContextValueFromState","map","fileId","userDownloadLink"],"sources":["../../../../../../src/server/plugins/engine/outputFormatters/machine/v1.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { getAnswer } from '~/src/server/plugins/engine/components/helpers.js'\nimport { FileUploadField } from '~/src/server/plugins/engine/components/index.js'\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport {\n type DetailItem,\n type DetailItemField,\n type DetailItemRepeat\n} from '~/src/server/plugins/engine/models/types.js'\n\nconst designerUrl = config.get('designerUrl')\n\nexport function format(\n items: DetailItem[],\n model: FormModel,\n _submitResponse: SubmitResponsePayload,\n _formStatus: ReturnType<typeof checkFormStatus>\n) {\n const now = new Date()\n\n const categorisedData = categoriseData(items)\n\n const data = {\n meta: {\n schemaVersion: '1',\n timestamp: now.toISOString(),\n definition: model.def\n },\n data: categorisedData\n }\n\n const body = JSON.stringify(data)\n\n return body\n}\n\n/**\n * Categories the form submission data into the \"main\" body and \"repeaters\".\n *\n * {\n * main: {\n * componentName: 'componentValue',\n * },\n * repeaters: {\n * repeaterName: [\n * {\n * componentName: 'componentValue'\n * }\n * ]\n * },\n * files: {\n * fileComponentName: [\n * {\n * fileId: '123-456-789',\n * link: 'https://forms-designer/file-download/123-456-789'\n * }\n * ]\n * }\n * }\n */\nfunction categoriseData(items: DetailItem[]) {\n const output: {\n main: Record<string, string>\n repeaters: Record<string, Record<string, string>[]>\n files: Record<string, Record<string, string>[]>\n } = { main: {}, repeaters: {}, files: {} }\n\n items.forEach((item) => {\n if ('subItems' in item) {\n output.repeaters[item.name] = extractRepeaters(item)\n } else if (isFileUploadFieldItem(item)) {\n output.files[item.name] = extractFileUploads(item)\n } else {\n output.main[item.name] = getAnswer(item.field, item.state, {\n format: 'data'\n })\n }\n })\n\n return output\n}\n\n/**\n * Returns the \"repeaters\" section of the response body\n * @param item - the repeater item\n * @returns the repeater item\n */\nfunction extractRepeaters(item: DetailItemRepeat) {\n const repeaters: Record<string, string>[] = []\n\n item.subItems.forEach((inputRepeaterItem) => {\n const outputRepeaterItem: Record<string, string> = {}\n\n inputRepeaterItem.forEach((repeaterComponent) => {\n outputRepeaterItem[repeaterComponent.name] = getAnswer(\n repeaterComponent.field,\n repeaterComponent.state,\n {\n format: 'data'\n }\n )\n })\n\n repeaters.push(outputRepeaterItem)\n })\n\n return repeaters\n}\n\n/**\n * Returns the \"files\" section of the response body\n * @param item - the file upload item in the form\n * @returns the file upload data\n */\nfunction extractFileUploads(item: FileUploadFieldDetailitem) {\n const fileUploadState = item.field.getContextValueFromState(item.state) ?? []\n\n return fileUploadState.map((fileId) => {\n return {\n fileId,\n userDownloadLink: `${designerUrl}/file-download/${fileId}`\n }\n })\n}\n\nfunction isFileUploadFieldItem(\n item: DetailItemField\n): item is FileUploadFieldDetailitem {\n return item.field instanceof FileUploadField\n}\n\n/**\n * A detail item specifically for files\n */\ntype FileUploadFieldDetailitem = Omit<DetailItemField, 'field'> & {\n field: FileUploadField\n}\n"],"mappings":"AAEA,SAASA,MAAM;AACf,SAASC,SAAS;AAClB,SAASC,eAAe;
|
|
1
|
+
{"version":3,"file":"v1.js","names":["config","getAnswer","FileUploadField","designerUrl","get","format","context","items","model","_submitResponse","_formStatus","now","Date","categorisedData","categoriseData","data","meta","schemaVersion","timestamp","toISOString","referenceNumber","definition","def","body","JSON","stringify","output","main","repeaters","files","forEach","item","name","extractRepeaters","isFileUploadFieldItem","extractFileUploads","field","state","subItems","inputRepeaterItem","outputRepeaterItem","repeaterComponent","push","fileUploadState","getContextValueFromState","map","fileId","userDownloadLink"],"sources":["../../../../../../src/server/plugins/engine/outputFormatters/machine/v1.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { getAnswer } from '~/src/server/plugins/engine/components/helpers.js'\nimport { FileUploadField } from '~/src/server/plugins/engine/components/index.js'\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport {\n type DetailItem,\n type DetailItemField,\n type DetailItemRepeat\n} from '~/src/server/plugins/engine/models/types.js'\nimport { type FormContext } from '~/src/server/plugins/engine/types.js'\n\nconst designerUrl = config.get('designerUrl')\n\nexport function format(\n context: FormContext,\n items: DetailItem[],\n model: FormModel,\n _submitResponse: SubmitResponsePayload,\n _formStatus: ReturnType<typeof checkFormStatus>\n) {\n const now = new Date()\n\n const categorisedData = categoriseData(items)\n\n const data = {\n meta: {\n schemaVersion: '1',\n timestamp: now.toISOString(),\n referenceNumber: context.referenceNumber,\n definition: model.def\n },\n data: categorisedData\n }\n\n const body = JSON.stringify(data)\n\n return body\n}\n\n/**\n * Categories the form submission data into the \"main\" body and \"repeaters\".\n *\n * {\n * main: {\n * componentName: 'componentValue',\n * },\n * repeaters: {\n * repeaterName: [\n * {\n * componentName: 'componentValue'\n * }\n * ]\n * },\n * files: {\n * fileComponentName: [\n * {\n * fileId: '123-456-789',\n * link: 'https://forms-designer/file-download/123-456-789'\n * }\n * ]\n * }\n * }\n */\nfunction categoriseData(items: DetailItem[]) {\n const output: {\n main: Record<string, string>\n repeaters: Record<string, Record<string, string>[]>\n files: Record<string, Record<string, string>[]>\n } = { main: {}, repeaters: {}, files: {} }\n\n items.forEach((item) => {\n if ('subItems' in item) {\n output.repeaters[item.name] = extractRepeaters(item)\n } else if (isFileUploadFieldItem(item)) {\n output.files[item.name] = extractFileUploads(item)\n } else {\n output.main[item.name] = getAnswer(item.field, item.state, {\n format: 'data'\n })\n }\n })\n\n return output\n}\n\n/**\n * Returns the \"repeaters\" section of the response body\n * @param item - the repeater item\n * @returns the repeater item\n */\nfunction extractRepeaters(item: DetailItemRepeat) {\n const repeaters: Record<string, string>[] = []\n\n item.subItems.forEach((inputRepeaterItem) => {\n const outputRepeaterItem: Record<string, string> = {}\n\n inputRepeaterItem.forEach((repeaterComponent) => {\n outputRepeaterItem[repeaterComponent.name] = getAnswer(\n repeaterComponent.field,\n repeaterComponent.state,\n {\n format: 'data'\n }\n )\n })\n\n repeaters.push(outputRepeaterItem)\n })\n\n return repeaters\n}\n\n/**\n * Returns the \"files\" section of the response body\n * @param item - the file upload item in the form\n * @returns the file upload data\n */\nfunction extractFileUploads(item: FileUploadFieldDetailitem) {\n const fileUploadState = item.field.getContextValueFromState(item.state) ?? []\n\n return fileUploadState.map((fileId) => {\n return {\n fileId,\n userDownloadLink: `${designerUrl}/file-download/${fileId}`\n }\n })\n}\n\nfunction isFileUploadFieldItem(\n item: DetailItemField\n): item is FileUploadFieldDetailitem {\n return item.field instanceof FileUploadField\n}\n\n/**\n * A detail item specifically for files\n */\ntype FileUploadFieldDetailitem = Omit<DetailItemField, 'field'> & {\n field: FileUploadField\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -2,4 +2,5 @@ import { type SubmitResponsePayload } from '@defra/forms-model';
|
|
|
2
2
|
import { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js';
|
|
3
3
|
import { type FormModel } from '~/src/server/plugins/engine/models/index.js';
|
|
4
4
|
import { type DetailItem } from '~/src/server/plugins/engine/models/types.js';
|
|
5
|
-
|
|
5
|
+
import { type FormContext } from '~/src/server/plugins/engine/types.js';
|
|
6
|
+
export declare function format(context: FormContext, items: DetailItem[], model: FormModel, _submitResponse: SubmitResponsePayload, _formStatus: ReturnType<typeof checkFormStatus>): string;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { config } from "../../../../../config/index.js";
|
|
2
2
|
import { FileUploadField } from "../../components/index.js";
|
|
3
3
|
const designerUrl = config.get('designerUrl');
|
|
4
|
-
export function format(items, model, _submitResponse, _formStatus) {
|
|
4
|
+
export function format(context, items, model, _submitResponse, _formStatus) {
|
|
5
5
|
const now = new Date();
|
|
6
6
|
const categorisedData = categoriseData(items);
|
|
7
7
|
const data = {
|
|
8
8
|
meta: {
|
|
9
9
|
schemaVersion: '2',
|
|
10
10
|
timestamp: now.toISOString(),
|
|
11
|
-
definition: model.def
|
|
11
|
+
definition: model.def,
|
|
12
|
+
referenceNumber: context.referenceNumber
|
|
12
13
|
},
|
|
13
14
|
data: categorisedData
|
|
14
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.js","names":["config","FileUploadField","designerUrl","get","format","items","model","_submitResponse","_formStatus","now","Date","categorisedData","categoriseData","data","meta","schemaVersion","timestamp","toISOString","definition","def","body","JSON","stringify","output","main","repeaters","files","forEach","item","name","state","extractRepeaters","isFileUploadFieldItem","extractFileUploads","field","getFormValueFromState","subItems","inputRepeaterItem","outputRepeaterItem","repeaterComponent","push","fileUploadState","getContextValueFromState","map","fileId","userDownloadLink"],"sources":["../../../../../../src/server/plugins/engine/outputFormatters/machine/v2.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { type UkAddressState } from '~/src/server/plugins/engine/components/UkAddressField.js'\nimport { FileUploadField } from '~/src/server/plugins/engine/components/index.js'\nimport {\n type DatePartsState,\n type MonthYearState\n} from '~/src/server/plugins/engine/components/types.js'\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport {\n type DetailItem,\n type DetailItemField,\n type DetailItemRepeat\n} from '~/src/server/plugins/engine/models/types.js'\nimport {\n type FormPayload,\n type FormValue\n} from '~/src/server/plugins/engine/types.js'\n\nconst designerUrl = config.get('designerUrl')\n\nexport function format(\n items: DetailItem[],\n model: FormModel,\n _submitResponse: SubmitResponsePayload,\n _formStatus: ReturnType<typeof checkFormStatus>\n) {\n const now = new Date()\n\n const categorisedData = categoriseData(items)\n\n const data = {\n meta: {\n schemaVersion: '2',\n timestamp: now.toISOString(),\n definition: model.def\n },\n data: categorisedData\n }\n\n const body = JSON.stringify(data)\n\n return body\n}\n\n/**\n * Categories the form submission data into the \"main\" body and \"repeaters\".\n *\n * {\n * main: {\n * componentName: 'componentValue',\n * },\n * repeaters: {\n * repeaterName: [\n * {\n * textComponentName: 'componentValue'\n * },\n * {\n * richComponentName: { foo: 'bar', 'baz': true }\n * }\n * ]\n * },\n * files: {\n * fileComponentName: [\n * {\n * fileId: '123-456-789',\n * link: 'https://forms-designer/file-download/123-456-789'\n * }\n * ]\n * }\n * }\n */\nfunction categoriseData(items: DetailItem[]) {\n const output: {\n main: Record<string, RichFormValue>\n repeaters: Record<string, Record<string, RichFormValue>[]>\n files: Record<string, Record<string, string>[]>\n } = { main: {}, repeaters: {}, files: {} }\n\n items.forEach((item) => {\n const { name, state } = item\n\n if ('subItems' in item) {\n output.repeaters[name] = extractRepeaters(item)\n } else if (isFileUploadFieldItem(item)) {\n output.files[name] = extractFileUploads(item)\n } else {\n output.main[name] = item.field.getFormValueFromState(state)\n }\n })\n\n return output\n}\n\n/**\n * Returns the \"repeaters\" section of the response body\n * @param item - the repeater item\n * @returns the repeater item\n */\nfunction extractRepeaters(item: DetailItemRepeat) {\n const repeaters: Record<string, RichFormValue>[] = []\n\n item.subItems.forEach((inputRepeaterItem) => {\n const outputRepeaterItem: Record<string, RichFormValue> = {}\n\n inputRepeaterItem.forEach((repeaterComponent) => {\n const { field, state } = repeaterComponent\n\n outputRepeaterItem[repeaterComponent.name] =\n field.getFormValueFromState(state)\n })\n\n repeaters.push(outputRepeaterItem)\n })\n\n return repeaters\n}\n\n/**\n * Returns the \"files\" section of the response body\n * @param item - the file upload item in the form\n * @returns the file upload data\n */\nfunction extractFileUploads(item: FileUploadFieldDetailitem) {\n const fileUploadState = item.field.getContextValueFromState(item.state) ?? []\n\n return fileUploadState.map((fileId) => {\n return {\n fileId,\n userDownloadLink: `${designerUrl}/file-download/${fileId}`\n }\n })\n}\n\nfunction isFileUploadFieldItem(\n item: DetailItemField\n): item is FileUploadFieldDetailitem {\n return item.field instanceof FileUploadField\n}\n\n/**\n * A detail item specifically for files\n */\ntype FileUploadFieldDetailitem = Omit<DetailItemField, 'field'> & {\n field: FileUploadField\n}\n\ntype RichFormValue =\n | FormValue\n | FormPayload\n | DatePartsState\n | MonthYearState\n | UkAddressState\n"],"mappings":"AAEA,SAASA,MAAM;AAEf,SAASC,eAAe;
|
|
1
|
+
{"version":3,"file":"v2.js","names":["config","FileUploadField","designerUrl","get","format","context","items","model","_submitResponse","_formStatus","now","Date","categorisedData","categoriseData","data","meta","schemaVersion","timestamp","toISOString","definition","def","referenceNumber","body","JSON","stringify","output","main","repeaters","files","forEach","item","name","state","extractRepeaters","isFileUploadFieldItem","extractFileUploads","field","getFormValueFromState","subItems","inputRepeaterItem","outputRepeaterItem","repeaterComponent","push","fileUploadState","getContextValueFromState","map","fileId","userDownloadLink"],"sources":["../../../../../../src/server/plugins/engine/outputFormatters/machine/v2.ts"],"sourcesContent":["import { type SubmitResponsePayload } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { type UkAddressState } from '~/src/server/plugins/engine/components/UkAddressField.js'\nimport { FileUploadField } from '~/src/server/plugins/engine/components/index.js'\nimport {\n type DatePartsState,\n type MonthYearState\n} from '~/src/server/plugins/engine/components/types.js'\nimport { type checkFormStatus } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport {\n type DetailItem,\n type DetailItemField,\n type DetailItemRepeat\n} from '~/src/server/plugins/engine/models/types.js'\nimport {\n type FormContext,\n type FormPayload,\n type FormValue\n} from '~/src/server/plugins/engine/types.js'\n\nconst designerUrl = config.get('designerUrl')\n\nexport function format(\n context: FormContext,\n items: DetailItem[],\n model: FormModel,\n _submitResponse: SubmitResponsePayload,\n _formStatus: ReturnType<typeof checkFormStatus>\n) {\n const now = new Date()\n\n const categorisedData = categoriseData(items)\n\n const data = {\n meta: {\n schemaVersion: '2',\n timestamp: now.toISOString(),\n definition: model.def,\n referenceNumber: context.referenceNumber\n },\n data: categorisedData\n }\n\n const body = JSON.stringify(data)\n\n return body\n}\n\n/**\n * Categories the form submission data into the \"main\" body and \"repeaters\".\n *\n * {\n * main: {\n * componentName: 'componentValue',\n * },\n * repeaters: {\n * repeaterName: [\n * {\n * textComponentName: 'componentValue'\n * },\n * {\n * richComponentName: { foo: 'bar', 'baz': true }\n * }\n * ]\n * },\n * files: {\n * fileComponentName: [\n * {\n * fileId: '123-456-789',\n * link: 'https://forms-designer/file-download/123-456-789'\n * }\n * ]\n * }\n * }\n */\nfunction categoriseData(items: DetailItem[]) {\n const output: {\n main: Record<string, RichFormValue>\n repeaters: Record<string, Record<string, RichFormValue>[]>\n files: Record<string, Record<string, string>[]>\n } = { main: {}, repeaters: {}, files: {} }\n\n items.forEach((item) => {\n const { name, state } = item\n\n if ('subItems' in item) {\n output.repeaters[name] = extractRepeaters(item)\n } else if (isFileUploadFieldItem(item)) {\n output.files[name] = extractFileUploads(item)\n } else {\n output.main[name] = item.field.getFormValueFromState(state)\n }\n })\n\n return output\n}\n\n/**\n * Returns the \"repeaters\" section of the response body\n * @param item - the repeater item\n * @returns the repeater item\n */\nfunction extractRepeaters(item: DetailItemRepeat) {\n const repeaters: Record<string, RichFormValue>[] = []\n\n item.subItems.forEach((inputRepeaterItem) => {\n const outputRepeaterItem: Record<string, RichFormValue> = {}\n\n inputRepeaterItem.forEach((repeaterComponent) => {\n const { field, state } = repeaterComponent\n\n outputRepeaterItem[repeaterComponent.name] =\n field.getFormValueFromState(state)\n })\n\n repeaters.push(outputRepeaterItem)\n })\n\n return repeaters\n}\n\n/**\n * Returns the \"files\" section of the response body\n * @param item - the file upload item in the form\n * @returns the file upload data\n */\nfunction extractFileUploads(item: FileUploadFieldDetailitem) {\n const fileUploadState = item.field.getContextValueFromState(item.state) ?? []\n\n return fileUploadState.map((fileId) => {\n return {\n fileId,\n userDownloadLink: `${designerUrl}/file-download/${fileId}`\n }\n })\n}\n\nfunction isFileUploadFieldItem(\n item: DetailItemField\n): item is FileUploadFieldDetailitem {\n return item.field instanceof FileUploadField\n}\n\n/**\n * A detail item specifically for files\n */\ntype FileUploadFieldDetailitem = Omit<DetailItemField, 'field'> & {\n field: FileUploadField\n}\n\ntype RichFormValue =\n | FormValue\n | FormPayload\n | DatePartsState\n | MonthYearState\n | UkAddressState\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ComponentType, ControllerType, Engine, hasComponents, hasNext, hasRepeater } from '@defra/forms-model';
|
|
2
|
+
import Boom from '@hapi/boom';
|
|
2
3
|
import { ComponentCollection } from "../components/ComponentCollection.js";
|
|
3
4
|
import { optionalText } from "../components/constants.js";
|
|
4
|
-
import { getCacheService, getErrors, normalisePath, proceed } from "../helpers.js";
|
|
5
|
+
import { getCacheService, getErrors, getSaveAndReturnHelpers, normalisePath, proceed } from "../helpers.js";
|
|
5
6
|
import { PageController } from "./PageController.js";
|
|
6
7
|
import { FormAction } from "../../../routes/types.js";
|
|
7
8
|
import { actionSchema, crumbSchema, paramsSchema } from "../../../schemas/index.js";
|
|
@@ -458,7 +459,13 @@ export class QuestionPageController extends PageController {
|
|
|
458
459
|
} = context;
|
|
459
460
|
|
|
460
461
|
// Save the current state and redirect to exit page
|
|
461
|
-
|
|
462
|
+
const saveAndReturn = getSaveAndReturnHelpers(request.server);
|
|
463
|
+
if (!saveAndReturn?.sessionPersister) {
|
|
464
|
+
throw Boom.internal('Server misconfigured for save and return');
|
|
465
|
+
}
|
|
466
|
+
await saveAndReturn.sessionPersister(state, request);
|
|
467
|
+
const cacheService = getCacheService(request.server);
|
|
468
|
+
await cacheService.clearState(request);
|
|
462
469
|
return h.redirect(this.getHref('/exit'));
|
|
463
470
|
}
|
|
464
471
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuestionPageController.js","names":["ComponentType","ControllerType","Engine","hasComponents","hasNext","hasRepeater","ComponentCollection","optionalText","getCacheService","getErrors","normalisePath","proceed","PageController","FormAction","actionSchema","crumbSchema","paramsSchema","merge","QuestionPageController","collection","errorSummaryTitle","allowSaveAndReturn","constructor","model","pageDef","components","page","formSchema","keys","crumb","action","next","def","filter","path","linkPath","pages","some","pagePath","allowContinue","engine","V2","controller","Terminal","length","getItemId","request","itemId","getFormParams","params","getViewModel","context","viewModel","query","payload","errors","pageTitle","showTitle","formComponents","isFormComponent","fieldset","label","isPageHeading","labelOrLegend","legend","size","classes","isOptional","fields","at","options","required","text","backLink","getBackLink","shouldShowSaveAndReturn","server","getRelevantPath","paths","startPath","getStartPath","relevantPath","getNextPath","evaluationState","summaryPath","getSummaryPath","statusPath","getStatusPath","defaultPath","undefined","pageIndex","indexOf","nextPage","slice","find","condition","conditionResult","fn","nextLink","link","conditions","getFormDataFromState","state","result","validate","abortEarly","stripUnknown","value","getStateFromValidForm","details","getState","cacheService","setState","mergeState","update","updated","filterConditionalComponents","filtered","component","content","type","Details","map","evaluatedComponent","Array","isArray","item","items","makeGetRouteHandler","h","viewName","getViewErrors","hasMissingNotificationEmail","view","isForceAccess","formsService","services","getFormMetadata","includes","notificationEmail","slug","returnUrl","href","backPath","endsWith","getHref","makePostRouteHandler","SaveAndReturn","handleSaveAndReturn","nextPath","nextUrl","redirect","getRouteOptions","ext","onPostHandler","method","_request","continue","postRouteOptions","parse","maxBytes","Number","MAX_SAFE_INTEGER","failAction"],"sources":["../../../../../src/server/plugins/engine/pageControllers/QuestionPageController.ts"],"sourcesContent":["import {\n ComponentType,\n ControllerType,\n Engine,\n hasComponents,\n hasNext,\n hasRepeater,\n type Link,\n type Page\n} from '@defra/forms-model'\nimport { type ResponseToolkit, type RouteOptions } from '@hapi/hapi'\nimport { type ValidationErrorItem } from 'joi'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { optionalText } from '~/src/server/plugins/engine/components/constants.js'\nimport { type BackLink } from '~/src/server/plugins/engine/components/types.js'\nimport {\n getCacheService,\n getErrors,\n normalisePath,\n proceed\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport {\n type FormContext,\n type FormContextRequest,\n type FormPageViewModel,\n type FormPayload,\n type FormPayloadParams,\n type FormState,\n type FormStateValue,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport {\n FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n crumbSchema,\n paramsSchema\n} from '~/src/server/schemas/index.js'\nimport { merge } from '~/src/server/services/cacheService.js'\n\nexport class QuestionPageController extends PageController {\n collection: ComponentCollection\n errorSummaryTitle = 'There is a problem'\n allowSaveAndReturn = true\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponents(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n\n this.collection.formSchema = this.collection.formSchema.keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n }\n\n get next(): Link[] {\n const { def, pageDef } = this\n\n if (!hasNext(pageDef)) {\n return []\n }\n\n // Remove stale links\n return pageDef.next.filter(({ path }) => {\n const linkPath = normalisePath(path)\n\n return def.pages.some((page) => {\n const pagePath = normalisePath(page.path)\n return pagePath === linkPath\n })\n })\n }\n\n get allowContinue(): boolean {\n if (this.model.engine === Engine.V2) {\n return this.pageDef.controller !== ControllerType.Terminal\n }\n\n return this.next.length > 0\n }\n\n getItemId(request?: FormContextRequest) {\n const { itemId } = this.getFormParams(request)\n return itemId ?? request?.params.itemId\n }\n\n /**\n * Used for mapping form payloads and errors to govuk-frontend's template api, so a page can be rendered\n * @param request - the hapi request\n * @param context - the form context\n */\n getViewModel(\n request: FormContextRequest,\n context: FormContext\n ): FormPageViewModel {\n const { collection, viewModel } = this\n const { query } = request\n const { payload, errors } = context\n\n let { pageTitle, showTitle } = viewModel\n\n const components = collection.getViewModel(payload, errors, query)\n const formComponents = components.filter(\n ({ isFormComponent }) => isFormComponent\n )\n\n // Single form component? Hide title and customise label or legend instead\n if (formComponents.length === 1) {\n const { model } = formComponents[0]\n const { fieldset, label } = model\n\n // Set as page heading when not following other content\n const isPageHeading = formComponents[0] === components[0]\n\n // Check for legend or label\n const labelOrLegend = fieldset?.legend ?? label\n\n // Use legend or label as page heading\n if (labelOrLegend) {\n const size = isPageHeading ? 'l' : 'm'\n\n labelOrLegend.classes =\n labelOrLegend === label\n ? `govuk-label--${size}`\n : `govuk-fieldset__legend--${size}`\n\n if (isPageHeading) {\n labelOrLegend.isPageHeading = isPageHeading\n\n // Check for optional in label\n const isOptional =\n this.collection.fields.at(0)?.options.required === false\n\n if (pageTitle) {\n labelOrLegend.text = isOptional\n ? `${pageTitle}${optionalText}`\n : pageTitle\n }\n\n pageTitle = pageTitle || labelOrLegend.text\n }\n }\n\n showTitle = !isPageHeading\n } else if (formComponents.length > 1) {\n // When there is more than one form component,\n // adjust the label/legends to give equal prominence\n for (const { model } of formComponents) {\n if (model.fieldset?.legend) {\n model.fieldset.legend.classes = 'govuk-fieldset__legend--m'\n }\n if (model.label) {\n model.label.classes = 'govuk-label--m'\n }\n }\n }\n\n return {\n ...viewModel,\n backLink: this.getBackLink(request, context),\n context,\n showTitle,\n components,\n errors,\n allowSaveAndReturn: this.shouldShowSaveAndReturn(request.server)\n }\n }\n\n getRelevantPath(\n request: FormRequest | FormRequestPayload,\n context: FormContext\n ) {\n const { paths } = context\n\n const startPath = this.getStartPath()\n const relevantPath = paths.at(-1) ?? startPath\n\n return !paths.length\n ? startPath // First possible path\n : relevantPath // Last possible path\n }\n\n /**\n * Apply conditions to evaluation state to determine next page path\n */\n getNextPath(context: FormContext) {\n const { model, next, path } = this\n const { evaluationState } = context\n\n const summaryPath = this.getSummaryPath()\n const statusPath = this.getStatusPath()\n\n // Walk from summary page (no next links) to status page\n let defaultPath = path === summaryPath ? statusPath : undefined\n\n if (model.engine === Engine.V2) {\n if (this.pageDef.controller !== ControllerType.Terminal) {\n const { pages } = this.model\n const pageIndex = pages.indexOf(this)\n\n // The \"next\" page is the first found after the current which is\n // either unconditional or has a condition that evaluates to \"true\"\n const nextPage = pages.slice(pageIndex + 1).find((page) => {\n const { condition } = page\n\n if (condition) {\n const conditionResult = condition.fn(evaluationState)\n\n if (!conditionResult) {\n return false\n }\n }\n\n return true\n })\n\n return nextPage?.path ?? defaultPath\n } else {\n return defaultPath\n }\n }\n\n const nextLink = next.find((link) => {\n const { condition } = link\n\n if (condition) {\n return model.conditions[condition]?.fn(evaluationState) ?? false\n }\n\n defaultPath = link.path\n return false\n })\n\n return nextLink?.path ?? defaultPath\n }\n\n /**\n * Gets the form payload (from state) for this page only\n */\n getFormDataFromState(\n request: FormContextRequest | undefined,\n state: FormSubmissionState\n ): FormPayload {\n const { collection } = this\n\n // Form params from request\n const params = this.getFormParams(request)\n\n // Form payload from state\n const payload = collection.getFormDataFromState(state)\n\n return {\n ...params,\n ...payload\n }\n }\n\n /**\n * Gets form params (from payload) for this page only\n */\n getFormParams(request?: FormContextRequest): FormPayloadParams {\n const { payload } = request ?? {}\n\n const result = paramsSchema.validate(payload, {\n abortEarly: false,\n stripUnknown: true\n })\n\n return result.value as FormPayloadParams\n }\n\n getStateFromValidForm(\n request: FormContextRequest,\n state: FormSubmissionState,\n payload: FormPayload\n ): FormState {\n return this.collection.getStateFromValidForm(payload)\n }\n\n getErrors(details?: ValidationErrorItem[]) {\n return getErrors(details)\n }\n\n async getState(request: FormRequest | FormRequestPayload) {\n const { query } = request\n\n // Skip get for preview URL direct access\n if ('force' in query) {\n return {}\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.getState(request)\n }\n\n async setState(\n request: FormRequest | FormRequestPayload,\n state: FormSubmissionState\n ) {\n const { query } = request\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return state\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, state)\n }\n\n async mergeState(\n request: FormRequest | FormRequestPayload,\n state: FormSubmissionState,\n update: object\n ) {\n const { query } = request\n\n // Merge state before set\n const updated = merge(state, update)\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return updated\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, updated)\n }\n\n filterConditionalComponents(\n viewModel: FormPageViewModel,\n model: FormModel,\n evaluationState: Partial<Record<string, FormStateValue>>\n ) {\n // Filter our components based on their conditions using our evaluated state\n let filtered = viewModel.components.filter((component) => {\n if (\n (!!component.model.content ||\n component.type === ComponentType.Details) &&\n component.model.condition\n ) {\n const condition = model.conditions[component.model.condition]\n return condition?.fn(evaluationState)\n }\n return true\n })\n\n /**\n * For conditional reveal components (which we no longer support until GDS resolves the related accessibility issues {@link https://github.com/alphagov/govuk-frontend/issues/1991}\n */\n filtered = filtered.map((component) => {\n const evaluatedComponent = component\n const content = evaluatedComponent.model.content\n if (Array.isArray(content)) {\n evaluatedComponent.model.content = content.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n // apply condition to items for radios, checkboxes etc\n const items = evaluatedComponent.model.items\n\n if (Array.isArray(items)) {\n evaluatedComponent.model.items = items.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n\n return evaluatedComponent\n })\n\n return filtered\n }\n\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { collection, model, viewName } = this\n const { evaluationState } = context\n\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n /**\n * Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it\n */\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, viewModel)\n }\n }\n\n async hasMissingNotificationEmail(\n request: FormRequest,\n context: FormContext\n ) {\n const { path } = this\n const { params } = request\n const { isForceAccess } = context\n\n const startPath = this.getStartPath()\n const summaryPath = this.getSummaryPath()\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n // Warn the user if the form has no notification email set only on start page and summary page\n if ([startPath, summaryPath].includes(path) && !isForceAccess) {\n const { notificationEmail } = await getFormMetadata(params.slug)\n return !notificationEmail\n }\n\n return false\n }\n\n /**\n * Get the back link for a given progress.\n */\n protected getBackLink(\n request: FormContextRequest,\n context: FormContext\n ): BackLink | undefined {\n const { pageDef } = this\n const { path, query } = request\n const { returnUrl } = query\n const { paths } = context\n\n const itemId = this.getItemId(request)\n\n // Check answers back link\n if (returnUrl) {\n return {\n text:\n hasRepeater(pageDef) && itemId\n ? 'Go back to add another'\n : 'Go back to check answers',\n href: returnUrl\n }\n }\n\n // Item delete pages etc\n const backPath =\n itemId && !path.endsWith(itemId)\n ? paths.at(-1) // Back to main page\n : paths.at(-2) // Back to previous page\n\n // No back link\n if (!backPath) {\n return\n }\n\n // Default back link\n return {\n text: 'Back',\n href: this.getHref(backPath)\n }\n }\n\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { collection, viewName, model } = this\n const { isForceAccess, state, evaluationState } = context\n\n /**\n * If there are any errors, render the page with the parsed errors\n * @todo Refactor to match POST REDIRECT GET pattern\n */\n if (context.errors || isForceAccess) {\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n return h.view(viewName, viewModel)\n }\n\n // Check if this is a save-and-return action\n const { action } = request.payload\n if (action === FormAction.SaveAndReturn) {\n return this.handleSaveAndReturn(request, context, h)\n }\n\n // Save and proceed\n await this.setState(request, state)\n return this.proceed(request, h, this.getNextPath(context))\n }\n }\n\n proceed(\n request: FormContextRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>,\n nextPath?: string\n ) {\n const nextUrl = nextPath\n ? this.getHref(nextPath) // Redirect to next page\n : this.href // Redirect to current page (refresh)\n\n return proceed(request, h, nextUrl)\n }\n\n /**\n * Handle save-and-return action by processing form data and redirecting to exit page\n */\n async handleSaveAndReturn(\n request: FormRequestPayload,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) {\n const { state } = context\n\n // Save the current state and redirect to exit page\n await this.setState(request, state)\n return h.redirect(this.getHref('/exit'))\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get getRouteOptions(): RouteOptions<FormRequestRefs> {\n return {\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n payload: {\n parse: true,\n maxBytes: Number.MAX_SAFE_INTEGER,\n failAction: 'ignore'\n },\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"QuestionPageController.js","names":["ComponentType","ControllerType","Engine","hasComponents","hasNext","hasRepeater","Boom","ComponentCollection","optionalText","getCacheService","getErrors","getSaveAndReturnHelpers","normalisePath","proceed","PageController","FormAction","actionSchema","crumbSchema","paramsSchema","merge","QuestionPageController","collection","errorSummaryTitle","allowSaveAndReturn","constructor","model","pageDef","components","page","formSchema","keys","crumb","action","next","def","filter","path","linkPath","pages","some","pagePath","allowContinue","engine","V2","controller","Terminal","length","getItemId","request","itemId","getFormParams","params","getViewModel","context","viewModel","query","payload","errors","pageTitle","showTitle","formComponents","isFormComponent","fieldset","label","isPageHeading","labelOrLegend","legend","size","classes","isOptional","fields","at","options","required","text","backLink","getBackLink","shouldShowSaveAndReturn","server","getRelevantPath","paths","startPath","getStartPath","relevantPath","getNextPath","evaluationState","summaryPath","getSummaryPath","statusPath","getStatusPath","defaultPath","undefined","pageIndex","indexOf","nextPage","slice","find","condition","conditionResult","fn","nextLink","link","conditions","getFormDataFromState","state","result","validate","abortEarly","stripUnknown","value","getStateFromValidForm","details","getState","cacheService","setState","mergeState","update","updated","filterConditionalComponents","filtered","component","content","type","Details","map","evaluatedComponent","Array","isArray","item","items","makeGetRouteHandler","h","viewName","getViewErrors","hasMissingNotificationEmail","view","isForceAccess","formsService","services","getFormMetadata","includes","notificationEmail","slug","returnUrl","href","backPath","endsWith","getHref","makePostRouteHandler","SaveAndReturn","handleSaveAndReturn","nextPath","nextUrl","saveAndReturn","sessionPersister","internal","clearState","redirect","getRouteOptions","ext","onPostHandler","method","_request","continue","postRouteOptions","parse","maxBytes","Number","MAX_SAFE_INTEGER","failAction"],"sources":["../../../../../src/server/plugins/engine/pageControllers/QuestionPageController.ts"],"sourcesContent":["import {\n ComponentType,\n ControllerType,\n Engine,\n hasComponents,\n hasNext,\n hasRepeater,\n type Link,\n type Page\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type ResponseToolkit, type RouteOptions } from '@hapi/hapi'\nimport { type ValidationErrorItem } from 'joi'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { optionalText } from '~/src/server/plugins/engine/components/constants.js'\nimport { type BackLink } from '~/src/server/plugins/engine/components/types.js'\nimport {\n getCacheService,\n getErrors,\n getSaveAndReturnHelpers,\n normalisePath,\n proceed\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport {\n type FormContext,\n type FormContextRequest,\n type FormPageViewModel,\n type FormPayload,\n type FormPayloadParams,\n type FormState,\n type FormStateValue,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport {\n FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n crumbSchema,\n paramsSchema\n} from '~/src/server/schemas/index.js'\nimport { merge } from '~/src/server/services/cacheService.js'\n\nexport class QuestionPageController extends PageController {\n collection: ComponentCollection\n errorSummaryTitle = 'There is a problem'\n allowSaveAndReturn = true\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponents(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n\n this.collection.formSchema = this.collection.formSchema.keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n }\n\n get next(): Link[] {\n const { def, pageDef } = this\n\n if (!hasNext(pageDef)) {\n return []\n }\n\n // Remove stale links\n return pageDef.next.filter(({ path }) => {\n const linkPath = normalisePath(path)\n\n return def.pages.some((page) => {\n const pagePath = normalisePath(page.path)\n return pagePath === linkPath\n })\n })\n }\n\n get allowContinue(): boolean {\n if (this.model.engine === Engine.V2) {\n return this.pageDef.controller !== ControllerType.Terminal\n }\n\n return this.next.length > 0\n }\n\n getItemId(request?: FormContextRequest) {\n const { itemId } = this.getFormParams(request)\n return itemId ?? request?.params.itemId\n }\n\n /**\n * Used for mapping form payloads and errors to govuk-frontend's template api, so a page can be rendered\n * @param request - the hapi request\n * @param context - the form context\n */\n getViewModel(\n request: FormContextRequest,\n context: FormContext\n ): FormPageViewModel {\n const { collection, viewModel } = this\n const { query } = request\n const { payload, errors } = context\n\n let { pageTitle, showTitle } = viewModel\n\n const components = collection.getViewModel(payload, errors, query)\n const formComponents = components.filter(\n ({ isFormComponent }) => isFormComponent\n )\n\n // Single form component? Hide title and customise label or legend instead\n if (formComponents.length === 1) {\n const { model } = formComponents[0]\n const { fieldset, label } = model\n\n // Set as page heading when not following other content\n const isPageHeading = formComponents[0] === components[0]\n\n // Check for legend or label\n const labelOrLegend = fieldset?.legend ?? label\n\n // Use legend or label as page heading\n if (labelOrLegend) {\n const size = isPageHeading ? 'l' : 'm'\n\n labelOrLegend.classes =\n labelOrLegend === label\n ? `govuk-label--${size}`\n : `govuk-fieldset__legend--${size}`\n\n if (isPageHeading) {\n labelOrLegend.isPageHeading = isPageHeading\n\n // Check for optional in label\n const isOptional =\n this.collection.fields.at(0)?.options.required === false\n\n if (pageTitle) {\n labelOrLegend.text = isOptional\n ? `${pageTitle}${optionalText}`\n : pageTitle\n }\n\n pageTitle = pageTitle || labelOrLegend.text\n }\n }\n\n showTitle = !isPageHeading\n } else if (formComponents.length > 1) {\n // When there is more than one form component,\n // adjust the label/legends to give equal prominence\n for (const { model } of formComponents) {\n if (model.fieldset?.legend) {\n model.fieldset.legend.classes = 'govuk-fieldset__legend--m'\n }\n if (model.label) {\n model.label.classes = 'govuk-label--m'\n }\n }\n }\n\n return {\n ...viewModel,\n backLink: this.getBackLink(request, context),\n context,\n showTitle,\n components,\n errors,\n allowSaveAndReturn: this.shouldShowSaveAndReturn(request.server)\n }\n }\n\n getRelevantPath(\n request: FormRequest | FormRequestPayload,\n context: FormContext\n ) {\n const { paths } = context\n\n const startPath = this.getStartPath()\n const relevantPath = paths.at(-1) ?? startPath\n\n return !paths.length\n ? startPath // First possible path\n : relevantPath // Last possible path\n }\n\n /**\n * Apply conditions to evaluation state to determine next page path\n */\n getNextPath(context: FormContext) {\n const { model, next, path } = this\n const { evaluationState } = context\n\n const summaryPath = this.getSummaryPath()\n const statusPath = this.getStatusPath()\n\n // Walk from summary page (no next links) to status page\n let defaultPath = path === summaryPath ? statusPath : undefined\n\n if (model.engine === Engine.V2) {\n if (this.pageDef.controller !== ControllerType.Terminal) {\n const { pages } = this.model\n const pageIndex = pages.indexOf(this)\n\n // The \"next\" page is the first found after the current which is\n // either unconditional or has a condition that evaluates to \"true\"\n const nextPage = pages.slice(pageIndex + 1).find((page) => {\n const { condition } = page\n\n if (condition) {\n const conditionResult = condition.fn(evaluationState)\n\n if (!conditionResult) {\n return false\n }\n }\n\n return true\n })\n\n return nextPage?.path ?? defaultPath\n } else {\n return defaultPath\n }\n }\n\n const nextLink = next.find((link) => {\n const { condition } = link\n\n if (condition) {\n return model.conditions[condition]?.fn(evaluationState) ?? false\n }\n\n defaultPath = link.path\n return false\n })\n\n return nextLink?.path ?? defaultPath\n }\n\n /**\n * Gets the form payload (from state) for this page only\n */\n getFormDataFromState(\n request: FormContextRequest | undefined,\n state: FormSubmissionState\n ): FormPayload {\n const { collection } = this\n\n // Form params from request\n const params = this.getFormParams(request)\n\n // Form payload from state\n const payload = collection.getFormDataFromState(state)\n\n return {\n ...params,\n ...payload\n }\n }\n\n /**\n * Gets form params (from payload) for this page only\n */\n getFormParams(request?: FormContextRequest): FormPayloadParams {\n const { payload } = request ?? {}\n\n const result = paramsSchema.validate(payload, {\n abortEarly: false,\n stripUnknown: true\n })\n\n return result.value as FormPayloadParams\n }\n\n getStateFromValidForm(\n request: FormContextRequest,\n state: FormSubmissionState,\n payload: FormPayload\n ): FormState {\n return this.collection.getStateFromValidForm(payload)\n }\n\n getErrors(details?: ValidationErrorItem[]) {\n return getErrors(details)\n }\n\n async getState(request: FormRequest | FormRequestPayload) {\n const { query } = request\n\n // Skip get for preview URL direct access\n if ('force' in query) {\n return {}\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.getState(request)\n }\n\n async setState(\n request: FormRequest | FormRequestPayload,\n state: FormSubmissionState\n ) {\n const { query } = request\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return state\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, state)\n }\n\n async mergeState(\n request: FormRequest | FormRequestPayload,\n state: FormSubmissionState,\n update: object\n ) {\n const { query } = request\n\n // Merge state before set\n const updated = merge(state, update)\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return updated\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, updated)\n }\n\n filterConditionalComponents(\n viewModel: FormPageViewModel,\n model: FormModel,\n evaluationState: Partial<Record<string, FormStateValue>>\n ) {\n // Filter our components based on their conditions using our evaluated state\n let filtered = viewModel.components.filter((component) => {\n if (\n (!!component.model.content ||\n component.type === ComponentType.Details) &&\n component.model.condition\n ) {\n const condition = model.conditions[component.model.condition]\n return condition?.fn(evaluationState)\n }\n return true\n })\n\n /**\n * For conditional reveal components (which we no longer support until GDS resolves the related accessibility issues {@link https://github.com/alphagov/govuk-frontend/issues/1991}\n */\n filtered = filtered.map((component) => {\n const evaluatedComponent = component\n const content = evaluatedComponent.model.content\n if (Array.isArray(content)) {\n evaluatedComponent.model.content = content.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n // apply condition to items for radios, checkboxes etc\n const items = evaluatedComponent.model.items\n\n if (Array.isArray(items)) {\n evaluatedComponent.model.items = items.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n\n return evaluatedComponent\n })\n\n return filtered\n }\n\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { collection, model, viewName } = this\n const { evaluationState } = context\n\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n /**\n * Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it\n */\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, viewModel)\n }\n }\n\n async hasMissingNotificationEmail(\n request: FormRequest,\n context: FormContext\n ) {\n const { path } = this\n const { params } = request\n const { isForceAccess } = context\n\n const startPath = this.getStartPath()\n const summaryPath = this.getSummaryPath()\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n // Warn the user if the form has no notification email set only on start page and summary page\n if ([startPath, summaryPath].includes(path) && !isForceAccess) {\n const { notificationEmail } = await getFormMetadata(params.slug)\n return !notificationEmail\n }\n\n return false\n }\n\n /**\n * Get the back link for a given progress.\n */\n protected getBackLink(\n request: FormContextRequest,\n context: FormContext\n ): BackLink | undefined {\n const { pageDef } = this\n const { path, query } = request\n const { returnUrl } = query\n const { paths } = context\n\n const itemId = this.getItemId(request)\n\n // Check answers back link\n if (returnUrl) {\n return {\n text:\n hasRepeater(pageDef) && itemId\n ? 'Go back to add another'\n : 'Go back to check answers',\n href: returnUrl\n }\n }\n\n // Item delete pages etc\n const backPath =\n itemId && !path.endsWith(itemId)\n ? paths.at(-1) // Back to main page\n : paths.at(-2) // Back to previous page\n\n // No back link\n if (!backPath) {\n return\n }\n\n // Default back link\n return {\n text: 'Back',\n href: this.getHref(backPath)\n }\n }\n\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { collection, viewName, model } = this\n const { isForceAccess, state, evaluationState } = context\n\n /**\n * If there are any errors, render the page with the parsed errors\n * @todo Refactor to match POST REDIRECT GET pattern\n */\n if (context.errors || isForceAccess) {\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n return h.view(viewName, viewModel)\n }\n\n // Check if this is a save-and-return action\n const { action } = request.payload\n if (action === FormAction.SaveAndReturn) {\n return this.handleSaveAndReturn(request, context, h)\n }\n\n // Save and proceed\n await this.setState(request, state)\n return this.proceed(request, h, this.getNextPath(context))\n }\n }\n\n proceed(\n request: FormContextRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>,\n nextPath?: string\n ) {\n const nextUrl = nextPath\n ? this.getHref(nextPath) // Redirect to next page\n : this.href // Redirect to current page (refresh)\n\n return proceed(request, h, nextUrl)\n }\n\n /**\n * Handle save-and-return action by processing form data and redirecting to exit page\n */\n async handleSaveAndReturn(\n request: FormRequestPayload,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) {\n const { state } = context\n\n // Save the current state and redirect to exit page\n const saveAndReturn = getSaveAndReturnHelpers(request.server)\n\n if (!saveAndReturn?.sessionPersister) {\n throw Boom.internal('Server misconfigured for save and return')\n }\n\n await saveAndReturn.sessionPersister(state, request)\n\n const cacheService = getCacheService(request.server)\n await cacheService.clearState(request)\n\n return h.redirect(this.getHref('/exit'))\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get getRouteOptions(): RouteOptions<FormRequestRefs> {\n return {\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n payload: {\n parse: true,\n maxBytes: Number.MAX_SAFE_INTEGER,\n failAction: 'ignore'\n },\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -68,9 +68,6 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
68
68
|
const {
|
|
69
69
|
params
|
|
70
70
|
} = request;
|
|
71
|
-
const {
|
|
72
|
-
state
|
|
73
|
-
} = context;
|
|
74
71
|
const cacheService = getCacheService(request.server);
|
|
75
72
|
const {
|
|
76
73
|
formsService
|
|
@@ -92,7 +89,7 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
92
89
|
// Send submission email
|
|
93
90
|
if (emailAddress) {
|
|
94
91
|
const viewModel = this.getSummaryViewModel(request, context);
|
|
95
|
-
await submitForm(request, viewModel, model,
|
|
92
|
+
await submitForm(context, request, viewModel, model, emailAddress);
|
|
96
93
|
}
|
|
97
94
|
await cacheService.setConfirmationState(request, {
|
|
98
95
|
confirmed: true
|
|
@@ -115,8 +112,8 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
115
112
|
};
|
|
116
113
|
}
|
|
117
114
|
}
|
|
118
|
-
async function submitForm(request, summaryViewModel, model,
|
|
119
|
-
await extendFileRetention(model, state, emailAddress);
|
|
115
|
+
async function submitForm(context, request, summaryViewModel, model, emailAddress) {
|
|
116
|
+
await extendFileRetention(model, context.state, emailAddress);
|
|
120
117
|
const formStatus = checkFormStatus(request.params);
|
|
121
118
|
const logTags = ['submit', 'submissionApi'];
|
|
122
119
|
request.logger.info(logTags, 'Preparing email', formStatus);
|
|
@@ -130,7 +127,7 @@ async function submitForm(request, summaryViewModel, model, state, emailAddress)
|
|
|
130
127
|
if (submitResponse === undefined) {
|
|
131
128
|
throw Boom.badRequest('Unexpected empty response from submit api');
|
|
132
129
|
}
|
|
133
|
-
return model.services.outputService.submit(request, model, emailAddress, items, submitResponse);
|
|
130
|
+
return model.services.outputService.submit(context, request, model, emailAddress, items, submitResponse);
|
|
134
131
|
}
|
|
135
132
|
async function extendFileRetention(model, state, updatedRetrievalKey) {
|
|
136
133
|
const {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SummaryPageController.js","names":["hasComponentsEvenIfNoNext","Boom","ComponentCollection","FileUploadField","getAnswer","checkEmailAddressForLiveFormSubmission","checkFormStatus","getCacheService","SummaryViewModel","QuestionPageController","SummaryPageController","constructor","model","pageDef","viewName","collection","components","page","getSummaryViewModel","request","context","viewModel","query","payload","errors","getViewModel","backLink","getBackLink","feedbackLink","phaseTag","allowSaveAndReturn","shouldShowSaveAndReturn","server","makeGetRouteHandler","h","hasMissingNotificationEmail","view","makePostRouteHandler","params","state","cacheService","formsService","services","getFormMetadata","notificationEmail","slug","isPreview","emailAddress","def","outputEmail","submitForm","setConfirmationState","confirmed","clearState","proceed","getStatusPath","postRouteOptions","ext","onPreHandler","method","continue","summaryViewModel","extendFileRetention","formStatus","logTags","logger","info","items","getFormSubmissionData","details","submitResponse","submitData","yar","id","undefined","badRequest","outputService","submit","updatedRetrievalKey","formSubmissionService","persistFiles","files","pages","forEach","fileUploadComponents","fields","filter","component","values","getFormValueFromState","length","push","map","status","fileId","form","file","initiatedRetrievalKey","metadata","retrievalKey","sessionId","main","item","name","title","label","value","field","format","repeaters","subItems","detailItems","subItem","relevantPages","href","flatMap","flat"],"sources":["../../../../../src/server/plugins/engine/pageControllers/SummaryPageController.ts"],"sourcesContent":["import {\n hasComponentsEvenIfNoNext,\n type Page,\n type SubmitPayload\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type ResponseToolkit, type RouteOptions } from '@hapi/hapi'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { FileUploadField } from '~/src/server/plugins/engine/components/FileUploadField.js'\nimport { getAnswer } from '~/src/server/plugins/engine/components/helpers.js'\nimport {\n checkEmailAddressForLiveFormSubmission,\n checkFormStatus,\n getCacheService\n} from '~/src/server/plugins/engine/helpers.js'\nimport {\n SummaryViewModel,\n type FormModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport {\n type Detail,\n type DetailItem\n} from '~/src/server/plugins/engine/models/types.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport {\n type FormContext,\n type FormContextRequest,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs\n} from '~/src/server/routes/types.js'\n\nexport class SummaryPageController extends QuestionPageController {\n declare pageDef: Page\n\n /**\n * The controller which is used when Page[\"controller\"] is defined as \"./pages/summary.js\"\n */\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n this.viewName = 'summary'\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponentsEvenIfNoNext(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n }\n\n getSummaryViewModel(\n request: FormContextRequest,\n context: FormContext\n ): SummaryViewModel {\n const viewModel = new SummaryViewModel(request, this, context)\n\n const { query } = request\n const { payload, errors } = context\n const components = this.collection.getViewModel(payload, errors, query)\n\n // We already figure these out in the base page controller. Take them and apply them to our page-specific model.\n // This is a stop-gap until we can add proper inheritance in place.\n viewModel.backLink = this.getBackLink(request, context)\n viewModel.feedbackLink = this.feedbackLink\n viewModel.phaseTag = this.phaseTag\n viewModel.components = components\n viewModel.allowSaveAndReturn = this.shouldShowSaveAndReturn(request.server)\n\n return viewModel\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,\n */\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { viewName } = this\n\n const viewModel = this.getSummaryViewModel(request, context)\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, viewModel)\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a POST request at `/{id}/{path*}`.\n * If a form is incomplete, a user will be redirected to the start page.\n */\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { model } = this\n const { params } = request\n const { state } = context\n const cacheService = getCacheService(request.server)\n\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n // Get the form metadata using the `slug` param\n const { notificationEmail } = await getFormMetadata(params.slug)\n const { isPreview } = checkFormStatus(request.params)\n const emailAddress = notificationEmail ?? this.model.def.outputEmail\n\n checkEmailAddressForLiveFormSubmission(emailAddress, isPreview)\n\n // Send submission email\n if (emailAddress) {\n const viewModel = this.getSummaryViewModel(request, context)\n await submitForm(request, viewModel, model, state, emailAddress)\n }\n\n await cacheService.setConfirmationState(request, { confirmed: true })\n\n // Clear all form data\n await cacheService.clearState(request)\n\n return this.proceed(request, h, this.getStatusPath())\n }\n }\n\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n ext: {\n onPreHandler: {\n method(request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n\nasync function submitForm(\n request: FormRequestPayload,\n summaryViewModel: SummaryViewModel,\n model: FormModel,\n state: FormSubmissionState,\n emailAddress: string\n) {\n await extendFileRetention(model, state, emailAddress)\n\n const formStatus = checkFormStatus(request.params)\n const logTags = ['submit', 'submissionApi']\n\n request.logger.info(logTags, 'Preparing email', formStatus)\n\n // Get detail items\n const items = getFormSubmissionData(\n summaryViewModel.context,\n summaryViewModel.details\n )\n\n // Submit data\n request.logger.info(logTags, 'Submitting data')\n const submitResponse = await submitData(\n model,\n items,\n emailAddress,\n request.yar.id\n )\n\n if (submitResponse === undefined) {\n throw Boom.badRequest('Unexpected empty response from submit api')\n }\n\n return model.services.outputService.submit(\n request,\n model,\n emailAddress,\n items,\n submitResponse\n )\n}\n\nasync function extendFileRetention(\n model: FormModel,\n state: FormSubmissionState,\n updatedRetrievalKey: string\n) {\n const { formSubmissionService } = model.services\n const { persistFiles } = formSubmissionService\n const files: { fileId: string; initiatedRetrievalKey: string }[] = []\n\n // For each file upload component with files in\n // state, add the files to the batch getting persisted\n model.pages.forEach((page) => {\n const fileUploadComponents = page.collection.fields.filter(\n (component) => component instanceof FileUploadField\n )\n\n fileUploadComponents.forEach((component) => {\n const values = component.getFormValueFromState(state)\n if (!values?.length) {\n return\n }\n\n files.push(\n ...values.map(({ status }) => ({\n fileId: status.form.file.fileId,\n initiatedRetrievalKey: status.metadata.retrievalKey\n }))\n )\n })\n })\n\n if (files.length) {\n return persistFiles(files, updatedRetrievalKey)\n }\n}\n\nfunction submitData(\n model: FormModel,\n items: DetailItem[],\n retrievalKey: string,\n sessionId: string\n) {\n const { formSubmissionService } = model.services\n const { submit } = formSubmissionService\n\n const payload: SubmitPayload = {\n sessionId,\n retrievalKey,\n\n // Main form answers\n main: items\n .filter((item) => 'field' in item)\n .map((item) => ({\n name: item.name,\n title: item.label,\n value: getAnswer(item.field, item.state, { format: 'data' })\n })),\n\n // Repeater form answers\n repeaters: items\n .filter((item) => 'subItems' in item)\n .map((item) => ({\n name: item.name,\n title: item.label,\n\n // Repeater item values\n value: item.subItems.map((detailItems) =>\n detailItems.map((subItem) => ({\n name: subItem.name,\n title: subItem.label,\n value: getAnswer(subItem.field, subItem.state, { format: 'data' })\n }))\n )\n }))\n }\n\n return submit(payload)\n}\n\nexport function getFormSubmissionData(context: FormContext, details: Detail[]) {\n return context.relevantPages\n .map(({ href }) =>\n details.flatMap(({ items }) =>\n items.filter(({ page }) => page.href === href)\n )\n )\n .flat()\n}\n"],"mappings":"AAAA,SACEA,yBAAyB,QAGpB,oBAAoB;AAC3B,OAAOC,IAAI,MAAM,YAAY;AAG7B,SAASC,mBAAmB;AAC5B,SAASC,eAAe;AACxB,SAASC,SAAS;AAClB,SACEC,sCAAsC,EACtCC,eAAe,EACfC,eAAe;AAEjB,SACEC,gBAAgB;AAOlB,SAASC,sBAAsB;AAY/B,OAAO,MAAMC,qBAAqB,SAASD,sBAAsB,CAAC;EAGhE;AACF;AACA;;EAEEE,WAAWA,CAACC,KAAgB,EAAEC,OAAa,EAAE;IAC3C,KAAK,CAACD,KAAK,EAAEC,OAAO,CAAC;IACrB,IAAI,CAACC,QAAQ,GAAG,SAAS;;IAEzB;IACA,IAAI,CAACC,UAAU,GAAG,IAAIb,mBAAmB,CACvCF,yBAAyB,CAACa,OAAO,CAAC,GAAGA,OAAO,CAACG,UAAU,GAAG,EAAE,EAC5D;MAAEJ,KAAK;MAAEK,IAAI,EAAE;IAAK,CACtB,CAAC;EACH;EAEAC,mBAAmBA,CACjBC,OAA2B,EAC3BC,OAAoB,EACF;IAClB,MAAMC,SAAS,GAAG,IAAIb,gBAAgB,CAACW,OAAO,EAAE,IAAI,EAAEC,OAAO,CAAC;IAE9D,MAAM;MAAEE;IAAM,CAAC,GAAGH,OAAO;IACzB,MAAM;MAAEI,OAAO;MAAEC;IAAO,CAAC,GAAGJ,OAAO;IACnC,MAAMJ,UAAU,GAAG,IAAI,CAACD,UAAU,CAACU,YAAY,CAACF,OAAO,EAAEC,MAAM,EAAEF,KAAK,CAAC;;IAEvE;IACA;IACAD,SAAS,CAACK,QAAQ,GAAG,IAAI,CAACC,WAAW,CAACR,OAAO,EAAEC,OAAO,CAAC;IACvDC,SAAS,CAACO,YAAY,GAAG,IAAI,CAACA,YAAY;IAC1CP,SAAS,CAACQ,QAAQ,GAAG,IAAI,CAACA,QAAQ;IAClCR,SAAS,CAACL,UAAU,GAAGA,UAAU;IACjCK,SAAS,CAACS,kBAAkB,GAAG,IAAI,CAACC,uBAAuB,CAACZ,OAAO,CAACa,MAAM,CAAC;IAE3E,OAAOX,SAAS;EAClB;;EAEA;AACF;AACA;EACEY,mBAAmBA,CAAA,EAAG;IACpB,OAAO,OACLd,OAAoB,EACpBC,OAAoB,EACpBc,CAA6C,KAC1C;MACH,MAAM;QAAEpB;MAAS,CAAC,GAAG,IAAI;MAEzB,MAAMO,SAAS,GAAG,IAAI,CAACH,mBAAmB,CAACC,OAAO,EAAEC,OAAO,CAAC;MAE5DC,SAAS,CAACc,2BAA2B,GACnC,MAAM,IAAI,CAACA,2BAA2B,CAAChB,OAAO,EAAEC,OAAO,CAAC;MAE1D,OAAOc,CAAC,CAACE,IAAI,CAACtB,QAAQ,EAAEO,SAAS,CAAC;IACpC,CAAC;EACH;;EAEA;AACF;AACA;AACA;EACEgB,oBAAoBA,CAAA,EAAG;IACrB,OAAO,OACLlB,OAA2B,EAC3BC,OAAoB,EACpBc,CAA6C,KAC1C;MACH,MAAM;QAAEtB;MAAM,CAAC,GAAG,IAAI;MACtB,MAAM;QAAE0B;MAAO,CAAC,GAAGnB,OAAO;MAC1B,MAAM;QAAEoB;MAAM,CAAC,GAAGnB,OAAO;MACzB,MAAMoB,YAAY,GAAGjC,eAAe,CAACY,OAAO,CAACa,MAAM,CAAC;MAEpD,MAAM;QAAES;MAAa,CAAC,GAAG,IAAI,CAAC7B,KAAK,CAAC8B,QAAQ;MAC5C,MAAM;QAAEC;MAAgB,CAAC,GAAGF,YAAY;;MAExC;MACA,MAAM;QAAEG;MAAkB,CAAC,GAAG,MAAMD,eAAe,CAACL,MAAM,CAACO,IAAI,CAAC;MAChE,MAAM;QAAEC;MAAU,CAAC,GAAGxC,eAAe,CAACa,OAAO,CAACmB,MAAM,CAAC;MACrD,MAAMS,YAAY,GAAGH,iBAAiB,IAAI,IAAI,CAAChC,KAAK,CAACoC,GAAG,CAACC,WAAW;MAEpE5C,sCAAsC,CAAC0C,YAAY,EAAED,SAAS,CAAC;;MAE/D;MACA,IAAIC,YAAY,EAAE;QAChB,MAAM1B,SAAS,GAAG,IAAI,CAACH,mBAAmB,CAACC,OAAO,EAAEC,OAAO,CAAC;QAC5D,MAAM8B,UAAU,CAAC/B,OAAO,EAAEE,SAAS,EAAET,KAAK,EAAE2B,KAAK,EAAEQ,YAAY,CAAC;MAClE;MAEA,MAAMP,YAAY,CAACW,oBAAoB,CAAChC,OAAO,EAAE;QAAEiC,SAAS,EAAE;MAAK,CAAC,CAAC;;MAErE;MACA,MAAMZ,YAAY,CAACa,UAAU,CAAClC,OAAO,CAAC;MAEtC,OAAO,IAAI,CAACmC,OAAO,CAACnC,OAAO,EAAEe,CAAC,EAAE,IAAI,CAACqB,aAAa,CAAC,CAAC,CAAC;IACvD,CAAC;EACH;EAEA,IAAIC,gBAAgBA,CAAA,EAAyC;IAC3D,OAAO;MACLC,GAAG,EAAE;QACHC,YAAY,EAAE;UACZC,MAAMA,CAACxC,OAAO,EAAEe,CAAC,EAAE;YACjB,OAAOA,CAAC,CAAC0B,QAAQ;UACnB;QACF;MACF;IACF,CAAC;EACH;AACF;AAEA,eAAeV,UAAUA,CACvB/B,OAA2B,EAC3B0C,gBAAkC,EAClCjD,KAAgB,EAChB2B,KAA0B,EAC1BQ,YAAoB,EACpB;EACA,MAAMe,mBAAmB,CAAClD,KAAK,EAAE2B,KAAK,EAAEQ,YAAY,CAAC;EAErD,MAAMgB,UAAU,GAAGzD,eAAe,CAACa,OAAO,CAACmB,MAAM,CAAC;EAClD,MAAM0B,OAAO,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC;EAE3C7C,OAAO,CAAC8C,MAAM,CAACC,IAAI,CAACF,OAAO,EAAE,iBAAiB,EAAED,UAAU,CAAC;;EAE3D;EACA,MAAMI,KAAK,GAAGC,qBAAqB,CACjCP,gBAAgB,CAACzC,OAAO,EACxByC,gBAAgB,CAACQ,OACnB,CAAC;;EAED;EACAlD,OAAO,CAAC8C,MAAM,CAACC,IAAI,CAACF,OAAO,EAAE,iBAAiB,CAAC;EAC/C,MAAMM,cAAc,GAAG,MAAMC,UAAU,CACrC3D,KAAK,EACLuD,KAAK,EACLpB,YAAY,EACZ5B,OAAO,CAACqD,GAAG,CAACC,EACd,CAAC;EAED,IAAIH,cAAc,KAAKI,SAAS,EAAE;IAChC,MAAMzE,IAAI,CAAC0E,UAAU,CAAC,2CAA2C,CAAC;EACpE;EAEA,OAAO/D,KAAK,CAAC8B,QAAQ,CAACkC,aAAa,CAACC,MAAM,CACxC1D,OAAO,EACPP,KAAK,EACLmC,YAAY,EACZoB,KAAK,EACLG,cACF,CAAC;AACH;AAEA,eAAeR,mBAAmBA,CAChClD,KAAgB,EAChB2B,KAA0B,EAC1BuC,mBAA2B,EAC3B;EACA,MAAM;IAAEC;EAAsB,CAAC,GAAGnE,KAAK,CAAC8B,QAAQ;EAChD,MAAM;IAAEsC;EAAa,CAAC,GAAGD,qBAAqB;EAC9C,MAAME,KAA0D,GAAG,EAAE;;EAErE;EACA;EACArE,KAAK,CAACsE,KAAK,CAACC,OAAO,CAAElE,IAAI,IAAK;IAC5B,MAAMmE,oBAAoB,GAAGnE,IAAI,CAACF,UAAU,CAACsE,MAAM,CAACC,MAAM,CACvDC,SAAS,IAAKA,SAAS,YAAYpF,eACtC,CAAC;IAEDiF,oBAAoB,CAACD,OAAO,CAAEI,SAAS,IAAK;MAC1C,MAAMC,MAAM,GAAGD,SAAS,CAACE,qBAAqB,CAAClD,KAAK,CAAC;MACrD,IAAI,CAACiD,MAAM,EAAEE,MAAM,EAAE;QACnB;MACF;MAEAT,KAAK,CAACU,IAAI,CACR,GAAGH,MAAM,CAACI,GAAG,CAAC,CAAC;QAAEC;MAAO,CAAC,MAAM;QAC7BC,MAAM,EAAED,MAAM,CAACE,IAAI,CAACC,IAAI,CAACF,MAAM;QAC/BG,qBAAqB,EAAEJ,MAAM,CAACK,QAAQ,CAACC;MACzC,CAAC,CAAC,CACJ,CAAC;IACH,CAAC,CAAC;EACJ,CAAC,CAAC;EAEF,IAAIlB,KAAK,CAACS,MAAM,EAAE;IAChB,OAAOV,YAAY,CAACC,KAAK,EAAEH,mBAAmB,CAAC;EACjD;AACF;AAEA,SAASP,UAAUA,CACjB3D,KAAgB,EAChBuD,KAAmB,EACnBgC,YAAoB,EACpBC,SAAiB,EACjB;EACA,MAAM;IAAErB;EAAsB,CAAC,GAAGnE,KAAK,CAAC8B,QAAQ;EAChD,MAAM;IAAEmC;EAAO,CAAC,GAAGE,qBAAqB;EAExC,MAAMxD,OAAsB,GAAG;IAC7B6E,SAAS;IACTD,YAAY;IAEZ;IACAE,IAAI,EAAElC,KAAK,CACRmB,MAAM,CAAEgB,IAAI,IAAK,OAAO,IAAIA,IAAI,CAAC,CACjCV,GAAG,CAAEU,IAAI,KAAM;MACdC,IAAI,EAAED,IAAI,CAACC,IAAI;MACfC,KAAK,EAAEF,IAAI,CAACG,KAAK;MACjBC,KAAK,EAAEtG,SAAS,CAACkG,IAAI,CAACK,KAAK,EAAEL,IAAI,CAAC/D,KAAK,EAAE;QAAEqE,MAAM,EAAE;MAAO,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEL;IACAC,SAAS,EAAE1C,KAAK,CACbmB,MAAM,CAAEgB,IAAI,IAAK,UAAU,IAAIA,IAAI,CAAC,CACpCV,GAAG,CAAEU,IAAI,KAAM;MACdC,IAAI,EAAED,IAAI,CAACC,IAAI;MACfC,KAAK,EAAEF,IAAI,CAACG,KAAK;MAEjB;MACAC,KAAK,EAAEJ,IAAI,CAACQ,QAAQ,CAAClB,GAAG,CAAEmB,WAAW,IACnCA,WAAW,CAACnB,GAAG,CAAEoB,OAAO,KAAM;QAC5BT,IAAI,EAAES,OAAO,CAACT,IAAI;QAClBC,KAAK,EAAEQ,OAAO,CAACP,KAAK;QACpBC,KAAK,EAAEtG,SAAS,CAAC4G,OAAO,CAACL,KAAK,EAAEK,OAAO,CAACzE,KAAK,EAAE;UAAEqE,MAAM,EAAE;QAAO,CAAC;MACnE,CAAC,CAAC,CACJ;IACF,CAAC,CAAC;EACN,CAAC;EAED,OAAO/B,MAAM,CAACtD,OAAO,CAAC;AACxB;AAEA,OAAO,SAAS6C,qBAAqBA,CAAChD,OAAoB,EAAEiD,OAAiB,EAAE;EAC7E,OAAOjD,OAAO,CAAC6F,aAAa,CACzBrB,GAAG,CAAC,CAAC;IAAEsB;EAAK,CAAC,KACZ7C,OAAO,CAAC8C,OAAO,CAAC,CAAC;IAAEhD;EAAM,CAAC,KACxBA,KAAK,CAACmB,MAAM,CAAC,CAAC;IAAErE;EAAK,CAAC,KAAKA,IAAI,CAACiG,IAAI,KAAKA,IAAI,CAC/C,CACF,CAAC,CACAE,IAAI,CAAC,CAAC;AACX","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"SummaryPageController.js","names":["hasComponentsEvenIfNoNext","Boom","ComponentCollection","FileUploadField","getAnswer","checkEmailAddressForLiveFormSubmission","checkFormStatus","getCacheService","SummaryViewModel","QuestionPageController","SummaryPageController","constructor","model","pageDef","viewName","collection","components","page","getSummaryViewModel","request","context","viewModel","query","payload","errors","getViewModel","backLink","getBackLink","feedbackLink","phaseTag","allowSaveAndReturn","shouldShowSaveAndReturn","server","makeGetRouteHandler","h","hasMissingNotificationEmail","view","makePostRouteHandler","params","cacheService","formsService","services","getFormMetadata","notificationEmail","slug","isPreview","emailAddress","def","outputEmail","submitForm","setConfirmationState","confirmed","clearState","proceed","getStatusPath","postRouteOptions","ext","onPreHandler","method","continue","summaryViewModel","extendFileRetention","state","formStatus","logTags","logger","info","items","getFormSubmissionData","details","submitResponse","submitData","yar","id","undefined","badRequest","outputService","submit","updatedRetrievalKey","formSubmissionService","persistFiles","files","pages","forEach","fileUploadComponents","fields","filter","component","values","getFormValueFromState","length","push","map","status","fileId","form","file","initiatedRetrievalKey","metadata","retrievalKey","sessionId","main","item","name","title","label","value","field","format","repeaters","subItems","detailItems","subItem","relevantPages","href","flatMap","flat"],"sources":["../../../../../src/server/plugins/engine/pageControllers/SummaryPageController.ts"],"sourcesContent":["import {\n hasComponentsEvenIfNoNext,\n type Page,\n type SubmitPayload\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type ResponseToolkit, type RouteOptions } from '@hapi/hapi'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { FileUploadField } from '~/src/server/plugins/engine/components/FileUploadField.js'\nimport { getAnswer } from '~/src/server/plugins/engine/components/helpers.js'\nimport {\n checkEmailAddressForLiveFormSubmission,\n checkFormStatus,\n getCacheService\n} from '~/src/server/plugins/engine/helpers.js'\nimport {\n SummaryViewModel,\n type FormModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport {\n type Detail,\n type DetailItem\n} from '~/src/server/plugins/engine/models/types.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport {\n type FormContext,\n type FormContextRequest,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs\n} from '~/src/server/routes/types.js'\n\nexport class SummaryPageController extends QuestionPageController {\n declare pageDef: Page\n\n /**\n * The controller which is used when Page[\"controller\"] is defined as \"./pages/summary.js\"\n */\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n this.viewName = 'summary'\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponentsEvenIfNoNext(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n }\n\n getSummaryViewModel(\n request: FormContextRequest,\n context: FormContext\n ): SummaryViewModel {\n const viewModel = new SummaryViewModel(request, this, context)\n\n const { query } = request\n const { payload, errors } = context\n const components = this.collection.getViewModel(payload, errors, query)\n\n // We already figure these out in the base page controller. Take them and apply them to our page-specific model.\n // This is a stop-gap until we can add proper inheritance in place.\n viewModel.backLink = this.getBackLink(request, context)\n viewModel.feedbackLink = this.feedbackLink\n viewModel.phaseTag = this.phaseTag\n viewModel.components = components\n viewModel.allowSaveAndReturn = this.shouldShowSaveAndReturn(request.server)\n\n return viewModel\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,\n */\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { viewName } = this\n\n const viewModel = this.getSummaryViewModel(request, context)\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, viewModel)\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a POST request at `/{id}/{path*}`.\n * If a form is incomplete, a user will be redirected to the start page.\n */\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { model } = this\n const { params } = request\n const cacheService = getCacheService(request.server)\n\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n // Get the form metadata using the `slug` param\n const { notificationEmail } = await getFormMetadata(params.slug)\n const { isPreview } = checkFormStatus(request.params)\n const emailAddress = notificationEmail ?? this.model.def.outputEmail\n\n checkEmailAddressForLiveFormSubmission(emailAddress, isPreview)\n\n // Send submission email\n if (emailAddress) {\n const viewModel = this.getSummaryViewModel(request, context)\n await submitForm(context, request, viewModel, model, emailAddress)\n }\n\n await cacheService.setConfirmationState(request, { confirmed: true })\n\n // Clear all form data\n await cacheService.clearState(request)\n\n return this.proceed(request, h, this.getStatusPath())\n }\n }\n\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n ext: {\n onPreHandler: {\n method(request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n\nasync function submitForm(\n context: FormContext,\n request: FormRequestPayload,\n summaryViewModel: SummaryViewModel,\n model: FormModel,\n emailAddress: string\n) {\n await extendFileRetention(model, context.state, emailAddress)\n\n const formStatus = checkFormStatus(request.params)\n const logTags = ['submit', 'submissionApi']\n\n request.logger.info(logTags, 'Preparing email', formStatus)\n\n // Get detail items\n const items = getFormSubmissionData(\n summaryViewModel.context,\n summaryViewModel.details\n )\n\n // Submit data\n request.logger.info(logTags, 'Submitting data')\n const submitResponse = await submitData(\n model,\n items,\n emailAddress,\n request.yar.id\n )\n\n if (submitResponse === undefined) {\n throw Boom.badRequest('Unexpected empty response from submit api')\n }\n\n return model.services.outputService.submit(\n context,\n request,\n model,\n emailAddress,\n items,\n submitResponse\n )\n}\n\nasync function extendFileRetention(\n model: FormModel,\n state: FormSubmissionState,\n updatedRetrievalKey: string\n) {\n const { formSubmissionService } = model.services\n const { persistFiles } = formSubmissionService\n const files: { fileId: string; initiatedRetrievalKey: string }[] = []\n\n // For each file upload component with files in\n // state, add the files to the batch getting persisted\n model.pages.forEach((page) => {\n const fileUploadComponents = page.collection.fields.filter(\n (component) => component instanceof FileUploadField\n )\n\n fileUploadComponents.forEach((component) => {\n const values = component.getFormValueFromState(state)\n if (!values?.length) {\n return\n }\n\n files.push(\n ...values.map(({ status }) => ({\n fileId: status.form.file.fileId,\n initiatedRetrievalKey: status.metadata.retrievalKey\n }))\n )\n })\n })\n\n if (files.length) {\n return persistFiles(files, updatedRetrievalKey)\n }\n}\n\nfunction submitData(\n model: FormModel,\n items: DetailItem[],\n retrievalKey: string,\n sessionId: string\n) {\n const { formSubmissionService } = model.services\n const { submit } = formSubmissionService\n\n const payload: SubmitPayload = {\n sessionId,\n retrievalKey,\n\n // Main form answers\n main: items\n .filter((item) => 'field' in item)\n .map((item) => ({\n name: item.name,\n title: item.label,\n value: getAnswer(item.field, item.state, { format: 'data' })\n })),\n\n // Repeater form answers\n repeaters: items\n .filter((item) => 'subItems' in item)\n .map((item) => ({\n name: item.name,\n title: item.label,\n\n // Repeater item values\n value: item.subItems.map((detailItems) =>\n detailItems.map((subItem) => ({\n name: subItem.name,\n title: subItem.label,\n value: getAnswer(subItem.field, subItem.state, { format: 'data' })\n }))\n )\n }))\n }\n\n return submit(payload)\n}\n\nexport function getFormSubmissionData(context: FormContext, details: Detail[]) {\n return context.relevantPages\n .map(({ href }) =>\n details.flatMap(({ items }) =>\n items.filter(({ page }) => page.href === href)\n )\n )\n .flat()\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -26,8 +26,7 @@ export const plugin = {
|
|
|
26
26
|
cacheName,
|
|
27
27
|
options: {
|
|
28
28
|
keyGenerator: saveAndReturn?.keyGenerator,
|
|
29
|
-
sessionHydrator: saveAndReturn?.sessionHydrator
|
|
30
|
-
sessionPersister: saveAndReturn?.sessionPersister
|
|
29
|
+
sessionHydrator: saveAndReturn?.sessionHydrator
|
|
31
30
|
}
|
|
32
31
|
});
|
|
33
32
|
await registerVision(server, options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":["validatePluginOptions","getRoutes","getSaveAndReturnExitRoutes","getFileUploadStatusRoutes","makeLoadFormPreHandler","getQuestionRoutes","getRepeaterItemDeleteRoutes","getRepeaterSummaryRoutes","registerVision","CacheService","plugin","name","dependencies","multiple","register","server","options","model","cacheName","saveAndReturn","nunjucks","nunjucksOptions","viewContext","preparePageEventRequestOptions","cacheService","keyGenerator","sessionHydrator","
|
|
1
|
+
{"version":3,"file":"plugin.js","names":["validatePluginOptions","getRoutes","getSaveAndReturnExitRoutes","getFileUploadStatusRoutes","makeLoadFormPreHandler","getQuestionRoutes","getRepeaterItemDeleteRoutes","getRepeaterSummaryRoutes","registerVision","CacheService","plugin","name","dependencies","multiple","register","server","options","model","cacheName","saveAndReturn","nunjucks","nunjucksOptions","viewContext","preparePageEventRequestOptions","cacheService","keyGenerator","sessionHydrator","expose","baseLayoutPath","app","itemCache","Map","models","loadFormPreHandler","getRouteOptions","pre","method","postRouteOptions","payload","parse","routes","route"],"sources":["../../../../src/server/plugins/engine/plugin.ts"],"sourcesContent":["import {\n type Lifecycle,\n type Plugin,\n type RouteOptions,\n type Server,\n type ServerRoute\n} from '@hapi/hapi'\n\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { validatePluginOptions } from '~/src/server/plugins/engine/options.js'\nimport { getRoutes as getSaveAndReturnExitRoutes } from '~/src/server/plugins/engine/routes/exit.js'\nimport { getRoutes as getFileUploadStatusRoutes } from '~/src/server/plugins/engine/routes/file-upload.js'\nimport { makeLoadFormPreHandler } from '~/src/server/plugins/engine/routes/index.js'\nimport { getRoutes as getQuestionRoutes } from '~/src/server/plugins/engine/routes/questions.js'\nimport { getRoutes as getRepeaterItemDeleteRoutes } from '~/src/server/plugins/engine/routes/repeaters/item-delete.js'\nimport { getRoutes as getRepeaterSummaryRoutes } from '~/src/server/plugins/engine/routes/repeaters/summary.js'\nimport { type PluginOptions } from '~/src/server/plugins/engine/types.js'\nimport { registerVision } from '~/src/server/plugins/engine/vision.js'\nimport {\n type FormRequestPayloadRefs,\n type FormRequestRefs\n} from '~/src/server/routes/types.js'\nimport { CacheService } from '~/src/server/services/index.js'\n\nexport const plugin = {\n name: '@defra/forms-engine-plugin',\n dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'],\n multiple: true,\n async register(server: Server, options: PluginOptions) {\n options = validatePluginOptions(options)\n\n const {\n model,\n cacheName,\n saveAndReturn,\n nunjucks: nunjucksOptions,\n viewContext,\n preparePageEventRequestOptions\n } = options\n\n const cacheService = new CacheService({\n server,\n cacheName,\n options: {\n keyGenerator: saveAndReturn?.keyGenerator,\n sessionHydrator: saveAndReturn?.sessionHydrator\n }\n })\n\n await registerVision(server, options)\n\n server.expose('baseLayoutPath', nunjucksOptions.baseLayoutPath)\n server.expose('viewContext', viewContext)\n server.expose('cacheService', cacheService)\n server.expose('saveAndReturn', saveAndReturn)\n\n server.app.model = model\n\n // In-memory cache of FormModel items, exposed\n // (for testing purposes) through `server.app.models`\n const itemCache = new Map<string, { model: FormModel; updatedAt: Date }>()\n server.app.models = itemCache\n\n const loadFormPreHandler = makeLoadFormPreHandler(server, options)\n\n const getRouteOptions: RouteOptions<FormRequestRefs> = {\n pre: [\n {\n method:\n loadFormPreHandler as unknown as Lifecycle.Method<FormRequestRefs>\n }\n ]\n }\n\n const postRouteOptions: RouteOptions<FormRequestPayloadRefs> = {\n payload: {\n parse: true\n },\n pre: [\n {\n method:\n loadFormPreHandler as unknown as Lifecycle.Method<FormRequestPayloadRefs>\n }\n ]\n }\n\n const routes = [\n ...getQuestionRoutes(\n getRouteOptions,\n postRouteOptions,\n preparePageEventRequestOptions\n ),\n ...getRepeaterSummaryRoutes(getRouteOptions, postRouteOptions),\n ...getRepeaterItemDeleteRoutes(getRouteOptions, postRouteOptions),\n ...getSaveAndReturnExitRoutes(getRouteOptions),\n ...getFileUploadStatusRoutes()\n ]\n\n server.route(routes as unknown as ServerRoute[]) // TODO\n }\n} satisfies Plugin<PluginOptions>\n"],"mappings":"AASA,SAASA,qBAAqB;AAC9B,SAASC,SAAS,IAAIC,0BAA0B;AAChD,SAASD,SAAS,IAAIE,yBAAyB;AAC/C,SAASC,sBAAsB;AAC/B,SAASH,SAAS,IAAII,iBAAiB;AACvC,SAASJ,SAAS,IAAIK,2BAA2B;AACjD,SAASL,SAAS,IAAIM,wBAAwB;AAE9C,SAASC,cAAc;AAKvB,SAASC,YAAY;AAErB,OAAO,MAAMC,MAAM,GAAG;EACpBC,IAAI,EAAE,4BAA4B;EAClCC,YAAY,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,WAAW,CAAC;EACvDC,QAAQ,EAAE,IAAI;EACd,MAAMC,QAAQA,CAACC,MAAc,EAAEC,OAAsB,EAAE;IACrDA,OAAO,GAAGhB,qBAAqB,CAACgB,OAAO,CAAC;IAExC,MAAM;MACJC,KAAK;MACLC,SAAS;MACTC,aAAa;MACbC,QAAQ,EAAEC,eAAe;MACzBC,WAAW;MACXC;IACF,CAAC,GAAGP,OAAO;IAEX,MAAMQ,YAAY,GAAG,IAAIf,YAAY,CAAC;MACpCM,MAAM;MACNG,SAAS;MACTF,OAAO,EAAE;QACPS,YAAY,EAAEN,aAAa,EAAEM,YAAY;QACzCC,eAAe,EAAEP,aAAa,EAAEO;MAClC;IACF,CAAC,CAAC;IAEF,MAAMlB,cAAc,CAACO,MAAM,EAAEC,OAAO,CAAC;IAErCD,MAAM,CAACY,MAAM,CAAC,gBAAgB,EAAEN,eAAe,CAACO,cAAc,CAAC;IAC/Db,MAAM,CAACY,MAAM,CAAC,aAAa,EAAEL,WAAW,CAAC;IACzCP,MAAM,CAACY,MAAM,CAAC,cAAc,EAAEH,YAAY,CAAC;IAC3CT,MAAM,CAACY,MAAM,CAAC,eAAe,EAAER,aAAa,CAAC;IAE7CJ,MAAM,CAACc,GAAG,CAACZ,KAAK,GAAGA,KAAK;;IAExB;IACA;IACA,MAAMa,SAAS,GAAG,IAAIC,GAAG,CAAgD,CAAC;IAC1EhB,MAAM,CAACc,GAAG,CAACG,MAAM,GAAGF,SAAS;IAE7B,MAAMG,kBAAkB,GAAG7B,sBAAsB,CAACW,MAAM,EAAEC,OAAO,CAAC;IAElE,MAAMkB,eAA8C,GAAG;MACrDC,GAAG,EAAE,CACH;QACEC,MAAM,EACJH;MACJ,CAAC;IAEL,CAAC;IAED,MAAMI,gBAAsD,GAAG;MAC7DC,OAAO,EAAE;QACPC,KAAK,EAAE;MACT,CAAC;MACDJ,GAAG,EAAE,CACH;QACEC,MAAM,EACJH;MACJ,CAAC;IAEL,CAAC;IAED,MAAMO,MAAM,GAAG,CACb,GAAGnC,iBAAiB,CAClB6B,eAAe,EACfG,gBAAgB,EAChBd,8BACF,CAAC,EACD,GAAGhB,wBAAwB,CAAC2B,eAAe,EAAEG,gBAAgB,CAAC,EAC9D,GAAG/B,2BAA2B,CAAC4B,eAAe,EAAEG,gBAAgB,CAAC,EACjE,GAAGnC,0BAA0B,CAACgC,eAAe,CAAC,EAC9C,GAAG/B,yBAAyB,CAAC,CAAC,CAC/B;IAEDY,MAAM,CAAC0B,KAAK,CAACD,MAAkC,CAAC,EAAC;EACnD;AACF,CAAiC","ignoreList":[]}
|
|
@@ -42,7 +42,7 @@ function makeGetHandler(preparePageEventRequestOptions) {
|
|
|
42
42
|
const items = getFormSubmissionData(viewModel.context, viewModel.details);
|
|
43
43
|
|
|
44
44
|
// @ts-expect-error - function signature will be refactored in the next iteration of the formatter
|
|
45
|
-
const payload = format(items, model, undefined, undefined);
|
|
45
|
+
const payload = format(context, items, model, undefined, undefined);
|
|
46
46
|
const opts = {
|
|
47
47
|
payload
|
|
48
48
|
};
|