@defra/forms-engine-plugin 4.11.3 → 4.13.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.
Files changed (38) hide show
  1. package/.server/server/plugins/engine/beta/form-context.js +5 -4
  2. package/.server/server/plugins/engine/beta/form-context.js.map +1 -1
  3. package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -1
  4. package/.server/server/plugins/engine/form-availability.d.ts +16 -0
  5. package/.server/server/plugins/engine/form-availability.js +26 -0
  6. package/.server/server/plugins/engine/form-availability.js.map +1 -0
  7. package/.server/server/plugins/engine/models/FormModel.d.ts +4 -0
  8. package/.server/server/plugins/engine/models/FormModel.js +14 -1
  9. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  10. package/.server/server/plugins/engine/models/unavailable-view-model.d.ts +8 -0
  11. package/.server/server/plugins/engine/models/unavailable-view-model.js +21 -0
  12. package/.server/server/plugins/engine/models/unavailable-view-model.js.map +1 -0
  13. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +1 -1
  14. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +5 -5
  15. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  16. package/.server/server/plugins/engine/plugin.js +6 -0
  17. package/.server/server/plugins/engine/plugin.js.map +1 -1
  18. package/.server/server/plugins/engine/routes/questions.js +1 -1
  19. package/.server/server/plugins/engine/routes/questions.js.map +1 -1
  20. package/.server/server/plugins/engine/unavailable-response.d.ts +9 -0
  21. package/.server/server/plugins/engine/unavailable-response.js +23 -0
  22. package/.server/server/plugins/engine/unavailable-response.js.map +1 -0
  23. package/.server/server/plugins/engine/views/file-upload.html +2 -1
  24. package/.server/server/plugins/engine/views/unavailable.html +20 -0
  25. package/.server/typings/hapi/index.d.js.map +1 -1
  26. package/package.json +4 -4
  27. package/src/server/plugins/engine/beta/form-context.ts +6 -8
  28. package/src/server/plugins/engine/components/helpers/geospatial.ts +1 -1
  29. package/src/server/plugins/engine/form-availability.ts +31 -0
  30. package/src/server/plugins/engine/models/FormModel.ts +20 -0
  31. package/src/server/plugins/engine/models/unavailable-view-model.ts +36 -0
  32. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +13 -6
  33. package/src/server/plugins/engine/plugin.ts +6 -0
  34. package/src/server/plugins/engine/routes/questions.ts +5 -1
  35. package/src/server/plugins/engine/unavailable-response.ts +29 -0
  36. package/src/server/plugins/engine/views/file-upload.html +2 -1
  37. package/src/server/plugins/engine/views/unavailable.html +20 -0
  38. package/src/typings/hapi/index.d.ts +1 -1
