@defra/forms-engine-plugin 4.0.43 → 4.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.public/stylesheets/application.min.css +1 -1
- package/.public/stylesheets/application.min.css.map +1 -1
- package/.server/client/stylesheets/_payment-field.scss +8 -0
- package/.server/client/stylesheets/application.scss +2 -0
- package/.server/index.js +3 -1
- package/.server/index.js.map +1 -1
- package/.server/server/constants.d.ts +1 -0
- package/.server/server/constants.js +1 -0
- package/.server/server/constants.js.map +1 -1
- package/.server/server/forms/payment-test.yaml +42 -0
- package/.server/server/forms/register-as-a-unicorn-breeder.yaml +14 -0
- package/.server/server/plugins/engine/components/FormComponent.d.ts +1 -0
- package/.server/server/plugins/engine/components/FormComponent.js +1 -0
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/PaymentField.d.ts +135 -0
- package/.server/server/plugins/engine/components/PaymentField.js +228 -0
- package/.server/server/plugins/engine/components/PaymentField.js.map +1 -0
- package/.server/server/plugins/engine/components/PaymentField.types.d.ts +21 -0
- package/.server/server/plugins/engine/components/PaymentField.types.js +2 -0
- package/.server/server/plugins/engine/components/PaymentField.types.js.map +1 -0
- package/.server/server/plugins/engine/components/UkAddressField.d.ts +1 -1
- package/.server/server/plugins/engine/components/UkAddressField.js +3 -1
- package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
- package/.server/server/plugins/engine/components/helpers/components.js +3 -0
- package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
- package/.server/server/plugins/engine/components/index.d.ts +1 -0
- package/.server/server/plugins/engine/components/index.js +1 -0
- package/.server/server/plugins/engine/components/index.js.map +1 -1
- package/.server/server/plugins/engine/helpers.d.ts +1 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +3 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js +7 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js +34 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +22 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js +43 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +29 -8
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +2 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +17 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +173 -51
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/errors.d.ts +31 -0
- package/.server/server/plugins/engine/pageControllers/errors.js +59 -2
- package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +27 -0
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js +77 -0
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -0
- package/.server/server/plugins/engine/plugin.js +4 -1
- package/.server/server/plugins/engine/plugin.js.map +1 -1
- package/.server/server/plugins/engine/routes/index.js +8 -4
- package/.server/server/plugins/engine/routes/index.js.map +1 -1
- package/.server/server/plugins/engine/routes/payment-helper.d.ts +14 -0
- package/.server/server/plugins/engine/routes/payment-helper.js +41 -0
- package/.server/server/plugins/engine/routes/payment-helper.js.map +1 -0
- package/.server/server/plugins/engine/routes/payment-helper.test.js +81 -0
- package/.server/server/plugins/engine/routes/payment-helper.test.js.map +1 -0
- package/.server/server/plugins/engine/routes/payment.d.ts +8 -0
- package/.server/server/plugins/engine/routes/payment.js +140 -0
- package/.server/server/plugins/engine/routes/payment.js.map +1 -0
- package/.server/server/plugins/engine/routes/payment.test.js +187 -0
- package/.server/server/plugins/engine/routes/payment.test.js.map +1 -0
- package/.server/server/plugins/engine/services/localFormsService.js +6 -0
- package/.server/server/plugins/engine/services/localFormsService.js.map +1 -1
- package/.server/server/plugins/engine/types/schema.js +7 -0
- package/.server/server/plugins/engine/types/schema.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +19 -1
- package/.server/server/plugins/engine/types.js +4 -0
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/plugins/engine/validationHelpers.d.ts +1 -1
- package/.server/server/plugins/engine/validationHelpers.js.map +1 -1
- package/.server/server/plugins/engine/views/components/paymentfield.html +42 -0
- package/.server/server/plugins/engine/views/index.html +9 -1
- package/.server/server/plugins/engine/views/partials/form.html +20 -5
- package/.server/server/plugins/engine/views/summary.html +17 -1
- package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
- package/.server/server/plugins/payment/helper.d.ts +30 -0
- package/.server/server/plugins/payment/helper.js +49 -0
- package/.server/server/plugins/payment/helper.js.map +1 -0
- package/.server/server/plugins/payment/helper.test.js +37 -0
- package/.server/server/plugins/payment/helper.test.js.map +1 -0
- package/.server/server/plugins/payment/service.d.ts +40 -0
- package/.server/server/plugins/payment/service.js +129 -0
- package/.server/server/plugins/payment/service.js.map +1 -0
- package/.server/server/plugins/payment/service.test.js +162 -0
- package/.server/server/plugins/payment/service.test.js.map +1 -0
- package/.server/server/plugins/payment/types.d.ts +172 -0
- package/.server/server/plugins/payment/types.js +78 -0
- package/.server/server/plugins/payment/types.js.map +1 -0
- package/.server/server/types.d.ts +2 -0
- package/.server/server/types.js.map +1 -1
- package/.server/typings/hapi/index.d.js.map +1 -1
- package/README.md +12 -9
- package/package.json +2 -2
- package/src/client/stylesheets/_payment-field.scss +8 -0
- package/src/client/stylesheets/application.scss +2 -0
- package/src/index.ts +5 -1
- package/src/server/constants.js +1 -0
- package/src/server/forms/payment-test.yaml +42 -0
- package/src/server/forms/register-as-a-unicorn-breeder.yaml +14 -0
- package/src/server/plugins/engine/components/FormComponent.ts +1 -0
- package/src/server/plugins/engine/components/PaymentField.test.ts +611 -0
- package/src/server/plugins/engine/components/PaymentField.ts +367 -0
- package/src/server/plugins/engine/components/PaymentField.types.ts +21 -0
- package/src/server/plugins/engine/components/UkAddressField.ts +2 -1
- package/src/server/plugins/engine/components/helpers/components.ts +5 -0
- package/src/server/plugins/engine/components/index.ts +1 -0
- package/src/server/plugins/engine/models/SummaryViewModel.ts +8 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.payment.test.ts +147 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +105 -103
- package/src/server/plugins/engine/outputFormatters/human/v1.ts +61 -2
- package/src/server/plugins/engine/outputFormatters/machine/v2.payment.test.ts +115 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.ts +60 -1
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +32 -6
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +247 -72
- package/src/server/plugins/engine/pageControllers/errors.test.ts +13 -1
- package/src/server/plugins/engine/pageControllers/errors.ts +79 -4
- package/src/server/plugins/engine/pageControllers/helpers/submission.test.ts +299 -0
- package/src/server/plugins/engine/pageControllers/helpers/submission.ts +110 -0
- package/src/server/plugins/engine/plugin.ts +11 -6
- package/src/server/plugins/engine/routes/index.ts +17 -16
- package/src/server/plugins/engine/routes/payment-helper.js +39 -0
- package/src/server/plugins/engine/routes/payment-helper.test.js +90 -0
- package/src/server/plugins/engine/routes/payment.js +151 -0
- package/src/server/plugins/engine/routes/payment.test.js +180 -0
- package/src/server/plugins/engine/services/localFormsService.js +7 -0
- package/src/server/plugins/engine/types/schema.ts +9 -0
- package/src/server/plugins/engine/types.ts +24 -1
- package/src/server/plugins/engine/validationHelpers.ts +1 -1
- package/src/server/plugins/engine/views/components/paymentfield.html +42 -0
- package/src/server/plugins/engine/views/index.html +9 -1
- package/src/server/plugins/engine/views/partials/form.html +20 -5
- package/src/server/plugins/engine/views/summary.html +17 -1
- package/src/server/plugins/payment/helper.js +56 -0
- package/src/server/plugins/payment/helper.test.js +52 -0
- package/src/server/plugins/payment/service.js +171 -0
- package/src/server/plugins/payment/service.test.js +205 -0
- package/src/server/plugins/payment/types.js +77 -0
- package/src/server/types.ts +2 -0
- package/src/typings/hapi/index.d.ts +1 -0
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { config } from "../../../../../config/index.js";
|
|
2
|
-
import { FileUploadField } from "../../components/index.js";
|
|
2
|
+
import { FileUploadField, PaymentField } from "../../components/index.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Payment data for the machine output format
|
|
6
|
+
* Defined locally to avoid circular dependency with types.ts
|
|
7
|
+
*/
|
|
8
|
+
|
|
3
9
|
const designerUrl = config.get('designerUrl');
|
|
4
10
|
export function format(context, items, model, _submitResponse, _formStatus) {
|
|
5
11
|
const now = new Date();
|
|
@@ -43,6 +49,15 @@ export function format(context, items, model, _submitResponse, _formStatus) {
|
|
|
43
49
|
* userDownloadLink: 'https://forms-designer/file-download/123-456-789'
|
|
44
50
|
* }
|
|
45
51
|
* ]
|
|
52
|
+
* },
|
|
53
|
+
* payments: {
|
|
54
|
+
* paymentComponentName: {
|
|
55
|
+
* paymentId: 'abc123',
|
|
56
|
+
* reference: 'REF-123',
|
|
57
|
+
* amount: 10.00,
|
|
58
|
+
* description: 'Application fee',
|
|
59
|
+
* createdAt: '2025-01-23T10:30:00.000Z'
|
|
60
|
+
* }
|
|
46
61
|
* }
|
|
47
62
|
* }
|
|
48
63
|
*/
|
|
@@ -61,6 +76,11 @@ export function categoriseData(items) {
|
|
|
61
76
|
output.repeaters[name] = extractRepeaters(item);
|
|
62
77
|
} else if (isFileUploadFieldItem(item)) {
|
|
63
78
|
output.files[name] = extractFileUploads(item);
|
|
79
|
+
} else if (isPaymentFieldItem(item)) {
|
|
80
|
+
const payment = extractPayment(item);
|
|
81
|
+
if (payment) {
|
|
82
|
+
output.payment = payment;
|
|
83
|
+
}
|
|
64
84
|
} else {
|
|
65
85
|
output.main[name] = item.field.getFormValueFromState(state);
|
|
66
86
|
}
|
|
@@ -110,4 +130,26 @@ function extractFileUploads(item) {
|
|
|
110
130
|
function isFileUploadFieldItem(item) {
|
|
111
131
|
return item.field instanceof FileUploadField;
|
|
112
132
|
}
|
|
133
|
+
function isPaymentFieldItem(item) {
|
|
134
|
+
return item.field instanceof PaymentField;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Returns the "payments" section of the response body
|
|
139
|
+
* @param item - the payment item in the form
|
|
140
|
+
* @returns the payment data
|
|
141
|
+
*/
|
|
142
|
+
function extractPayment(item) {
|
|
143
|
+
const paymentState = item.field.getPaymentStateFromState(item.state);
|
|
144
|
+
if (!paymentState) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
paymentId: paymentState.paymentId,
|
|
149
|
+
reference: paymentState.reference,
|
|
150
|
+
amount: paymentState.amount,
|
|
151
|
+
description: paymentState.description,
|
|
152
|
+
createdAt: paymentState.preAuth?.createdAt ?? ''
|
|
153
|
+
};
|
|
154
|
+
}
|
|
113
155
|
//# sourceMappingURL=v2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.js","names":["config","FileUploadField","designerUrl","get","format","context","items","model","_submitResponse","_formStatus","now","Date","categorisedData","categoriseData","meta","schemaVersion","timestamp","toISOString","definition","def","referenceNumber","data","body","JSON","stringify","output","main","repeaters","files","forEach","item","name","state","extractRepeaters","isFileUploadFieldItem","extractFileUploads","field","getFormValueFromState","subItems","inputRepeaterItem","outputRepeaterItem","repeaterComponent","push","fileUploadState","map","fileState","file","status","form","fileId","fileName","filename","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 {
|
|
1
|
+
{"version":3,"file":"v2.js","names":["config","FileUploadField","PaymentField","designerUrl","get","format","context","items","model","_submitResponse","_formStatus","now","Date","categorisedData","categoriseData","meta","schemaVersion","timestamp","toISOString","definition","def","referenceNumber","data","body","JSON","stringify","output","main","repeaters","files","forEach","item","name","state","extractRepeaters","isFileUploadFieldItem","extractFileUploads","isPaymentFieldItem","payment","extractPayment","field","getFormValueFromState","subItems","inputRepeaterItem","outputRepeaterItem","repeaterComponent","push","fileUploadState","map","fileState","file","status","form","fileId","fileName","filename","userDownloadLink","paymentState","getPaymentStateFromState","undefined","paymentId","reference","amount","description","createdAt","preAuth"],"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 {\n FileUploadField,\n PaymentField\n} 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 {\n type FileUploadFieldDetailitem,\n type FormAdapterFile,\n type FormContext,\n type RichFormValue\n} from '~/src/server/plugins/engine/types.js'\n\n/**\n * Payment data for the machine output format\n * Defined locally to avoid circular dependency with types.ts\n */\ninterface PaymentOutput {\n paymentId: string\n reference: string\n amount: number\n description: string\n createdAt: string\n}\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 meta: Record<string, unknown> = {\n schemaVersion: '2',\n timestamp: now.toISOString(),\n definition: model.def,\n referenceNumber: context.referenceNumber\n }\n\n const data = {\n meta,\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 * fileName: 'example.pdf',\n * userDownloadLink: 'https://forms-designer/file-download/123-456-789'\n * }\n * ]\n * },\n * payments: {\n * paymentComponentName: {\n * paymentId: 'abc123',\n * reference: 'REF-123',\n * amount: 10.00,\n * description: 'Application fee',\n * createdAt: '2025-01-23T10:30:00.000Z'\n * }\n * }\n * }\n */\nexport function categoriseData(items: DetailItem[]) {\n const output: {\n main: Record<string, RichFormValue>\n repeaters: Record<string, Record<string, RichFormValue>[]>\n files: Record<\n string,\n { fileId: string; fileName: string; userDownloadLink: string }[]\n >\n payment?: PaymentOutput\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 if (isPaymentFieldItem(item)) {\n const payment = extractPayment(item)\n if (payment) {\n output.payment = payment\n }\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(\n item: FileUploadFieldDetailitem\n): FormAdapterFile[] {\n const fileUploadState = item.field.getFormValueFromState(item.state) ?? []\n\n return fileUploadState.map((fileState) => {\n const { file } = fileState.status.form\n return {\n fileId: file.fileId,\n fileName: file.filename,\n userDownloadLink: `${designerUrl}/file-download/${file.fileId}`\n }\n })\n}\n\nfunction isFileUploadFieldItem(\n item: DetailItemField\n): item is FileUploadFieldDetailitem {\n return item.field instanceof FileUploadField\n}\n\nfunction isPaymentFieldItem(item: DetailItemField): item is DetailItemField & {\n field: PaymentField\n} {\n return item.field instanceof PaymentField\n}\n\n/**\n * Returns the \"payments\" section of the response body\n * @param item - the payment item in the form\n * @returns the payment data\n */\nfunction extractPayment(\n item: DetailItemField & { field: PaymentField }\n): PaymentOutput | undefined {\n const paymentState = item.field.getPaymentStateFromState(item.state)\n\n if (!paymentState) {\n return undefined\n }\n\n return {\n paymentId: paymentState.paymentId,\n reference: paymentState.reference,\n amount: paymentState.amount,\n description: paymentState.description,\n createdAt: paymentState.preAuth?.createdAt ?? ''\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { ComponentType, ControllerType, Engine, hasComponents, hasNext, hasRepeater } from '@defra/forms-model';
|
|
2
2
|
import Boom from '@hapi/boom';
|
|
3
|
-
import { COMPONENT_STATE_ERROR, EXTERNAL_STATE_APPENDAGE, EXTERNAL_STATE_PAYLOAD } from "../../../constants.js";
|
|
3
|
+
import { COMPONENT_STATE_ERROR, EXTERNAL_STATE_APPENDAGE, EXTERNAL_STATE_PAYLOAD, PAYMENT_EXPIRED_NOTIFICATION } from "../../../constants.js";
|
|
4
4
|
import { ComponentCollection } from "../components/ComponentCollection.js";
|
|
5
5
|
import { optionalText } from "../components/constants.js";
|
|
6
|
-
import { getCacheService, getErrors, getSaveAndExitHelpers, normalisePath, proceed } from "../helpers.js";
|
|
6
|
+
import { checkFormStatus, getCacheService, getErrors, getSaveAndExitHelpers, normalisePath, proceed } from "../helpers.js";
|
|
7
7
|
import { PageController } from "./PageController.js";
|
|
8
8
|
import { clearNotYetValidatedState, prefillStateFromQueryParameters } from "./helpers/state.js";
|
|
9
9
|
import { getComponentsByType } from "../validationHelpers.js";
|
|
10
|
-
import { FormAction } from "../../../routes/types.js";
|
|
10
|
+
import { FormAction, FormStatus } from "../../../routes/types.js";
|
|
11
11
|
import { actionSchema, crumbSchema, paramsSchema } from "../../../schemas/index.js";
|
|
12
12
|
import { merge } from "../../../services/cacheService.js";
|
|
13
13
|
export class QuestionPageController extends PageController {
|
|
@@ -132,6 +132,15 @@ export class QuestionPageController extends PageController {
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
+
const hasIncompletePayment = components.some(({
|
|
136
|
+
model
|
|
137
|
+
}) => {
|
|
138
|
+
if ('paymentState' in model) {
|
|
139
|
+
const paymentState = model.paymentState;
|
|
140
|
+
return !paymentState?.preAuth?.status;
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
});
|
|
135
144
|
return {
|
|
136
145
|
...viewModel,
|
|
137
146
|
backLink: this.getBackLink(request, context),
|
|
@@ -139,7 +148,8 @@ export class QuestionPageController extends PageController {
|
|
|
139
148
|
showTitle,
|
|
140
149
|
components,
|
|
141
150
|
errors,
|
|
142
|
-
allowSaveAndExit: this.shouldShowSaveAndExit(request.server)
|
|
151
|
+
allowSaveAndExit: this.shouldShowSaveAndExit(request.server),
|
|
152
|
+
showSubmitButton: !hasIncompletePayment
|
|
143
153
|
};
|
|
144
154
|
}
|
|
145
155
|
getRelevantPath(request, context) {
|
|
@@ -336,6 +346,8 @@ export class QuestionPageController extends PageController {
|
|
|
336
346
|
const flashedError = request.yar.flash(COMPONENT_STATE_ERROR);
|
|
337
347
|
const flashedErrors = !Array.isArray(flashedError) ? [flashedError] : [];
|
|
338
348
|
viewModel.errors = (viewModel.errors ?? []).concat(flashedErrors);
|
|
349
|
+
const paymentExpiredFlash = request.yar.flash(PAYMENT_EXPIRED_NOTIFICATION);
|
|
350
|
+
viewModel.showPaymentExpiredNotification = !Array.isArray(paymentExpiredFlash);
|
|
339
351
|
|
|
340
352
|
/**
|
|
341
353
|
* Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it
|
|
@@ -432,7 +444,7 @@ export class QuestionPageController extends PageController {
|
|
|
432
444
|
} = context;
|
|
433
445
|
const action = request.payload.action;
|
|
434
446
|
if (action?.startsWith(FormAction.External)) {
|
|
435
|
-
return this.dispatchExternal(request, h, context);
|
|
447
|
+
return await this.dispatchExternal(request, h, context);
|
|
436
448
|
}
|
|
437
449
|
|
|
438
450
|
/**
|
|
@@ -460,7 +472,7 @@ export class QuestionPageController extends PageController {
|
|
|
460
472
|
return this.proceed(request, h, this.getNextPath(context));
|
|
461
473
|
};
|
|
462
474
|
}
|
|
463
|
-
dispatchExternal(request, h, context) {
|
|
475
|
+
async dispatchExternal(request, h, context) {
|
|
464
476
|
const {
|
|
465
477
|
externalComponents
|
|
466
478
|
} = getComponentsByType();
|
|
@@ -493,11 +505,20 @@ export class QuestionPageController extends PageController {
|
|
|
493
505
|
|
|
494
506
|
// Clear any previous state appendage
|
|
495
507
|
request.yar.clear(EXTERNAL_STATE_APPENDAGE);
|
|
496
|
-
|
|
508
|
+
|
|
509
|
+
// Determine if this is a live form (not preview/draft)
|
|
510
|
+
const {
|
|
511
|
+
state,
|
|
512
|
+
isPreview
|
|
513
|
+
} = checkFormStatus(request.params);
|
|
514
|
+
const isLive = state === FormStatus.Live;
|
|
515
|
+
return await selectedComponent.dispatcher(request, h, {
|
|
497
516
|
component,
|
|
498
517
|
controller: this,
|
|
499
518
|
sourceUrl: request.url.toString(),
|
|
500
|
-
actionArgs: args
|
|
519
|
+
actionArgs: args,
|
|
520
|
+
isLive,
|
|
521
|
+
isPreview
|
|
501
522
|
});
|
|
502
523
|
}
|
|
503
524
|
proceed(request, h, nextPath) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuestionPageController.js","names":["ComponentType","ControllerType","Engine","hasComponents","hasNext","hasRepeater","Boom","COMPONENT_STATE_ERROR","EXTERNAL_STATE_APPENDAGE","EXTERNAL_STATE_PAYLOAD","ComponentCollection","optionalText","getCacheService","getErrors","getSaveAndExitHelpers","normalisePath","proceed","PageController","clearNotYetValidatedState","prefillStateFromQueryParameters","getComponentsByType","FormAction","actionSchema","crumbSchema","paramsSchema","merge","QuestionPageController","collection","errorSummaryTitle","allowSaveAndExit","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","shouldShowSaveAndExit","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","redirect","url","origin","pathname","getViewErrors","flashedError","yar","flash","flashedErrors","concat","hasMissingNotificationEmail","view","isForceAccess","formsService","services","getFormMetadata","includes","notificationEmail","slug","returnUrl","href","backPath","endsWith","getHref","makePostRouteHandler","startsWith","External","dispatchExternal","SaveAndExit","handleSaveAndExit","externalComponents","externalActionsWithArgs","split","externalActionArgs","arg","args","Object","fromEntries","componentName","componentDefMap","get","componentType","internal","selectedComponent","stashedPayload","clear","dispatcher","sourceUrl","toString","actionArgs","nextPath","nextUrl","saveAndExit","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 RouteOptions } from '@hapi/hapi'\nimport { type ValidationErrorItem } from 'joi'\n\nimport {\n COMPONENT_STATE_ERROR,\n EXTERNAL_STATE_APPENDAGE,\n EXTERNAL_STATE_PAYLOAD\n} from '~/src/server/constants.js'\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 getSaveAndExitHelpers,\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 clearNotYetValidatedState,\n prefillStateFromQueryParameters\n} from '~/src/server/plugins/engine/pageControllers/helpers/state.js'\nimport {\n type AnyFormRequest,\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 { getComponentsByType } from '~/src/server/plugins/engine/validationHelpers.js'\nimport {\n FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs,\n type FormResponseToolkit\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 allowSaveAndExit = 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 allowSaveAndExit: this.shouldShowSaveAndExit(request.server)\n }\n }\n\n getRelevantPath(request: AnyFormRequest, context: FormContext) {\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: AnyFormRequest) {\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(request: AnyFormRequest, state: FormSubmissionState) {\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 // Clear any 'not yet validated' state before saving to cache\n return cacheService.setState(request, clearNotYetValidatedState(state))\n }\n\n async mergeState(\n request: AnyFormRequest,\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: FormResponseToolkit\n ) => {\n const { collection, model, viewName } = this\n const { evaluationState } = context\n\n // Copy any URL params into the form state (if not already done so)\n if (await prefillStateFromQueryParameters(request, this)) {\n // Forward to same page without query string\n return h.redirect(`${request.url.origin}${request.url.pathname}`)\n }\n\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n const flashedError = request.yar.flash(COMPONENT_STATE_ERROR)\n const flashedErrors = !Array.isArray(flashedError) ? [flashedError] : []\n\n viewModel.errors = (viewModel.errors ?? []).concat(flashedErrors)\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: FormResponseToolkit\n ) => {\n const { collection, viewName, model } = this\n const { isForceAccess, state, evaluationState } = context\n const action = request.payload.action\n\n if (action?.startsWith(FormAction.External)) {\n return this.dispatchExternal(request, h, context)\n }\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 // Save state\n await this.setState(request, state)\n\n // Check if this is a save-and-exit action\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n // Proceed to the next page\n return this.proceed(request, h, this.getNextPath(context))\n }\n }\n\n private dispatchExternal(\n request: FormRequestPayload,\n h: FormResponseToolkit,\n context: FormContext\n ) {\n const { externalComponents } = getComponentsByType()\n const action = request.payload.action ?? ''\n\n // Find the external action and arguments\n // `external-{componentName}--{argname1}:{argvalue1}--{argname2}:{argvalue2}`\n // E.g. external-abcdef--amount:10--step:manual\n const externalActionsWithArgs = action\n .slice(`${FormAction.External}-`.length)\n .split('--')\n\n const externalActionArgs = externalActionsWithArgs\n .slice(1)\n .map((arg) => arg.split(':'))\n\n const args = Object.fromEntries(externalActionArgs) as Record<\n string,\n string\n >\n\n const componentName = externalActionsWithArgs[0]\n const component = this.model.componentDefMap.get(componentName)\n const componentType = component?.type\n\n if (!componentType) {\n throw Boom.internal(\n `External component of type ${componentType} not found`\n )\n }\n\n const selectedComponent = externalComponents.get(componentType)\n\n if (!selectedComponent) {\n throw Boom.internal(`External component ${componentName} not found`)\n }\n\n // Stash payload without crumb and action\n const stashedPayload = {\n ...context.payload,\n crumb: undefined,\n action: undefined\n }\n request.yar.flash(EXTERNAL_STATE_PAYLOAD, stashedPayload, true)\n\n // Clear any previous state appendage\n request.yar.clear(EXTERNAL_STATE_APPENDAGE)\n\n return selectedComponent.dispatcher(request, h, {\n component,\n controller: this,\n sourceUrl: request.url.toString(),\n actionArgs: args\n })\n }\n\n proceed(\n request: FormContextRequest,\n h: FormResponseToolkit,\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-exit action\n */\n handleSaveAndExit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const saveAndExit = getSaveAndExitHelpers(request.server)\n\n if (!saveAndExit) {\n throw Boom.internal('Server misconfigured for save and exit')\n }\n\n return saveAndExit(request, h, context)\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","COMPONENT_STATE_ERROR","EXTERNAL_STATE_APPENDAGE","EXTERNAL_STATE_PAYLOAD","PAYMENT_EXPIRED_NOTIFICATION","ComponentCollection","optionalText","checkFormStatus","getCacheService","getErrors","getSaveAndExitHelpers","normalisePath","proceed","PageController","clearNotYetValidatedState","prefillStateFromQueryParameters","getComponentsByType","FormAction","FormStatus","actionSchema","crumbSchema","paramsSchema","merge","QuestionPageController","collection","errorSummaryTitle","allowSaveAndExit","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","hasIncompletePayment","paymentState","preAuth","status","backLink","getBackLink","shouldShowSaveAndExit","server","showSubmitButton","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","redirect","url","origin","pathname","getViewErrors","flashedError","yar","flash","flashedErrors","concat","paymentExpiredFlash","showPaymentExpiredNotification","hasMissingNotificationEmail","view","isForceAccess","formsService","services","getFormMetadata","includes","notificationEmail","slug","returnUrl","href","backPath","endsWith","getHref","makePostRouteHandler","startsWith","External","dispatchExternal","SaveAndExit","handleSaveAndExit","externalComponents","externalActionsWithArgs","split","externalActionArgs","arg","args","Object","fromEntries","componentName","componentDefMap","get","componentType","internal","selectedComponent","stashedPayload","clear","isPreview","isLive","Live","dispatcher","sourceUrl","toString","actionArgs","nextPath","nextUrl","saveAndExit","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 RouteOptions } from '@hapi/hapi'\nimport { type ValidationErrorItem } from 'joi'\n\nimport {\n COMPONENT_STATE_ERROR,\n EXTERNAL_STATE_APPENDAGE,\n EXTERNAL_STATE_PAYLOAD,\n PAYMENT_EXPIRED_NOTIFICATION\n} from '~/src/server/constants.js'\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 checkFormStatus,\n getCacheService,\n getErrors,\n getSaveAndExitHelpers,\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 clearNotYetValidatedState,\n prefillStateFromQueryParameters\n} from '~/src/server/plugins/engine/pageControllers/helpers/state.js'\nimport {\n type AnyFormRequest,\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 { getComponentsByType } from '~/src/server/plugins/engine/validationHelpers.js'\nimport {\n FormAction,\n FormStatus,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs,\n type FormResponseToolkit\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 allowSaveAndExit = 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 const hasIncompletePayment = components.some(({ model }) => {\n if ('paymentState' in model) {\n const paymentState = model.paymentState as\n | { preAuth?: { status?: string } }\n | undefined\n return !paymentState?.preAuth?.status\n }\n return false\n })\n\n return {\n ...viewModel,\n backLink: this.getBackLink(request, context),\n context,\n showTitle,\n components,\n errors,\n allowSaveAndExit: this.shouldShowSaveAndExit(request.server),\n showSubmitButton: !hasIncompletePayment\n }\n }\n\n getRelevantPath(request: AnyFormRequest, context: FormContext) {\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: AnyFormRequest) {\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(request: AnyFormRequest, state: FormSubmissionState) {\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 // Clear any 'not yet validated' state before saving to cache\n return cacheService.setState(request, clearNotYetValidatedState(state))\n }\n\n async mergeState(\n request: AnyFormRequest,\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: FormResponseToolkit\n ) => {\n const { collection, model, viewName } = this\n const { evaluationState } = context\n\n // Copy any URL params into the form state (if not already done so)\n if (await prefillStateFromQueryParameters(request, this)) {\n // Forward to same page without query string\n return h.redirect(`${request.url.origin}${request.url.pathname}`)\n }\n\n const viewModel = this.getViewModel(request, context)\n viewModel.errors = collection.getViewErrors(viewModel.errors)\n\n const flashedError = request.yar.flash(COMPONENT_STATE_ERROR)\n const flashedErrors = !Array.isArray(flashedError) ? [flashedError] : []\n\n viewModel.errors = (viewModel.errors ?? []).concat(flashedErrors)\n\n const paymentExpiredFlash = request.yar.flash(\n PAYMENT_EXPIRED_NOTIFICATION\n )\n viewModel.showPaymentExpiredNotification =\n !Array.isArray(paymentExpiredFlash)\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: FormResponseToolkit\n ) => {\n const { collection, viewName, model } = this\n const { isForceAccess, state, evaluationState } = context\n const action = request.payload.action\n\n if (action?.startsWith(FormAction.External)) {\n return await this.dispatchExternal(request, h, context)\n }\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 // Save state\n await this.setState(request, state)\n\n // Check if this is a save-and-exit action\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n // Proceed to the next page\n return this.proceed(request, h, this.getNextPath(context))\n }\n }\n\n private async dispatchExternal(\n request: FormRequestPayload,\n h: FormResponseToolkit,\n context: FormContext\n ) {\n const { externalComponents } = getComponentsByType()\n const action = request.payload.action ?? ''\n\n // Find the external action and arguments\n // `external-{componentName}--{argname1}:{argvalue1}--{argname2}:{argvalue2}`\n // E.g. external-abcdef--amount:10--step:manual\n const externalActionsWithArgs = action\n .slice(`${FormAction.External}-`.length)\n .split('--')\n\n const externalActionArgs = externalActionsWithArgs\n .slice(1)\n .map((arg) => arg.split(':'))\n\n const args = Object.fromEntries(externalActionArgs) as Record<\n string,\n string\n >\n\n const componentName = externalActionsWithArgs[0]\n const component = this.model.componentDefMap.get(componentName)\n const componentType = component?.type\n\n if (!componentType) {\n throw Boom.internal(\n `External component of type ${componentType} not found`\n )\n }\n\n const selectedComponent = externalComponents.get(componentType)\n\n if (!selectedComponent) {\n throw Boom.internal(`External component ${componentName} not found`)\n }\n\n // Stash payload without crumb and action\n const stashedPayload = {\n ...context.payload,\n crumb: undefined,\n action: undefined\n }\n request.yar.flash(EXTERNAL_STATE_PAYLOAD, stashedPayload, true)\n\n // Clear any previous state appendage\n request.yar.clear(EXTERNAL_STATE_APPENDAGE)\n\n // Determine if this is a live form (not preview/draft)\n const { state, isPreview } = checkFormStatus(request.params)\n const isLive = state === FormStatus.Live\n\n return await selectedComponent.dispatcher(request, h, {\n component,\n controller: this,\n sourceUrl: request.url.toString(),\n actionArgs: args,\n isLive,\n isPreview\n })\n }\n\n proceed(\n request: FormContextRequest,\n h: FormResponseToolkit,\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-exit action\n */\n handleSaveAndExit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const saveAndExit = getSaveAndExitHelpers(request.server)\n\n if (!saveAndExit) {\n throw Boom.internal('Server misconfigured for save and exit')\n }\n\n return saveAndExit(request, h, context)\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":[]}
|
|
@@ -15,6 +15,8 @@ export declare class StartPageController extends QuestionPageController {
|
|
|
15
15
|
errors?: import("~/src/server/plugins/engine/types.js").FormSubmissionError[];
|
|
16
16
|
hasMissingNotificationEmail?: boolean;
|
|
17
17
|
allowSaveAndExit: boolean;
|
|
18
|
+
showSubmitButton?: boolean;
|
|
19
|
+
showPaymentExpiredNotification?: boolean;
|
|
18
20
|
page: import("./PageController.js").PageController;
|
|
19
21
|
name?: string;
|
|
20
22
|
pageTitle: string;
|
|
@@ -13,6 +13,7 @@ export declare class SummaryPageController extends QuestionPageController {
|
|
|
13
13
|
*/
|
|
14
14
|
constructor(model: FormModel, pageDef: Page);
|
|
15
15
|
getSummaryViewModel(request: FormContextRequest, context: FormContext): SummaryViewModel;
|
|
16
|
+
private buildPaymentDetails;
|
|
16
17
|
/**
|
|
17
18
|
* Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,
|
|
18
19
|
*/
|
|
@@ -23,6 +24,22 @@ export declare class SummaryPageController extends QuestionPageController {
|
|
|
23
24
|
*/
|
|
24
25
|
makePostRouteHandler(): (request: FormRequestPayload, context: FormContext, h: FormResponseToolkit) => Promise<import("@hapi/hapi").ResponseObject>;
|
|
25
26
|
handleFormSubmit(request: FormRequestPayload, context: FormContext, h: FormResponseToolkit): Promise<import("@hapi/hapi").ResponseObject>;
|
|
27
|
+
/**
|
|
28
|
+
* Handles errors during form submission
|
|
29
|
+
*/
|
|
30
|
+
private handleSubmissionError;
|
|
31
|
+
/**
|
|
32
|
+
* Handles InvalidComponentStateError during submission
|
|
33
|
+
*/
|
|
34
|
+
private handleInvalidComponentStateError;
|
|
35
|
+
/**
|
|
36
|
+
* Handles PaymentPreAuthError during submission
|
|
37
|
+
*/
|
|
38
|
+
private handlePaymentPreAuthError;
|
|
39
|
+
/**
|
|
40
|
+
* Handles PaymentSubmissionError during submission
|
|
41
|
+
*/
|
|
42
|
+
private handlePaymentSubmissionError;
|
|
26
43
|
get postRouteOptions(): RouteOptions<FormRequestPayloadRefs>;
|
|
27
44
|
}
|
|
28
45
|
export declare function submitForm(context: FormContext, metadata: FormMetadata, request: FormRequestPayload, summaryViewModel: SummaryViewModel, model: FormModel, emailAddress: string, formMetadata: FormMetadata): Promise<void>;
|