@defra/forms-engine-plugin 1.4.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.server/server/plugins/engine/README.md +2 -46
- package/.server/server/plugins/engine/configureEnginePlugin.d.ts +1 -1
- package/.server/server/plugins/engine/configureEnginePlugin.js +5 -2
- package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
- package/.server/server/plugins/engine/helpers.d.ts +11 -0
- package/.server/server/plugins/engine/helpers.js +7 -1
- package/.server/server/plugins/engine/helpers.js.map +1 -1
- package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +1 -1
- package/.server/server/plugins/engine/models/SummaryViewModel.js +1 -1
- package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
- package/.server/server/plugins/engine/options.js +5 -3
- package/.server/server/plugins/engine/options.js.map +1 -1
- package/.server/server/plugins/engine/options.test.js +18 -9
- package/.server/server/plugins/engine/options.test.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/PageController.d.ts +3 -1
- package/.server/server/plugins/engine/pageControllers/PageController.js +5 -1
- package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +2 -4
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +2 -2
- package/.server/server/plugins/engine/pageControllers/StartPageController.js +1 -3
- package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/StatusPageController.d.ts +1 -0
- package/.server/server/plugins/engine/pageControllers/StatusPageController.js +1 -0
- package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +0 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +1 -4
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/TerminalPageController.d.ts +1 -0
- package/.server/server/plugins/engine/pageControllers/TerminalPageController.js +1 -0
- package/.server/server/plugins/engine/pageControllers/TerminalPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/__stubs__/request.d.ts +4 -0
- package/.server/server/plugins/engine/pageControllers/__stubs__/request.js +14 -0
- package/.server/server/plugins/engine/pageControllers/__stubs__/request.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/__stubs__/server.d.ts +3 -0
- package/.server/server/plugins/engine/pageControllers/__stubs__/server.js +23 -0
- package/.server/server/plugins/engine/pageControllers/__stubs__/server.js.map +1 -0
- package/.server/server/plugins/engine/plugin.js +5 -6
- package/.server/server/plugins/engine/plugin.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +7 -5
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/types.d.ts +2 -1
- package/.server/server/types.js.map +1 -1
- package/.server/typings/hapi/index.d.js.map +1 -1
- package/package.json +1 -1
- package/src/server/plugins/engine/README.md +2 -46
- package/src/server/plugins/engine/configureEnginePlugin.ts +4 -2
- package/src/server/plugins/engine/helpers.test.ts +3 -2
- package/src/server/plugins/engine/helpers.ts +9 -1
- package/src/server/plugins/engine/models/FormModel.test.ts +11 -10
- package/src/server/plugins/engine/models/SummaryViewModel.test.ts +7 -5
- package/src/server/plugins/engine/models/SummaryViewModel.ts +1 -1
- package/src/server/plugins/engine/options.js +5 -3
- package/src/server/plugins/engine/options.test.js +22 -11
- package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +3 -3
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +12 -1
- package/src/server/plugins/engine/pageControllers/PageController.test.ts +9 -0
- package/src/server/plugins/engine/pageControllers/PageController.ts +10 -1
- package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +34 -28
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +2 -5
- package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +19 -4
- package/src/server/plugins/engine/pageControllers/StartPageController.test.ts +32 -0
- package/src/server/plugins/engine/pageControllers/StartPageController.ts +2 -4
- package/src/server/plugins/engine/pageControllers/StatusPageController.test.ts +32 -0
- package/src/server/plugins/engine/pageControllers/StatusPageController.ts +1 -0
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +1 -5
- package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +9 -0
- package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +1 -0
- package/src/server/plugins/engine/pageControllers/__stubs__/request.ts +21 -0
- package/src/server/plugins/engine/pageControllers/__stubs__/server.ts +27 -0
- package/src/server/plugins/engine/plugin.ts +6 -6
- package/src/server/plugins/engine/types.ts +14 -9
- package/src/server/types.ts +2 -0
- package/src/typings/hapi/index.d.ts +2 -0
|
@@ -9,6 +9,7 @@ import { merge } from "../../../services/cacheService.js";
|
|
|
9
9
|
export class QuestionPageController extends PageController {
|
|
10
10
|
collection;
|
|
11
11
|
errorSummaryTitle = 'There is a problem';
|
|
12
|
+
allowSaveAndReturn = true;
|
|
12
13
|
constructor(model, pageDef) {
|
|
13
14
|
super(model, pageDef);
|
|
14
15
|
|
|
@@ -134,7 +135,7 @@ export class QuestionPageController extends PageController {
|
|
|
134
135
|
showTitle,
|
|
135
136
|
components,
|
|
136
137
|
errors,
|
|
137
|
-
allowSaveAndReturn: this.shouldShowSaveAndReturn()
|
|
138
|
+
allowSaveAndReturn: this.shouldShowSaveAndReturn(request.server)
|
|
138
139
|
};
|
|
139
140
|
}
|
|
140
141
|
getRelevantPath(request, context) {
|
|
@@ -447,9 +448,6 @@ export class QuestionPageController extends PageController {
|
|
|
447
448
|
|
|
448
449
|
return proceed(request, h, nextUrl);
|
|
449
450
|
}
|
|
450
|
-
shouldShowSaveAndReturn() {
|
|
451
|
-
return true;
|
|
452
|
-
}
|
|
453
451
|
|
|
454
452
|
/**
|
|
455
453
|
* Handle save-and-return action by processing form data and redirecting to exit page
|
|
@@ -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","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","allowSaveAndReturn","shouldShowSaveAndReturn","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","server","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\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()\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 shouldShowSaveAndReturn(): boolean {\n return true\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","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":"AAAA,SACEA,aAAa,EACbC,cAAc,EACdC,MAAM,EACNC,aAAa,EACbC,OAAO,EACPC,WAAW,QAGN,oBAAoB;AAI3B,SAASC,mBAAmB;AAC5B,SAASC,YAAY;AAErB,SACEC,eAAe,EACfC,SAAS,EACTC,aAAa,EACbC,OAAO;AAGT,SAASC,cAAc;AAWvB,SACEC,UAAU;AAMZ,SACEC,YAAY,EACZC,WAAW,EACXC,YAAY;AAEd,SAASC,KAAK;AAEd,OAAO,MAAMC,sBAAsB,SAASN,cAAc,CAAC;EACzDO,UAAU;EACVC,iBAAiB,GAAG,oBAAoB;EACxCC,kBAAkB,GAAG,IAAI;EAEzBC,WAAWA,CAACC,KAAgB,EAAEC,OAAa,EAAE;IAC3C,KAAK,CAACD,KAAK,EAAEC,OAAO,CAAC;;IAErB;IACA,IAAI,CAACL,UAAU,GAAG,IAAIb,mBAAmB,CACvCH,aAAa,CAACqB,OAAO,CAAC,GAAGA,OAAO,CAACC,UAAU,GAAG,EAAE,EAChD;MAAEF,KAAK;MAAEG,IAAI,EAAE;IAAK,CACtB,CAAC;IAED,IAAI,CAACP,UAAU,CAACQ,UAAU,GAAG,IAAI,CAACR,UAAU,CAACQ,UAAU,CAACC,IAAI,CAAC;MAC3DC,KAAK,EAAEd,WAAW;MAClBe,MAAM,EAAEhB;IACV,CAAC,CAAC;EACJ;EAEA,IAAIiB,IAAIA,CAAA,EAAW;IACjB,MAAM;MAAEC,GAAG;MAAER;IAAQ,CAAC,GAAG,IAAI;IAE7B,IAAI,CAACpB,OAAO,CAACoB,OAAO,CAAC,EAAE;MACrB,OAAO,EAAE;IACX;;IAEA;IACA,OAAOA,OAAO,CAACO,IAAI,CAACE,MAAM,CAAC,CAAC;MAAEC;IAAK,CAAC,KAAK;MACvC,MAAMC,QAAQ,GAAGzB,aAAa,CAACwB,IAAI,CAAC;MAEpC,OAAOF,GAAG,CAACI,KAAK,CAACC,IAAI,CAAEX,IAAI,IAAK;QAC9B,MAAMY,QAAQ,GAAG5B,aAAa,CAACgB,IAAI,CAACQ,IAAI,CAAC;QACzC,OAAOI,QAAQ,KAAKH,QAAQ;MAC9B,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ;EAEA,IAAII,aAAaA,CAAA,EAAY;IAC3B,IAAI,IAAI,CAAChB,KAAK,CAACiB,MAAM,KAAKtC,MAAM,CAACuC,EAAE,EAAE;MACnC,OAAO,IAAI,CAACjB,OAAO,CAACkB,UAAU,KAAKzC,cAAc,CAAC0C,QAAQ;IAC5D;IAEA,OAAO,IAAI,CAACZ,IAAI,CAACa,MAAM,GAAG,CAAC;EAC7B;EAEAC,SAASA,CAACC,OAA4B,EAAE;IACtC,MAAM;MAAEC;IAAO,CAAC,GAAG,IAAI,CAACC,aAAa,CAACF,OAAO,CAAC;IAC9C,OAAOC,MAAM,IAAID,OAAO,EAAEG,MAAM,CAACF,MAAM;EACzC;;EAEA;AACF;AACA;AACA;AACA;EACEG,YAAYA,CACVJ,OAA2B,EAC3BK,OAAoB,EACD;IACnB,MAAM;MAAEhC,UAAU;MAAEiC;IAAU,CAAC,GAAG,IAAI;IACtC,MAAM;MAAEC;IAAM,CAAC,GAAGP,OAAO;IACzB,MAAM;MAAEQ,OAAO;MAAEC;IAAO,CAAC,GAAGJ,OAAO;IAEnC,IAAI;MAAEK,SAAS;MAAEC;IAAU,CAAC,GAAGL,SAAS;IAExC,MAAM3B,UAAU,GAAGN,UAAU,CAAC+B,YAAY,CAACI,OAAO,EAAEC,MAAM,EAAEF,KAAK,CAAC;IAClE,MAAMK,cAAc,GAAGjC,UAAU,CAACQ,MAAM,CACtC,CAAC;MAAE0B;IAAgB,CAAC,KAAKA,eAC3B,CAAC;;IAED;IACA,IAAID,cAAc,CAACd,MAAM,KAAK,CAAC,EAAE;MAC/B,MAAM;QAAErB;MAAM,CAAC,GAAGmC,cAAc,CAAC,CAAC,CAAC;MACnC,MAAM;QAAEE,QAAQ;QAAEC;MAAM,CAAC,GAAGtC,KAAK;;MAEjC;MACA,MAAMuC,aAAa,GAAGJ,cAAc,CAAC,CAAC,CAAC,KAAKjC,UAAU,CAAC,CAAC,CAAC;;MAEzD;MACA,MAAMsC,aAAa,GAAGH,QAAQ,EAAEI,MAAM,IAAIH,KAAK;;MAE/C;MACA,IAAIE,aAAa,EAAE;QACjB,MAAME,IAAI,GAAGH,aAAa,GAAG,GAAG,GAAG,GAAG;QAEtCC,aAAa,CAACG,OAAO,GACnBH,aAAa,KAAKF,KAAK,GACnB,gBAAgBI,IAAI,EAAE,GACtB,2BAA2BA,IAAI,EAAE;QAEvC,IAAIH,aAAa,EAAE;UACjBC,aAAa,CAACD,aAAa,GAAGA,aAAa;;UAE3C;UACA,MAAMK,UAAU,GACd,IAAI,CAAChD,UAAU,CAACiD,MAAM,CAACC,EAAE,CAAC,CAAC,CAAC,EAAEC,OAAO,CAACC,QAAQ,KAAK,KAAK;UAE1D,IAAIf,SAAS,EAAE;YACbO,aAAa,CAACS,IAAI,GAAGL,UAAU,GAC3B,GAAGX,SAAS,GAAGjD,YAAY,EAAE,GAC7BiD,SAAS;UACf;UAEAA,SAAS,GAAGA,SAAS,IAAIO,aAAa,CAACS,IAAI;QAC7C;MACF;MAEAf,SAAS,GAAG,CAACK,aAAa;IAC5B,CAAC,MAAM,IAAIJ,cAAc,CAACd,MAAM,GAAG,CAAC,EAAE;MACpC;MACA;MACA,KAAK,MAAM;QAAErB;MAAM,CAAC,IAAImC,cAAc,EAAE;QACtC,IAAInC,KAAK,CAACqC,QAAQ,EAAEI,MAAM,EAAE;UAC1BzC,KAAK,CAACqC,QAAQ,CAACI,MAAM,CAACE,OAAO,GAAG,2BAA2B;QAC7D;QACA,IAAI3C,KAAK,CAACsC,KAAK,EAAE;UACftC,KAAK,CAACsC,KAAK,CAACK,OAAO,GAAG,gBAAgB;QACxC;MACF;IACF;IAEA,OAAO;MACL,GAAGd,SAAS;MACZqB,QAAQ,EAAE,IAAI,CAACC,WAAW,CAAC5B,OAAO,EAAEK,OAAO,CAAC;MAC5CA,OAAO;MACPM,SAAS;MACThC,UAAU;MACV8B,MAAM;MACNlC,kBAAkB,EAAE,IAAI,CAACsD,uBAAuB,CAAC7B,OAAO,CAAC8B,MAAM;IACjE,CAAC;EACH;EAEAC,eAAeA,CACb/B,OAAyC,EACzCK,OAAoB,EACpB;IACA,MAAM;MAAE2B;IAAM,CAAC,GAAG3B,OAAO;IAEzB,MAAM4B,SAAS,GAAG,IAAI,CAACC,YAAY,CAAC,CAAC;IACrC,MAAMC,YAAY,GAAGH,KAAK,CAACT,EAAE,CAAC,CAAC,CAAC,CAAC,IAAIU,SAAS;IAE9C,OAAO,CAACD,KAAK,CAAClC,MAAM,GAChBmC,SAAS,CAAC;IAAA,EACVE,YAAY,EAAC;EACnB;;EAEA;AACF;AACA;EACEC,WAAWA,CAAC/B,OAAoB,EAAE;IAChC,MAAM;MAAE5B,KAAK;MAAEQ,IAAI;MAAEG;IAAK,CAAC,GAAG,IAAI;IAClC,MAAM;MAAEiD;IAAgB,CAAC,GAAGhC,OAAO;IAEnC,MAAMiC,WAAW,GAAG,IAAI,CAACC,cAAc,CAAC,CAAC;IACzC,MAAMC,UAAU,GAAG,IAAI,CAACC,aAAa,CAAC,CAAC;;IAEvC;IACA,IAAIC,WAAW,GAAGtD,IAAI,KAAKkD,WAAW,GAAGE,UAAU,GAAGG,SAAS;IAE/D,IAAIlE,KAAK,CAACiB,MAAM,KAAKtC,MAAM,CAACuC,EAAE,EAAE;MAC9B,IAAI,IAAI,CAACjB,OAAO,CAACkB,UAAU,KAAKzC,cAAc,CAAC0C,QAAQ,EAAE;QACvD,MAAM;UAAEP;QAAM,CAAC,GAAG,IAAI,CAACb,KAAK;QAC5B,MAAMmE,SAAS,GAAGtD,KAAK,CAACuD,OAAO,CAAC,IAAI,CAAC;;QAErC;QACA;QACA,MAAMC,QAAQ,GAAGxD,KAAK,CAACyD,KAAK,CAACH,SAAS,GAAG,CAAC,CAAC,CAACI,IAAI,CAAEpE,IAAI,IAAK;UACzD,MAAM;YAAEqE;UAAU,CAAC,GAAGrE,IAAI;UAE1B,IAAIqE,SAAS,EAAE;YACb,MAAMC,eAAe,GAAGD,SAAS,CAACE,EAAE,CAACd,eAAe,CAAC;YAErD,IAAI,CAACa,eAAe,EAAE;cACpB,OAAO,KAAK;YACd;UACF;UAEA,OAAO,IAAI;QACb,CAAC,CAAC;QAEF,OAAOJ,QAAQ,EAAE1D,IAAI,IAAIsD,WAAW;MACtC,CAAC,MAAM;QACL,OAAOA,WAAW;MACpB;IACF;IAEA,MAAMU,QAAQ,GAAGnE,IAAI,CAAC+D,IAAI,CAAEK,IAAI,IAAK;MACnC,MAAM;QAAEJ;MAAU,CAAC,GAAGI,IAAI;MAE1B,IAAIJ,SAAS,EAAE;QACb,OAAOxE,KAAK,CAAC6E,UAAU,CAACL,SAAS,CAAC,EAAEE,EAAE,CAACd,eAAe,CAAC,IAAI,KAAK;MAClE;MAEAK,WAAW,GAAGW,IAAI,CAACjE,IAAI;MACvB,OAAO,KAAK;IACd,CAAC,CAAC;IAEF,OAAOgE,QAAQ,EAAEhE,IAAI,IAAIsD,WAAW;EACtC;;EAEA;AACF;AACA;EACEa,oBAAoBA,CAClBvD,OAAuC,EACvCwD,KAA0B,EACb;IACb,MAAM;MAAEnF;IAAW,CAAC,GAAG,IAAI;;IAE3B;IACA,MAAM8B,MAAM,GAAG,IAAI,CAACD,aAAa,CAACF,OAAO,CAAC;;IAE1C;IACA,MAAMQ,OAAO,GAAGnC,UAAU,CAACkF,oBAAoB,CAACC,KAAK,CAAC;IAEtD,OAAO;MACL,GAAGrD,MAAM;MACT,GAAGK;IACL,CAAC;EACH;;EAEA;AACF;AACA;EACEN,aAAaA,CAACF,OAA4B,EAAqB;IAC7D,MAAM;MAAEQ;IAAQ,CAAC,GAAGR,OAAO,IAAI,CAAC,CAAC;IAEjC,MAAMyD,MAAM,GAAGvF,YAAY,CAACwF,QAAQ,CAAClD,OAAO,EAAE;MAC5CmD,UAAU,EAAE,KAAK;MACjBC,YAAY,EAAE;IAChB,CAAC,CAAC;IAEF,OAAOH,MAAM,CAACI,KAAK;EACrB;EAEAC,qBAAqBA,CACnB9D,OAA2B,EAC3BwD,KAA0B,EAC1BhD,OAAoB,EACT;IACX,OAAO,IAAI,CAACnC,UAAU,CAACyF,qBAAqB,CAACtD,OAAO,CAAC;EACvD;EAEA7C,SAASA,CAACoG,OAA+B,EAAE;IACzC,OAAOpG,SAAS,CAACoG,OAAO,CAAC;EAC3B;EAEA,MAAMC,QAAQA,CAAChE,OAAyC,EAAE;IACxD,MAAM;MAAEO;IAAM,CAAC,GAAGP,OAAO;;IAEzB;IACA,IAAI,OAAO,IAAIO,KAAK,EAAE;MACpB,OAAO,CAAC,CAAC;IACX;IAEA,MAAM0D,YAAY,GAAGvG,eAAe,CAACsC,OAAO,CAAC8B,MAAM,CAAC;IAEpD,OAAOmC,YAAY,CAACD,QAAQ,CAAChE,OAAO,CAAC;EACvC;EAEA,MAAMkE,QAAQA,CACZlE,OAAyC,EACzCwD,KAA0B,EAC1B;IACA,MAAM;MAAEjD;IAAM,CAAC,GAAGP,OAAO;;IAEzB;IACA,IAAI,OAAO,IAAIO,KAAK,EAAE;MACpB,OAAOiD,KAAK;IACd;IAEA,MAAMS,YAAY,GAAGvG,eAAe,CAACsC,OAAO,CAAC8B,MAAM,CAAC;IAEpD,OAAOmC,YAAY,CAACC,QAAQ,CAAClE,OAAO,EAAEwD,KAAK,CAAC;EAC9C;EAEA,MAAMW,UAAUA,CACdnE,OAAyC,EACzCwD,KAA0B,EAC1BY,MAAc,EACd;IACA,MAAM;MAAE7D;IAAM,CAAC,GAAGP,OAAO;;IAEzB;IACA,MAAMqE,OAAO,GAAGlG,KAAK,CAACqF,KAAK,EAAEY,MAAM,CAAC;;IAEpC;IACA,IAAI,OAAO,IAAI7D,KAAK,EAAE;MACpB,OAAO8D,OAAO;IAChB;IAEA,MAAMJ,YAAY,GAAGvG,eAAe,CAACsC,OAAO,CAAC8B,MAAM,CAAC;IAEpD,OAAOmC,YAAY,CAACC,QAAQ,CAAClE,OAAO,EAAEqE,OAAO,CAAC;EAChD;EAEAC,2BAA2BA,CACzBhE,SAA4B,EAC5B7B,KAAgB,EAChB4D,eAAwD,EACxD;IACA;IACA,IAAIkC,QAAQ,GAAGjE,SAAS,CAAC3B,UAAU,CAACQ,MAAM,CAAEqF,SAAS,IAAK;MACxD,IACE,CAAC,CAAC,CAACA,SAAS,CAAC/F,KAAK,CAACgG,OAAO,IACxBD,SAAS,CAACE,IAAI,KAAKxH,aAAa,CAACyH,OAAO,KAC1CH,SAAS,CAAC/F,KAAK,CAACwE,SAAS,EACzB;QACA,MAAMA,SAAS,GAAGxE,KAAK,CAAC6E,UAAU,CAACkB,SAAS,CAAC/F,KAAK,CAACwE,SAAS,CAAC;QAC7D,OAAOA,SAAS,EAAEE,EAAE,CAACd,eAAe,CAAC;MACvC;MACA,OAAO,IAAI;IACb,CAAC,CAAC;;IAEF;AACJ;AACA;IACIkC,QAAQ,GAAGA,QAAQ,CAACK,GAAG,CAAEJ,SAAS,IAAK;MACrC,MAAMK,kBAAkB,GAAGL,SAAS;MACpC,MAAMC,OAAO,GAAGI,kBAAkB,CAACpG,KAAK,CAACgG,OAAO;MAChD,IAAIK,KAAK,CAACC,OAAO,CAACN,OAAO,CAAC,EAAE;QAC1BI,kBAAkB,CAACpG,KAAK,CAACgG,OAAO,GAAGA,OAAO,CAACtF,MAAM,CAAE6F,IAAI,IACrDA,IAAI,CAAC/B,SAAS,GACVxE,KAAK,CAAC6E,UAAU,CAAC0B,IAAI,CAAC/B,SAAS,CAAC,EAAEE,EAAE,CAACd,eAAe,CAAC,GACrD,IACN,CAAC;MACH;MACA;MACA,MAAM4C,KAAK,GAAGJ,kBAAkB,CAACpG,KAAK,CAACwG,KAAK;MAE5C,IAAIH,KAAK,CAACC,OAAO,CAACE,KAAK,CAAC,EAAE;QACxBJ,kBAAkB,CAACpG,KAAK,CAACwG,KAAK,GAAGA,KAAK,CAAC9F,MAAM,CAAE6F,IAAI,IACjDA,IAAI,CAAC/B,SAAS,GACVxE,KAAK,CAAC6E,UAAU,CAAC0B,IAAI,CAAC/B,SAAS,CAAC,EAAEE,EAAE,CAACd,eAAe,CAAC,GACrD,IACN,CAAC;MACH;MAEA,OAAOwC,kBAAkB;IAC3B,CAAC,CAAC;IAEF,OAAON,QAAQ;EACjB;EAEAW,mBAAmBA,CAAA,EAAG;IACpB,OAAO,OACLlF,OAAoB,EACpBK,OAAoB,EACpB8E,CAA6C,KAC1C;MACH,MAAM;QAAE9G,UAAU;QAAEI,KAAK;QAAE2G;MAAS,CAAC,GAAG,IAAI;MAC5C,MAAM;QAAE/C;MAAgB,CAAC,GAAGhC,OAAO;MAEnC,MAAMC,SAAS,GAAG,IAAI,CAACF,YAAY,CAACJ,OAAO,EAAEK,OAAO,CAAC;MACrDC,SAAS,CAACG,MAAM,GAAGpC,UAAU,CAACgH,aAAa,CAAC/E,SAAS,CAACG,MAAM,CAAC;;MAE7D;AACN;AACA;;MAEM;MACAH,SAAS,CAAC3B,UAAU,GAAG,IAAI,CAAC2F,2BAA2B,CACrDhE,SAAS,EACT7B,KAAK,EACL4D,eACF,CAAC;MAED/B,SAAS,CAACgF,2BAA2B,GACnC,MAAM,IAAI,CAACA,2BAA2B,CAACtF,OAAO,EAAEK,OAAO,CAAC;MAE1D,OAAO8E,CAAC,CAACI,IAAI,CAACH,QAAQ,EAAE9E,SAAS,CAAC;IACpC,CAAC;EACH;EAEA,MAAMgF,2BAA2BA,CAC/BtF,OAAoB,EACpBK,OAAoB,EACpB;IACA,MAAM;MAAEjB;IAAK,CAAC,GAAG,IAAI;IACrB,MAAM;MAAEe;IAAO,CAAC,GAAGH,OAAO;IAC1B,MAAM;MAAEwF;IAAc,CAAC,GAAGnF,OAAO;IAEjC,MAAM4B,SAAS,GAAG,IAAI,CAACC,YAAY,CAAC,CAAC;IACrC,MAAMI,WAAW,GAAG,IAAI,CAACC,cAAc,CAAC,CAAC;IACzC,MAAM;MAAEkD;IAAa,CAAC,GAAG,IAAI,CAAChH,KAAK,CAACiH,QAAQ;IAC5C,MAAM;MAAEC;IAAgB,CAAC,GAAGF,YAAY;;IAExC;IACA,IAAI,CAACxD,SAAS,EAAEK,WAAW,CAAC,CAACsD,QAAQ,CAACxG,IAAI,CAAC,IAAI,CAACoG,aAAa,EAAE;MAC7D,MAAM;QAAEK;MAAkB,CAAC,GAAG,MAAMF,eAAe,CAACxF,MAAM,CAAC2F,IAAI,CAAC;MAChE,OAAO,CAACD,iBAAiB;IAC3B;IAEA,OAAO,KAAK;EACd;;EAEA;AACF;AACA;EACYjE,WAAWA,CACnB5B,OAA2B,EAC3BK,OAAoB,EACE;IACtB,MAAM;MAAE3B;IAAQ,CAAC,GAAG,IAAI;IACxB,MAAM;MAAEU,IAAI;MAAEmB;IAAM,CAAC,GAAGP,OAAO;IAC/B,MAAM;MAAE+F;IAAU,CAAC,GAAGxF,KAAK;IAC3B,MAAM;MAAEyB;IAAM,CAAC,GAAG3B,OAAO;IAEzB,MAAMJ,MAAM,GAAG,IAAI,CAACF,SAAS,CAACC,OAAO,CAAC;;IAEtC;IACA,IAAI+F,SAAS,EAAE;MACb,OAAO;QACLrE,IAAI,EACFnE,WAAW,CAACmB,OAAO,CAAC,IAAIuB,MAAM,GAC1B,wBAAwB,GACxB,0BAA0B;QAChC+F,IAAI,EAAED;MACR,CAAC;IACH;;IAEA;IACA,MAAME,QAAQ,GACZhG,MAAM,IAAI,CAACb,IAAI,CAAC8G,QAAQ,CAACjG,MAAM,CAAC,GAC5B+B,KAAK,CAACT,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAAA,EACbS,KAAK,CAACT,EAAE,CAAC,CAAC,CAAC,CAAC,EAAC;;IAEnB;IACA,IAAI,CAAC0E,QAAQ,EAAE;MACb;IACF;;IAEA;IACA,OAAO;MACLvE,IAAI,EAAE,MAAM;MACZsE,IAAI,EAAE,IAAI,CAACG,OAAO,CAACF,QAAQ;IAC7B,CAAC;EACH;EAEAG,oBAAoBA,CAAA,EAAG;IACrB,OAAO,OACLpG,OAA2B,EAC3BK,OAAoB,EACpB8E,CAA6C,KAC1C;MACH,MAAM;QAAE9G,UAAU;QAAE+G,QAAQ;QAAE3G;MAAM,CAAC,GAAG,IAAI;MAC5C,MAAM;QAAE+G,aAAa;QAAEhC,KAAK;QAAEnB;MAAgB,CAAC,GAAGhC,OAAO;;MAEzD;AACN;AACA;AACA;MACM,IAAIA,OAAO,CAACI,MAAM,IAAI+E,aAAa,EAAE;QACnC,MAAMlF,SAAS,GAAG,IAAI,CAACF,YAAY,CAACJ,OAAO,EAAEK,OAAO,CAAC;QACrDC,SAAS,CAACG,MAAM,GAAGpC,UAAU,CAACgH,aAAa,CAAC/E,SAAS,CAACG,MAAM,CAAC;;QAE7D;QACAH,SAAS,CAAC3B,UAAU,GAAG,IAAI,CAAC2F,2BAA2B,CACrDhE,SAAS,EACT7B,KAAK,EACL4D,eACF,CAAC;QAED,OAAO8C,CAAC,CAACI,IAAI,CAACH,QAAQ,EAAE9E,SAAS,CAAC;MACpC;;MAEA;MACA,MAAM;QAAEtB;MAAO,CAAC,GAAGgB,OAAO,CAACQ,OAAO;MAClC,IAAIxB,MAAM,KAAKjB,UAAU,CAACsI,aAAa,EAAE;QACvC,OAAO,IAAI,CAACC,mBAAmB,CAACtG,OAAO,EAAEK,OAAO,EAAE8E,CAAC,CAAC;MACtD;;MAEA;MACA,MAAM,IAAI,CAACjB,QAAQ,CAAClE,OAAO,EAAEwD,KAAK,CAAC;MACnC,OAAO,IAAI,CAAC3F,OAAO,CAACmC,OAAO,EAAEmF,CAAC,EAAE,IAAI,CAAC/C,WAAW,CAAC/B,OAAO,CAAC,CAAC;IAC5D,CAAC;EACH;EAEAxC,OAAOA,CACLmC,OAA2B,EAC3BmF,CAA6C,EAC7CoB,QAAiB,EACjB;IACA,MAAMC,OAAO,GAAGD,QAAQ,GACpB,IAAI,CAACJ,OAAO,CAACI,QAAQ,CAAC,CAAC;IAAA,EACvB,IAAI,CAACP,IAAI,EAAC;;IAEd,OAAOnI,OAAO,CAACmC,OAAO,EAAEmF,CAAC,EAAEqB,OAAO,CAAC;EACrC;;EAEA;AACF;AACA;EACE,MAAMF,mBAAmBA,CACvBtG,OAA2B,EAC3BK,OAAoB,EACpB8E,CAA6C,EAC7C;IACA,MAAM;MAAE3B;IAAM,CAAC,GAAGnD,OAAO;;IAEzB;IACA,MAAM,IAAI,CAAC6D,QAAQ,CAAClE,OAAO,EAAEwD,KAAK,CAAC;IACnC,OAAO2B,CAAC,CAACsB,QAAQ,CAAC,IAAI,CAACN,OAAO,CAAC,OAAO,CAAC,CAAC;EAC1C;;EAEA;AACF;AACA;EACE,IAAIO,eAAeA,CAAA,EAAkC;IACnD,OAAO;MACLC,GAAG,EAAE;QACHC,aAAa,EAAE;UACbC,MAAMA,CAACC,QAAQ,EAAE3B,CAAC,EAAE;YAClB,OAAOA,CAAC,CAAC4B,QAAQ;UACnB;QACF;MACF;IACF,CAAC;EACH;;EAEA;AACF;AACA;EACE,IAAIC,gBAAgBA,CAAA,EAAyC;IAC3D,OAAO;MACLxG,OAAO,EAAE;QACPyG,KAAK,EAAE,IAAI;QACXC,QAAQ,EAAEC,MAAM,CAACC,gBAAgB;QACjCC,UAAU,EAAE;MACd,CAAC;MACDV,GAAG,EAAE;QACHC,aAAa,EAAE;UACbC,MAAMA,CAACC,QAAQ,EAAE3B,CAAC,EAAE;YAClB,OAAOA,CAAC,CAAC4B,QAAQ;UACnB;QACF;MACF;IACF,CAAC;EACH;AACF","ignoreList":[]}
|
|
@@ -7,13 +7,14 @@ export declare class StartPageController extends QuestionPageController {
|
|
|
7
7
|
* This page should not be used in production. This page is helpful for prototyping start pages within the app,
|
|
8
8
|
* but start pages should really live on gov.uk (whitehall publisher) so a user can be properly signposted.
|
|
9
9
|
*/
|
|
10
|
+
allowSaveAndReturn: boolean;
|
|
10
11
|
getViewModel(request: FormRequest, context: FormContext): {
|
|
11
12
|
isStartPage: boolean;
|
|
12
13
|
components: import("../components/types.js").ComponentViewModel[];
|
|
13
14
|
context: FormContext;
|
|
14
15
|
errors?: import("~/src/server/plugins/engine/types.js").FormSubmissionError[];
|
|
15
16
|
hasMissingNotificationEmail?: boolean;
|
|
16
|
-
allowSaveAndReturn
|
|
17
|
+
allowSaveAndReturn: boolean;
|
|
17
18
|
page: import("./PageController.js").PageController;
|
|
18
19
|
name?: string;
|
|
19
20
|
pageTitle: string;
|
|
@@ -48,5 +49,4 @@ export declare class StartPageController extends QuestionPageController {
|
|
|
48
49
|
*/
|
|
49
50
|
slug?: string | undefined;
|
|
50
51
|
};
|
|
51
|
-
shouldShowSaveAndReturn(): boolean;
|
|
52
52
|
}
|
|
@@ -6,14 +6,12 @@ export class StartPageController extends QuestionPageController {
|
|
|
6
6
|
* but start pages should really live on gov.uk (whitehall publisher) so a user can be properly signposted.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
allowSaveAndReturn = false;
|
|
9
10
|
getViewModel(request, context) {
|
|
10
11
|
return {
|
|
11
12
|
...super.getViewModel(request, context),
|
|
12
13
|
isStartPage: true
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
|
-
shouldShowSaveAndReturn() {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
16
|
}
|
|
19
17
|
//# sourceMappingURL=StartPageController.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StartPageController.js","names":["QuestionPageController","StartPageController","getViewModel","request","context","isStartPage"
|
|
1
|
+
{"version":3,"file":"StartPageController.js","names":["QuestionPageController","StartPageController","allowSaveAndReturn","getViewModel","request","context","isStartPage"],"sources":["../../../../../src/server/plugins/engine/pageControllers/StartPageController.ts"],"sourcesContent":["import { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport { type FormContext } from '~/src/server/plugins/engine/types.js'\nimport { type FormRequest } from '~/src/server/routes/types.js'\n\nexport class StartPageController extends QuestionPageController {\n /**\n * The controller which is used when Page[\"controller\"] is defined as \"./pages/start.js\"\n * This page should not be used in production. This page is helpful for prototyping start pages within the app,\n * but start pages should really live on gov.uk (whitehall publisher) so a user can be properly signposted.\n */\n\n allowSaveAndReturn = false\n\n getViewModel(request: FormRequest, context: FormContext) {\n return {\n ...super.getViewModel(request, context),\n isStartPage: true\n }\n }\n}\n"],"mappings":"AAAA,SAASA,sBAAsB;AAI/B,OAAO,MAAMC,mBAAmB,SAASD,sBAAsB,CAAC;EAC9D;AACF;AACA;AACA;AACA;;EAEEE,kBAAkB,GAAG,KAAK;EAE1BC,YAAYA,CAACC,OAAoB,EAAEC,OAAoB,EAAE;IACvD,OAAO;MACL,GAAG,KAAK,CAACF,YAAY,CAACC,OAAO,EAAEC,OAAO,CAAC;MACvCC,WAAW,EAAE;IACf,CAAC;EACH;AACF","ignoreList":[]}
|
|
@@ -6,6 +6,7 @@ import { type FormContext } from '~/src/server/plugins/engine/types.js';
|
|
|
6
6
|
import { type FormRequest } from '~/src/server/routes/types.js';
|
|
7
7
|
export declare class StatusPageController extends QuestionPageController {
|
|
8
8
|
pageDef: PageStatus;
|
|
9
|
+
allowSaveAndReturn: boolean;
|
|
9
10
|
constructor(model: FormModel, pageDef: PageStatus);
|
|
10
11
|
getRelevantPath(): string;
|
|
11
12
|
makeGetRouteHandler(): (request: FormRequest, context: FormContext, h: Pick<ResponseToolkit, "redirect" | "view">) => Promise<import("@hapi/hapi").ResponseObject>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getCacheService } from "../helpers.js";
|
|
2
2
|
import { QuestionPageController } from "./QuestionPageController.js";
|
|
3
3
|
export class StatusPageController extends QuestionPageController {
|
|
4
|
+
allowSaveAndReturn = false;
|
|
4
5
|
constructor(model, pageDef) {
|
|
5
6
|
super(model, pageDef);
|
|
6
7
|
this.viewName = 'confirmation';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusPageController.js","names":["getCacheService","QuestionPageController","StatusPageController","constructor","model","pageDef","viewName","getRelevantPath","getStatusPath","makeGetRouteHandler","request","context","h","viewModel","cacheService","server","confirmationState","getConfirmationState","confirmed","proceed","getStartPath","slug","params","formsService","services","getFormMetadata","submissionGuidance","view"],"sources":["../../../../../src/server/plugins/engine/pageControllers/StatusPageController.ts"],"sourcesContent":["import { type PageStatus } from '@defra/forms-model'\nimport { type ResponseToolkit } from '@hapi/hapi'\n\nimport { getCacheService } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport { type FormContext } from '~/src/server/plugins/engine/types.js'\nimport { type FormRequest } from '~/src/server/routes/types.js'\n\nexport class StatusPageController extends QuestionPageController {\n declare pageDef: PageStatus\n\n constructor(model: FormModel, pageDef: PageStatus) {\n super(model, pageDef)\n this.viewName = 'confirmation'\n }\n\n getRelevantPath() {\n return this.getStatusPath()\n }\n\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { viewModel, viewName } = this\n\n const cacheService = getCacheService(request.server)\n const confirmationState = await cacheService.getConfirmationState(request)\n\n // If there's no confirmation state, then\n // redirect the user back to the start of the form\n if (!confirmationState.confirmed) {\n return this.proceed(request, h, this.getStartPath())\n }\n\n const slug = request.params.slug\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n const { submissionGuidance } = await getFormMetadata(slug)\n\n return h.view(viewName, {\n ...viewModel,\n submissionGuidance\n })\n }\n }\n}\n"],"mappings":"AAGA,SAASA,eAAe;AAExB,SAASC,sBAAsB;AAI/B,OAAO,MAAMC,oBAAoB,SAASD,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"StatusPageController.js","names":["getCacheService","QuestionPageController","StatusPageController","allowSaveAndReturn","constructor","model","pageDef","viewName","getRelevantPath","getStatusPath","makeGetRouteHandler","request","context","h","viewModel","cacheService","server","confirmationState","getConfirmationState","confirmed","proceed","getStartPath","slug","params","formsService","services","getFormMetadata","submissionGuidance","view"],"sources":["../../../../../src/server/plugins/engine/pageControllers/StatusPageController.ts"],"sourcesContent":["import { type PageStatus } from '@defra/forms-model'\nimport { type ResponseToolkit } from '@hapi/hapi'\n\nimport { getCacheService } from '~/src/server/plugins/engine/helpers.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport { type FormContext } from '~/src/server/plugins/engine/types.js'\nimport { type FormRequest } from '~/src/server/routes/types.js'\n\nexport class StatusPageController extends QuestionPageController {\n declare pageDef: PageStatus\n allowSaveAndReturn = false\n\n constructor(model: FormModel, pageDef: PageStatus) {\n super(model, pageDef)\n this.viewName = 'confirmation'\n }\n\n getRelevantPath() {\n return this.getStatusPath()\n }\n\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { viewModel, viewName } = this\n\n const cacheService = getCacheService(request.server)\n const confirmationState = await cacheService.getConfirmationState(request)\n\n // If there's no confirmation state, then\n // redirect the user back to the start of the form\n if (!confirmationState.confirmed) {\n return this.proceed(request, h, this.getStartPath())\n }\n\n const slug = request.params.slug\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n const { submissionGuidance } = await getFormMetadata(slug)\n\n return h.view(viewName, {\n ...viewModel,\n submissionGuidance\n })\n }\n }\n}\n"],"mappings":"AAGA,SAASA,eAAe;AAExB,SAASC,sBAAsB;AAI/B,OAAO,MAAMC,oBAAoB,SAASD,sBAAsB,CAAC;EAE/DE,kBAAkB,GAAG,KAAK;EAE1BC,WAAWA,CAACC,KAAgB,EAAEC,OAAmB,EAAE;IACjD,KAAK,CAACD,KAAK,EAAEC,OAAO,CAAC;IACrB,IAAI,CAACC,QAAQ,GAAG,cAAc;EAChC;EAEAC,eAAeA,CAAA,EAAG;IAChB,OAAO,IAAI,CAACC,aAAa,CAAC,CAAC;EAC7B;EAEAC,mBAAmBA,CAAA,EAAG;IACpB,OAAO,OACLC,OAAoB,EACpBC,OAAoB,EACpBC,CAA6C,KAC1C;MACH,MAAM;QAAEC,SAAS;QAAEP;MAAS,CAAC,GAAG,IAAI;MAEpC,MAAMQ,YAAY,GAAGf,eAAe,CAACW,OAAO,CAACK,MAAM,CAAC;MACpD,MAAMC,iBAAiB,GAAG,MAAMF,YAAY,CAACG,oBAAoB,CAACP,OAAO,CAAC;;MAE1E;MACA;MACA,IAAI,CAACM,iBAAiB,CAACE,SAAS,EAAE;QAChC,OAAO,IAAI,CAACC,OAAO,CAACT,OAAO,EAAEE,CAAC,EAAE,IAAI,CAACQ,YAAY,CAAC,CAAC,CAAC;MACtD;MAEA,MAAMC,IAAI,GAAGX,OAAO,CAACY,MAAM,CAACD,IAAI;MAChC,MAAM;QAAEE;MAAa,CAAC,GAAG,IAAI,CAACnB,KAAK,CAACoB,QAAQ;MAC5C,MAAM;QAAEC;MAAgB,CAAC,GAAGF,YAAY;MAExC,MAAM;QAAEG;MAAmB,CAAC,GAAG,MAAMD,eAAe,CAACJ,IAAI,CAAC;MAE1D,OAAOT,CAAC,CAACe,IAAI,CAACrB,QAAQ,EAAE;QACtB,GAAGO,SAAS;QACZa;MACF,CAAC,CAAC;IACJ,CAAC;EACH;AACF","ignoreList":[]}
|
|
@@ -22,6 +22,5 @@ export declare class SummaryPageController extends QuestionPageController {
|
|
|
22
22
|
*/
|
|
23
23
|
makePostRouteHandler(): (request: FormRequestPayload, context: FormContext, h: Pick<ResponseToolkit, "redirect" | "view">) => Promise<import("@hapi/hapi").ResponseObject>;
|
|
24
24
|
get postRouteOptions(): RouteOptions<FormRequestPayloadRefs>;
|
|
25
|
-
shouldShowSaveAndReturn(): boolean;
|
|
26
25
|
}
|
|
27
26
|
export declare function getFormSubmissionData(context: FormContext, details: Detail[]): DetailItem[];
|
|
@@ -38,7 +38,7 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
38
38
|
viewModel.feedbackLink = this.feedbackLink;
|
|
39
39
|
viewModel.phaseTag = this.phaseTag;
|
|
40
40
|
viewModel.components = components;
|
|
41
|
-
viewModel.allowSaveAndReturn = this.shouldShowSaveAndReturn();
|
|
41
|
+
viewModel.allowSaveAndReturn = this.shouldShowSaveAndReturn(request.server);
|
|
42
42
|
return viewModel;
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -114,9 +114,6 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
114
114
|
}
|
|
115
115
|
};
|
|
116
116
|
}
|
|
117
|
-
shouldShowSaveAndReturn() {
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
117
|
}
|
|
121
118
|
async function submitForm(request, summaryViewModel, model, state, emailAddress) {
|
|
122
119
|
await extendFileRetention(model, state, emailAddress);
|
|
@@ -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","makeGetRouteHandler","h","hasMissingNotificationEmail","view","makePostRouteHandler","params","state","cacheService","server","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()\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 shouldShowSaveAndReturn(): boolean {\n return true\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":"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","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","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":"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","ignoreList":[]}
|
|
@@ -5,5 +5,6 @@ import { type FormContext } from '~/src/server/plugins/engine/types.js';
|
|
|
5
5
|
import { type FormRequestPayload } from '~/src/server/routes/types.js';
|
|
6
6
|
export declare class TerminalPageController extends QuestionPageController {
|
|
7
7
|
pageDef: PageTerminal;
|
|
8
|
+
allowSaveAndReturn: boolean;
|
|
8
9
|
makePostRouteHandler(): (request: FormRequestPayload, context: FormContext, h: Pick<ResponseToolkit, 'redirect' | 'view'>) => Promise<ResponseObject>;
|
|
9
10
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Boom from '@hapi/boom';
|
|
2
2
|
import { QuestionPageController } from "./QuestionPageController.js";
|
|
3
3
|
export class TerminalPageController extends QuestionPageController {
|
|
4
|
+
allowSaveAndReturn = false;
|
|
4
5
|
makePostRouteHandler() {
|
|
5
6
|
throw Boom.methodNotAllowed('POST method not allowed for terminal pages');
|
|
6
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalPageController.js","names":["Boom","QuestionPageController","TerminalPageController","makePostRouteHandler","methodNotAllowed"],"sources":["../../../../../src/server/plugins/engine/pageControllers/TerminalPageController.ts"],"sourcesContent":["import { type PageTerminal } from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type ResponseObject, type ResponseToolkit } from '@hapi/hapi'\n\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport { type FormContext } from '~/src/server/plugins/engine/types.js'\nimport { type FormRequestPayload } from '~/src/server/routes/types.js'\n\nexport class TerminalPageController extends QuestionPageController {\n declare pageDef: PageTerminal\n\n makePostRouteHandler(): (\n request: FormRequestPayload,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => Promise<ResponseObject> {\n throw Boom.methodNotAllowed('POST method not allowed for terminal pages')\n }\n}\n"],"mappings":"AACA,OAAOA,IAAI,MAAM,YAAY;AAG7B,SAASC,sBAAsB;AAI/B,OAAO,MAAMC,sBAAsB,SAASD,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"TerminalPageController.js","names":["Boom","QuestionPageController","TerminalPageController","allowSaveAndReturn","makePostRouteHandler","methodNotAllowed"],"sources":["../../../../../src/server/plugins/engine/pageControllers/TerminalPageController.ts"],"sourcesContent":["import { type PageTerminal } from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type ResponseObject, type ResponseToolkit } from '@hapi/hapi'\n\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport { type FormContext } from '~/src/server/plugins/engine/types.js'\nimport { type FormRequestPayload } from '~/src/server/routes/types.js'\n\nexport class TerminalPageController extends QuestionPageController {\n declare pageDef: PageTerminal\n allowSaveAndReturn = false\n\n makePostRouteHandler(): (\n request: FormRequestPayload,\n context: FormContext,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => Promise<ResponseObject> {\n throw Boom.methodNotAllowed('POST method not allowed for terminal pages')\n }\n}\n"],"mappings":"AACA,OAAOA,IAAI,MAAM,YAAY;AAG7B,SAASC,sBAAsB;AAI/B,OAAO,MAAMC,sBAAsB,SAASD,sBAAsB,CAAC;EAEjEE,kBAAkB,GAAG,KAAK;EAE1BC,oBAAoBA,CAAA,EAIS;IAC3B,MAAMJ,IAAI,CAACK,gBAAgB,CAAC,4CAA4C,CAAC;EAC3E;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type FormContextRequest } from '~/src/server/plugins/engine/types.js';
|
|
2
|
+
import { type FormRequest } from '~/src/server/routes/types.js';
|
|
3
|
+
export declare function buildFormRequest(request: Omit<FormRequest, 'server'>): FormRequest;
|
|
4
|
+
export declare function buildFormContextRequest(request: Omit<FormContextRequest, 'server'>): FormContextRequest;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { server } from "./server.js";
|
|
2
|
+
export function buildFormRequest(request) {
|
|
3
|
+
return {
|
|
4
|
+
...request,
|
|
5
|
+
server
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export function buildFormContextRequest(request) {
|
|
9
|
+
return {
|
|
10
|
+
...request,
|
|
11
|
+
server
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","names":["server","buildFormRequest","request","buildFormContextRequest"],"sources":["../../../../../../src/server/plugins/engine/pageControllers/__stubs__/request.ts"],"sourcesContent":["import { server } from '~/src/server/plugins/engine/pageControllers/__stubs__/server.js'\nimport { type FormContextRequest } from '~/src/server/plugins/engine/types.js'\nimport { type FormRequest } from '~/src/server/routes/types.js'\n\nexport function buildFormRequest(\n request: Omit<FormRequest, 'server'>\n): FormRequest {\n return {\n ...request,\n server\n } as FormRequest\n}\n\nexport function buildFormContextRequest(\n request: Omit<FormContextRequest, 'server'>\n): FormContextRequest {\n return {\n ...request,\n server\n } as FormContextRequest\n}\n"],"mappings":"AAAA,SAASA,MAAM;AAIf,OAAO,SAASC,gBAAgBA,CAC9BC,OAAoC,EACvB;EACb,OAAO;IACL,GAAGA,OAAO;IACVF;EACF,CAAC;AACH;AAEA,OAAO,SAASG,uBAAuBA,CACrCD,OAA2C,EACvB;EACpB,OAAO;IACL,GAAGA,OAAO;IACVF;EACF,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const server = {
|
|
2
|
+
plugins: {
|
|
3
|
+
'forms-engine-plugin': {
|
|
4
|
+
baseLayoutPath: '',
|
|
5
|
+
cacheService: {}
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
}; // only mocking out properties we care about;
|
|
9
|
+
|
|
10
|
+
export const serverWithSaveAndReturn = {
|
|
11
|
+
plugins: {
|
|
12
|
+
...server.plugins,
|
|
13
|
+
'forms-engine-plugin': {
|
|
14
|
+
...server.plugins['forms-engine-plugin'],
|
|
15
|
+
saveAndReturn: {
|
|
16
|
+
keyGenerator: jest.fn().mockReturnValue('foobar'),
|
|
17
|
+
sessionHydrator: jest.fn().mockReturnValue({}),
|
|
18
|
+
sessionPersister: jest.fn().mockImplementation(() => Promise.resolve())
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}; // only mocking out properties we care about
|
|
23
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","names":["server","plugins","baseLayoutPath","cacheService","serverWithSaveAndReturn","saveAndReturn","keyGenerator","jest","fn","mockReturnValue","sessionHydrator","sessionPersister","mockImplementation","Promise","resolve"],"sources":["../../../../../../src/server/plugins/engine/pageControllers/__stubs__/server.ts"],"sourcesContent":["import { type Server } from '@hapi/hapi'\n\nimport { type PluginOptions } from '~/src/server/plugins/engine/types.js'\nimport { type CacheService } from '~/src/server/services/index.js'\n\nexport const server: Server = {\n plugins: {\n 'forms-engine-plugin': {\n baseLayoutPath: '',\n cacheService: {} as CacheService\n }\n }\n} as Server // only mocking out properties we care about;\n\nexport const serverWithSaveAndReturn: Server = {\n plugins: {\n ...server.plugins,\n 'forms-engine-plugin': {\n ...server.plugins['forms-engine-plugin'],\n saveAndReturn: {\n keyGenerator: jest.fn().mockReturnValue('foobar'),\n sessionHydrator: jest.fn().mockReturnValue({}),\n sessionPersister: jest.fn().mockImplementation(() => Promise.resolve())\n } as Pick<PluginOptions, 'saveAndReturn'>\n }\n }\n} as Server // only mocking out properties we care about\n"],"mappings":"AAKA,OAAO,MAAMA,MAAc,GAAG;EAC5BC,OAAO,EAAE;IACP,qBAAqB,EAAE;MACrBC,cAAc,EAAE,EAAE;MAClBC,YAAY,EAAE,CAAC;IACjB;EACF;AACF,CAAW,EAAC;;AAEZ,OAAO,MAAMC,uBAA+B,GAAG;EAC7CH,OAAO,EAAE;IACP,GAAGD,MAAM,CAACC,OAAO;IACjB,qBAAqB,EAAE;MACrB,GAAGD,MAAM,CAACC,OAAO,CAAC,qBAAqB,CAAC;MACxCI,aAAa,EAAE;QACbC,YAAY,EAAEC,IAAI,CAACC,EAAE,CAAC,CAAC,CAACC,eAAe,CAAC,QAAQ,CAAC;QACjDC,eAAe,EAAEH,IAAI,CAACC,EAAE,CAAC,CAAC,CAACC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC9CE,gBAAgB,EAAEJ,IAAI,CAACC,EAAE,CAAC,CAAC,CAACI,kBAAkB,CAAC,MAAMC,OAAO,CAACC,OAAO,CAAC,CAAC;MACxE;IACF;EACF;AACF,CAAW,EAAC","ignoreList":[]}
|
|
@@ -16,9 +16,7 @@ export const plugin = {
|
|
|
16
16
|
const {
|
|
17
17
|
model,
|
|
18
18
|
cacheName,
|
|
19
|
-
|
|
20
|
-
sessionHydrator,
|
|
21
|
-
sessionPersister,
|
|
19
|
+
saveAndReturn,
|
|
22
20
|
nunjucks: nunjucksOptions,
|
|
23
21
|
viewContext,
|
|
24
22
|
preparePageEventRequestOptions
|
|
@@ -27,15 +25,16 @@ export const plugin = {
|
|
|
27
25
|
server,
|
|
28
26
|
cacheName,
|
|
29
27
|
options: {
|
|
30
|
-
keyGenerator,
|
|
31
|
-
sessionHydrator,
|
|
32
|
-
sessionPersister
|
|
28
|
+
keyGenerator: saveAndReturn?.keyGenerator,
|
|
29
|
+
sessionHydrator: saveAndReturn?.sessionHydrator,
|
|
30
|
+
sessionPersister: saveAndReturn?.sessionPersister
|
|
33
31
|
}
|
|
34
32
|
});
|
|
35
33
|
await registerVision(server, options);
|
|
36
34
|
server.expose('baseLayoutPath', nunjucksOptions.baseLayoutPath);
|
|
37
35
|
server.expose('viewContext', viewContext);
|
|
38
36
|
server.expose('cacheService', cacheService);
|
|
37
|
+
server.expose('saveAndReturn', saveAndReturn);
|
|
39
38
|
server.app.model = model;
|
|
40
39
|
|
|
41
40
|
// In-memory cache of FormModel items, exposed
|
|
@@ -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","
|
|
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","sessionPersister","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 sessionPersister: saveAndReturn?.sessionPersister\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,eAAe;QAC/CC,gBAAgB,EAAER,aAAa,EAAEQ;MACnC;IACF,CAAC,CAAC;IAEF,MAAMnB,cAAc,CAACO,MAAM,EAAEC,OAAO,CAAC;IAErCD,MAAM,CAACa,MAAM,CAAC,gBAAgB,EAAEP,eAAe,CAACQ,cAAc,CAAC;IAC/Dd,MAAM,CAACa,MAAM,CAAC,aAAa,EAAEN,WAAW,CAAC;IACzCP,MAAM,CAACa,MAAM,CAAC,cAAc,EAAEJ,YAAY,CAAC;IAC3CT,MAAM,CAACa,MAAM,CAAC,eAAe,EAAET,aAAa,CAAC;IAE7CJ,MAAM,CAACe,GAAG,CAACb,KAAK,GAAGA,KAAK;;IAExB;IACA;IACA,MAAMc,SAAS,GAAG,IAAIC,GAAG,CAAgD,CAAC;IAC1EjB,MAAM,CAACe,GAAG,CAACG,MAAM,GAAGF,SAAS;IAE7B,MAAMG,kBAAkB,GAAG9B,sBAAsB,CAACW,MAAM,EAAEC,OAAO,CAAC;IAElE,MAAMmB,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,GAAGpC,iBAAiB,CAClB8B,eAAe,EACfG,gBAAgB,EAChBf,8BACF,CAAC,EACD,GAAGhB,wBAAwB,CAAC4B,eAAe,EAAEG,gBAAgB,CAAC,EAC9D,GAAGhC,2BAA2B,CAAC6B,eAAe,EAAEG,gBAAgB,CAAC,EACjE,GAAGpC,0BAA0B,CAACiC,eAAe,CAAC,EAC9C,GAAGhC,yBAAyB,CAAC,CAAC,CAC/B;IAEDY,MAAM,CAAC2B,KAAK,CAACD,MAAkC,CAAC,EAAC;EACnD;AACF,CAAiC","ignoreList":[]}
|
|
@@ -125,7 +125,7 @@ export type FormContextRequest = ({
|
|
|
125
125
|
} | {
|
|
126
126
|
method: FormRequest['method'];
|
|
127
127
|
payload?: object | undefined;
|
|
128
|
-
}) & Pick<FormRequest, 'app' | 'method' | 'params' | 'path' | 'query' | 'url'>;
|
|
128
|
+
}) & Pick<FormRequest, 'app' | 'method' | 'params' | 'path' | 'query' | 'url' | 'server'>;
|
|
129
129
|
export interface UploadInitiateResponse {
|
|
130
130
|
uploadId: string;
|
|
131
131
|
uploadUrl: string;
|
|
@@ -235,7 +235,7 @@ export interface FormPageViewModel extends PageViewModelBase {
|
|
|
235
235
|
context: FormContext;
|
|
236
236
|
errors?: FormSubmissionError[];
|
|
237
237
|
hasMissingNotificationEmail?: boolean;
|
|
238
|
-
allowSaveAndReturn
|
|
238
|
+
allowSaveAndReturn: boolean;
|
|
239
239
|
}
|
|
240
240
|
export interface RepeaterSummaryPageViewModel extends PageViewModelBase {
|
|
241
241
|
context: FormContext;
|
|
@@ -270,9 +270,11 @@ export interface PluginOptions {
|
|
|
270
270
|
cacheName?: string;
|
|
271
271
|
globals?: Record<string, GlobalFunction>;
|
|
272
272
|
filters?: Record<string, FilterFunction>;
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
273
|
+
saveAndReturn?: {
|
|
274
|
+
keyGenerator: (request: RequestType) => string;
|
|
275
|
+
sessionHydrator: (request: RequestType) => Promise<FormSubmissionState>;
|
|
276
|
+
sessionPersister: (key: string, state: FormSubmissionState, request: RequestType) => Promise<void>;
|
|
277
|
+
};
|
|
276
278
|
pluginPath?: string;
|
|
277
279
|
nunjucks: {
|
|
278
280
|
baseLayoutPath: string;
|