@@ -433,7 +433,8 @@ export async function submitForm(
433
433
 
434
434
  const items = getFormSubmissionData(
435
435
  summaryViewModel.context,
436
- summaryViewModel.details
436
+ summaryViewModel.details,
437
+ model
437
438
  )
438
439
 
439
440
  try {
@@ -531,11 +532,14 @@ function submitData(
531
532
  main: buildMainRecords(items),
532
533
  repeaters: buildRepeaterRecords(items)
533
534
  }
534
-
535
535
  return submit(payload)
536
536
  }
537
537
 
538
- export function getFormSubmissionData(context: FormContext, details: Detail[]) {
538
+ export function getFormSubmissionData(
539
+ context: FormContext,
540
+ details: Detail[],
541
+ model: FormModel
542
+ ) {
539
543
  const items = context.relevantPages
540
544
  .map(({ href }) =>
541
545
  details.flatMap(({ items }) =>
@@ -544,7 +548,7 @@ export function getFormSubmissionData(context: FormContext, details: Detail[]) {
544
548
  )
545
549
  .flat()
546
550
 
547
- const paymentItems = getPaymentFieldItems(context)
551
+ const paymentItems = getPaymentFieldItems(context, model)
548
552
 
549
553
  return [...items, ...paymentItems]
550
554
  }
@@ -553,10 +557,13 @@ export function getFormSubmissionData(context: FormContext, details: Detail[]) {
553
557
  * Gets DetailItems for PaymentField components
554
558
  * PaymentField is excluded from summaryDetails for UI but needs to be in submission data
555
559
  */
556
- function getPaymentFieldItems(context: FormContext): DetailItemField[] {
560
+ function getPaymentFieldItems(
561
+ context: FormContext,
562
+ model: FormModel
563
+ ): DetailItemField[] {
557
564
  const items: DetailItemField[] = []
558
565
 
559
- for (const page of context.relevantPages) {
566
+ for (const page of model.pages) {
560
567
  for (const field of page.collection.fields) {
561
568
  if (field instanceof PaymentField) {
562
569
  items.push({
@@ -15,6 +15,7 @@ import { getRoutes as getQuestionRoutes } from './routes/questions.js'
15
15
  import { getRoutes as getRepeaterItemDeleteRoutes } from './routes/repeaters/item-delete.js'
16
16
  import { getRoutes as getRepeaterSummaryRoutes } from './routes/repeaters/summary.js'
17
17
  import { type PluginOptions } from './types.js'
18
+ import { registerUnavailableResponse } from './unavailable-response.js'
18
19
  import { registerVision } from './vision.js'
19
20
  import { mapPlugin } from '../map/index.js'
20
21
  import { postcodeLookupPlugin } from '../postcode-lookup/index.js'
@@ -129,5 +130,10 @@ export const plugin = {
129
130
  ]
130
131
 
131
132
  server.route(routes as unknown as ServerRoute[]) // TODO
133
+
134
+ // Registration order is important: must be registered after the engine's
135
+ // routes so it sees their responses, but before any global error-page
136
+ // handler that would re-shape Boom errors.
137
+ registerUnavailableResponse(server)
132
138
  }
133
139
  } satisfies Plugin<PluginOptions>
@@ -59,7 +59,11 @@ async function handleHttpEvent(
59
59
  // TODO: Update structured data POST payload with when helper
60
60
  // is updated to removing the dependency on `SummaryViewModel` etc.
61
61
  const viewModel = new SummaryViewModel(request, page, context)
62
- const items = getFormSubmissionData(viewModel.context, viewModel.details)
62
+ const items = getFormSubmissionData(
63
+ viewModel.context,
64
+ viewModel.details,
65
+ model
66
+ )
63
67
 
64
68
  // @ts-expect-error - function signature will be refactored in the next iteration of the formatter
65
69
  const payload = format(context, items, model, undefined, undefined)
@@ -0,0 +1,29 @@
1
+ import { type Request, type ResponseToolkit, type Server } from '@hapi/hapi'
2
+
3
+ import { isOfflineBoom } from './form-availability.js'
4
+ import { unavailableViewModel } from './models/unavailable-view-model.js'
5
+
6
+ /**
7
+ * Registers a server-wide onPreResponse extension that intercepts the offline
8
+ * Boom thrown and renders the unavailable view.
9
+ *
10
+ * Must be registered after the engine's routes so it sees their responses,
11
+ * but before any global error-page handler that would re-shape Boom errors.
12
+ */
13
+ export function registerUnavailableResponse(server: Server) {
14
+ server.ext('onPreResponse', (request: Request, h: ResponseToolkit) => {
15
+ const response = request.response
16
+ if (!isOfflineBoom(response)) {
17
+ return h.continue
18
+ }
19
+
20
+ const { metadata } = response.data
21
+
22
+ return h
23
+ .view('unavailable', unavailableViewModel(metadata))
24
+ .header('Cache-Control', 'no-store, no-cache, must-revalidate')
25
+ .header('X-Robots-Tag', 'noindex, nofollow')
26
+ .code(200)
27
+ .takeover()
28
+ })
29
+ }
@@ -16,7 +16,8 @@
16
16
  {{ govukButton({
17
17
  text: "Upload file",
18
18
  classes: "govuk-button--secondary upload-file-button",
19
- preventDoubleClick: true
19
+ preventDoubleClick: true,
20
+ disabled: context.isForceAccess
20
21
  }) }}
21
22
  {% else %}
22
23
  {{ govukWarningText({
@@ -0,0 +1,20 @@
1
+ {% extends baseLayoutPath %}
2
+
3
+ {% block content %}
4
+ <div class="govuk-grid-row">
5
+ <div class="govuk-grid-column-two-thirds">
6
+ <h1 class="govuk-heading-l">Sorry, this form is unavailable</h1>
7
+ <p class="govuk-body">'{{ formTitle }}' has been archived and is no longer available.</p>
8
+ <p class="govuk-body">Contact the {{ organisationName }}.</p>
9
+
10
+ {% if phoneLines %}
11
+ <ul class="govuk-list govuk-list--bullet">
12
+ {% for line in phoneLines %}
13
+ <li>{{ line }}</li>
14
+ {% endfor %}
15
+ </ul>
16
+ <p class="govuk-body"><a href="https://www.gov.uk/call-charges" class="govuk-link govuk-link--no-visited-state">Find out about call charges</a></p>
17
+ {% endif %}
18
+ </div>
19
+ </div>
20
+ {% endblock %}
@@ -59,7 +59,7 @@ declare module '@hapi/hapi' {
59
59
 
60
60
  interface ServerApplicationState {
61
61
  model?: FormModel
62
- models: Map<string, { model: FormModel; updatedAt: Date }>
62
+ models?: Map<string, { model: FormModel; updatedAt: Date }>
63
63
  }
64
64
  }
65
65