@defra/forms-engine-plugin 4.23.0 → 5.0.0-alpha

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 (309) hide show
  1. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  2. package/.server/server/forms/simple-form.yaml +106 -3
  3. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +11 -11
  4. package/.server/server/plugins/engine/components/AutocompleteField.js +2 -2
  5. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
  6. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +3 -2
  7. package/.server/server/plugins/engine/components/CheckboxesField.js +4 -9
  8. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  9. package/.server/server/plugins/engine/components/ComponentCollection.d.ts +8 -7
  10. package/.server/server/plugins/engine/components/ComponentCollection.js +106 -51
  11. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  12. package/.server/server/plugins/engine/components/DatePartsField.d.ts +8 -6
  13. package/.server/server/plugins/engine/components/DatePartsField.js +27 -9
  14. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  15. package/.server/server/plugins/engine/components/DeclarationField.d.ts +13 -11
  16. package/.server/server/plugins/engine/components/DeclarationField.js +31 -9
  17. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  18. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +6 -5
  19. package/.server/server/plugins/engine/components/EastingNorthingField.js +42 -22
  20. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  21. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +11 -14
  22. package/.server/server/plugins/engine/components/EmailAddressField.js +2 -2
  23. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
  24. package/.server/server/plugins/engine/components/FileUploadField.d.ts +14 -12
  25. package/.server/server/plugins/engine/components/FileUploadField.js +22 -12
  26. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  27. package/.server/server/plugins/engine/components/FormComponent.d.ts +21 -12
  28. package/.server/server/plugins/engine/components/FormComponent.js +33 -14
  29. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  30. package/.server/server/plugins/engine/components/GeospatialField.d.ts +14 -12
  31. package/.server/server/plugins/engine/components/GeospatialField.js +19 -13
  32. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  33. package/.server/server/plugins/engine/components/LatLongField.d.ts +6 -5
  34. package/.server/server/plugins/engine/components/LatLongField.js +32 -20
  35. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  36. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +7 -6
  37. package/.server/server/plugins/engine/components/ListFormComponent.js +19 -7
  38. package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
  39. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +17 -16
  40. package/.server/server/plugins/engine/components/LocationFieldBase.js +2 -2
  41. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  42. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +3 -3
  43. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +2 -2
  44. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  45. package/.server/server/plugins/engine/components/Markdown.d.ts +8 -7
  46. package/.server/server/plugins/engine/components/Markdown.js +5 -2
  47. package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
  48. package/.server/server/plugins/engine/components/MonthYearField.d.ts +9 -7
  49. package/.server/server/plugins/engine/components/MonthYearField.js +26 -8
  50. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  51. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +10 -9
  52. package/.server/server/plugins/engine/components/MultilineTextField.js +2 -2
  53. package/.server/server/plugins/engine/components/MultilineTextField.js.map +1 -1
  54. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
  55. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +14 -6
  56. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
  57. package/.server/server/plugins/engine/components/NumberField.d.ts +10 -9
  58. package/.server/server/plugins/engine/components/NumberField.js +2 -2
  59. package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
  60. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +2 -1
  61. package/.server/server/plugins/engine/components/OsGridRefField.js +14 -6
  62. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
  63. package/.server/server/plugins/engine/components/PaymentField.d.ts +12 -10
  64. package/.server/server/plugins/engine/components/PaymentField.js +21 -8
  65. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  66. package/.server/server/plugins/engine/components/SelectField.d.ts +11 -11
  67. package/.server/server/plugins/engine/components/SelectField.js +2 -2
  68. package/.server/server/plugins/engine/components/SelectField.js.map +1 -1
  69. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +4 -4
  70. package/.server/server/plugins/engine/components/SelectionControlField.js +2 -2
  71. package/.server/server/plugins/engine/components/SelectionControlField.js.map +1 -1
  72. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +10 -9
  73. package/.server/server/plugins/engine/components/TelephoneNumberField.js +2 -2
  74. package/.server/server/plugins/engine/components/TelephoneNumberField.js.map +1 -1
  75. package/.server/server/plugins/engine/components/UkAddressField.d.ts +12 -10
  76. package/.server/server/plugins/engine/components/UkAddressField.js +29 -17
  77. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  78. package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -0
  79. package/.server/server/plugins/engine/components/YesNoField.js +9 -0
  80. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  81. package/.server/server/plugins/engine/components/helpers/components.d.ts +3 -2
  82. package/.server/server/plugins/engine/components/helpers/components.js +11 -8
  83. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  84. package/.server/server/plugins/engine/components/types.d.ts +8 -1
  85. package/.server/server/plugins/engine/components/types.js.map +1 -1
  86. package/.server/server/plugins/engine/configureEnginePlugin.js +8 -1
  87. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  88. package/.server/server/plugins/engine/form-context.d.ts +1 -0
  89. package/.server/server/plugins/engine/form-context.js +4 -2
  90. package/.server/server/plugins/engine/form-context.js.map +1 -1
  91. package/.server/server/plugins/engine/helpers.d.ts +1 -1
  92. package/.server/server/plugins/engine/helpers.js +8 -13
  93. package/.server/server/plugins/engine/helpers.js.map +1 -1
  94. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +39 -0
  95. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +50 -0
  96. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -0
  97. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +5 -0
  98. package/.server/server/plugins/engine/i18n/createFormTranslator.js +18 -0
  99. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -0
  100. package/.server/server/plugins/engine/i18n/createTranslator.d.ts +9 -0
  101. package/.server/server/plugins/engine/i18n/createTranslator.js +51 -0
  102. package/.server/server/plugins/engine/i18n/createTranslator.js.map +1 -0
  103. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +5 -0
  104. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +57 -0
  105. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -0
  106. package/.server/server/plugins/engine/i18n/index.d.ts +18 -0
  107. package/.server/server/plugins/engine/i18n/index.js +71 -0
  108. package/.server/server/plugins/engine/i18n/index.js.map +1 -0
  109. package/.server/server/plugins/engine/i18n/translations/cy.json +271 -0
  110. package/.server/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  111. package/.server/server/plugins/engine/i18n/types.d.ts +41 -0
  112. package/.server/server/plugins/engine/i18n/types.js +2 -0
  113. package/.server/server/plugins/engine/i18n/types.js.map +1 -0
  114. package/.server/server/plugins/engine/index.js +3 -2
  115. package/.server/server/plugins/engine/index.js.map +1 -1
  116. package/.server/server/plugins/engine/models/FormModel.d.ts +9 -1
  117. package/.server/server/plugins/engine/models/FormModel.js +44 -18
  118. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  119. package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +5 -2
  120. package/.server/server/plugins/engine/models/SummaryViewModel.js +44 -18
  121. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  122. package/.server/server/plugins/engine/options.js +2 -1
  123. package/.server/server/plugins/engine/options.js.map +1 -1
  124. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +4 -0
  125. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
  126. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  127. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  128. package/.server/server/plugins/engine/outputFormatters/machine/v1.js +7 -6
  129. package/.server/server/plugins/engine/outputFormatters/machine/v1.js.map +1 -1
  130. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +2 -1
  131. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +6 -3
  132. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  133. package/.server/server/plugins/engine/pageControllers/PageController.d.ts +3 -1
  134. package/.server/server/plugins/engine/pageControllers/PageController.js +11 -1
  135. package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
  136. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +4 -2
  137. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +52 -21
  138. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  139. package/.server/server/plugins/engine/pageControllers/RepeatPageController.d.ts +3 -2
  140. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +63 -26
  141. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
  142. package/.server/server/plugins/engine/pageControllers/StartPageController.d.ts +3 -1
  143. package/.server/server/plugins/engine/pageControllers/StartPageController.js +2 -2
  144. package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -1
  145. package/.server/server/plugins/engine/pageControllers/StatusPageController.js +12 -2
  146. package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -1
  147. package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +4 -3
  148. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +44 -28
  149. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  150. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.d.ts +2 -0
  151. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js +24 -0
  152. package/.server/server/plugins/engine/pageControllers/__stubs__/translator.js.map +1 -0
  153. package/.server/server/plugins/engine/pageControllers/errors.d.ts +1 -1
  154. package/.server/server/plugins/engine/pageControllers/errors.js +3 -2
  155. package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
  156. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +3 -2
  157. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +4 -4
  158. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  159. package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +7 -3
  160. package/.server/server/plugins/engine/pageControllers/validationOptions.js +34 -33
  161. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  162. package/.server/server/plugins/engine/plugin.js +2 -0
  163. package/.server/server/plugins/engine/plugin.js.map +1 -1
  164. package/.server/server/plugins/engine/routes/index.js +4 -1
  165. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  166. package/.server/server/plugins/engine/routes/questions.js +5 -2
  167. package/.server/server/plugins/engine/routes/questions.js.map +1 -1
  168. package/.server/server/plugins/engine/types/index.d.ts +1 -0
  169. package/.server/server/plugins/engine/types/index.js.map +1 -1
  170. package/.server/server/plugins/engine/types/schema.js +1 -0
  171. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  172. package/.server/server/plugins/engine/types.d.ts +12 -1
  173. package/.server/server/plugins/engine/types.js.map +1 -1
  174. package/.server/server/plugins/engine/views/components/_location-field-base.html +1 -1
  175. package/.server/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  176. package/.server/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  177. package/.server/server/plugins/engine/views/components/osgridreffield.html +1 -1
  178. package/.server/server/plugins/engine/views/components/paymentfield.html +8 -8
  179. package/.server/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  180. package/.server/server/plugins/engine/views/confirmation.html +4 -4
  181. package/.server/server/plugins/engine/views/exit.html +4 -4
  182. package/.server/server/plugins/engine/views/file-upload.html +3 -3
  183. package/.server/server/plugins/engine/views/index.html +3 -3
  184. package/.server/server/plugins/engine/views/item-delete.html +1 -1
  185. package/.server/server/plugins/engine/views/partials/form.html +3 -3
  186. package/.server/server/plugins/engine/views/partials/preview-banner.html +4 -4
  187. package/.server/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  188. package/.server/server/plugins/engine/views/repeat-list-summary.html +4 -4
  189. package/.server/server/plugins/engine/views/summary.html +14 -7
  190. package/.server/server/plugins/nunjucks/enviroment.test.js +10 -0
  191. package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
  192. package/.server/server/plugins/nunjucks/environment.d.ts +8 -0
  193. package/.server/server/plugins/nunjucks/environment.js +13 -0
  194. package/.server/server/plugins/nunjucks/environment.js.map +1 -1
  195. package/.server/server/plugins/nunjucks/filters/answer.js +9 -1
  196. package/.server/server/plugins/nunjucks/filters/answer.js.map +1 -1
  197. package/.server/server/plugins/nunjucks/filters/answer.test.js +13 -2
  198. package/.server/server/plugins/nunjucks/filters/answer.test.js.map +1 -1
  199. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  200. package/.server/server/plugins/postcode-lookup/models/index.d.ts +24 -19
  201. package/.server/server/plugins/postcode-lookup/models/index.js +83 -76
  202. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  203. package/.server/server/plugins/postcode-lookup/routes/index.js +7 -13
  204. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  205. package/.server/server/plugins/postcode-lookup/types.d.ts +1 -0
  206. package/.server/server/plugins/postcode-lookup/types.js +1 -0
  207. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  208. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  209. package/.server/server/types.d.ts +2 -1
  210. package/.server/server/types.js.map +1 -1
  211. package/.server/server/utils/utils.d.ts +5 -0
  212. package/.server/server/utils/utils.js +16 -0
  213. package/.server/server/utils/utils.js.map +1 -1
  214. package/.server/typings/hapi/index.d.js.map +1 -1
  215. package/package.json +3 -2
  216. package/src/server/forms/register-as-a-unicorn-breeder.yaml +0 -14
  217. package/src/server/forms/simple-form.yaml +106 -3
  218. package/src/server/plugins/engine/components/AutocompleteField.ts +3 -6
  219. package/src/server/plugins/engine/components/CheckboxesField.ts +12 -11
  220. package/src/server/plugins/engine/components/ComponentCollection.ts +143 -61
  221. package/src/server/plugins/engine/components/DatePartsField.ts +33 -11
  222. package/src/server/plugins/engine/components/DeclarationField.ts +37 -14
  223. package/src/server/plugins/engine/components/EastingNorthingField.ts +83 -22
  224. package/src/server/plugins/engine/components/EmailAddressField.ts +4 -7
  225. package/src/server/plugins/engine/components/FileUploadField.ts +28 -22
  226. package/src/server/plugins/engine/components/FormComponent.ts +49 -12
  227. package/src/server/plugins/engine/components/GeospatialField.ts +36 -21
  228. package/src/server/plugins/engine/components/LatLongField.ts +52 -21
  229. package/src/server/plugins/engine/components/ListFormComponent.ts +26 -10
  230. package/src/server/plugins/engine/components/LocationFieldBase.ts +5 -8
  231. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +3 -3
  232. package/src/server/plugins/engine/components/Markdown.ts +7 -3
  233. package/src/server/plugins/engine/components/MonthYearField.ts +32 -10
  234. package/src/server/plugins/engine/components/MultilineTextField.ts +5 -8
  235. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +25 -11
  236. package/src/server/plugins/engine/components/NumberField.ts +3 -4
  237. package/src/server/plugins/engine/components/OsGridRefField.ts +25 -9
  238. package/src/server/plugins/engine/components/PaymentField.ts +22 -12
  239. package/src/server/plugins/engine/components/SelectField.ts +3 -6
  240. package/src/server/plugins/engine/components/SelectionControlField.ts +7 -8
  241. package/src/server/plugins/engine/components/TelephoneNumberField.ts +4 -7
  242. package/src/server/plugins/engine/components/UkAddressField.ts +33 -18
  243. package/src/server/plugins/engine/components/YesNoField.ts +10 -0
  244. package/src/server/plugins/engine/components/helpers/components.ts +13 -6
  245. package/src/server/plugins/engine/components/types.ts +9 -0
  246. package/src/server/plugins/engine/configureEnginePlugin.ts +12 -1
  247. package/src/server/plugins/engine/form-context.ts +8 -2
  248. package/src/server/plugins/engine/helpers.ts +10 -18
  249. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +69 -0
  250. package/src/server/plugins/engine/i18n/createFormTranslator.ts +33 -0
  251. package/src/server/plugins/engine/i18n/createTranslator.ts +61 -0
  252. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +61 -0
  253. package/src/server/plugins/engine/i18n/index.ts +80 -0
  254. package/src/server/plugins/engine/i18n/translations/cy.json +271 -0
  255. package/src/server/plugins/engine/i18n/translations/en-GB.json +271 -0
  256. package/src/server/plugins/engine/i18n/types.ts +62 -0
  257. package/src/server/plugins/engine/index.ts +4 -2
  258. package/src/server/plugins/engine/models/FormModel.ts +59 -23
  259. package/src/server/plugins/engine/models/SummaryViewModel.ts +68 -25
  260. package/src/server/plugins/engine/options.js +2 -1
  261. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +5 -0
  262. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -3
  263. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +9 -8
  264. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +7 -3
  265. package/src/server/plugins/engine/pageControllers/PageController.ts +12 -1
  266. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +53 -21
  267. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +66 -29
  268. package/src/server/plugins/engine/pageControllers/StartPageController.ts +7 -2
  269. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +10 -2
  270. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +48 -22
  271. package/src/server/plugins/engine/pageControllers/__stubs__/translator.ts +28 -0
  272. package/src/server/plugins/engine/pageControllers/errors.ts +4 -2
  273. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +11 -4
  274. package/src/server/plugins/engine/pageControllers/validationOptions.ts +43 -53
  275. package/src/server/plugins/engine/plugin.ts +2 -0
  276. package/src/server/plugins/engine/routes/index.ts +9 -1
  277. package/src/server/plugins/engine/routes/questions.ts +5 -1
  278. package/src/server/plugins/engine/types/index.ts +5 -0
  279. package/src/server/plugins/engine/types/schema.ts +1 -0
  280. package/src/server/plugins/engine/types.ts +10 -0
  281. package/src/server/plugins/engine/views/components/_location-field-base.html +1 -1
  282. package/src/server/plugins/engine/views/components/fileuploadfield.html +3 -3
  283. package/src/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +1 -1
  284. package/src/server/plugins/engine/views/components/osgridreffield.html +1 -1
  285. package/src/server/plugins/engine/views/components/paymentfield.html +8 -8
  286. package/src/server/plugins/engine/views/components/ukaddressfield.html +4 -4
  287. package/src/server/plugins/engine/views/confirmation.html +4 -4
  288. package/src/server/plugins/engine/views/exit.html +4 -4
  289. package/src/server/plugins/engine/views/file-upload.html +3 -3
  290. package/src/server/plugins/engine/views/index.html +3 -3
  291. package/src/server/plugins/engine/views/item-delete.html +1 -1
  292. package/src/server/plugins/engine/views/partials/form.html +3 -3
  293. package/src/server/plugins/engine/views/partials/preview-banner.html +4 -4
  294. package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +4 -5
  295. package/src/server/plugins/engine/views/repeat-list-summary.html +4 -4
  296. package/src/server/plugins/engine/views/summary.html +14 -7
  297. package/src/server/plugins/nunjucks/environment.js +14 -0
  298. package/src/server/plugins/nunjucks/filters/answer.js +12 -1
  299. package/src/server/plugins/postcode-lookup/models/index.js +144 -87
  300. package/src/server/plugins/postcode-lookup/routes/index.js +13 -16
  301. package/src/server/plugins/postcode-lookup/types.js +1 -0
  302. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  303. package/src/server/types.ts +2 -0
  304. package/src/server/utils/utils.js +14 -0
  305. package/src/typings/hapi/index.d.ts +1 -0
  306. package/.server/server/plugins/engine/components/constants.d.ts +0 -1
  307. package/.server/server/plugins/engine/components/constants.js +0 -2
  308. package/.server/server/plugins/engine/components/constants.js.map +0 -1
  309. package/src/server/plugins/engine/components/constants.ts +0 -1
@@ -5,6 +5,7 @@ import { FormComponent, isFormState } from "./FormComponent.js";
5
5
  import { deduplicateErrorsByHref, getLocationFieldViewModel } from "./LocationFieldHelpers.js";
6
6
  import { NumberField } from "./NumberField.js";
7
7
  import { createLowerFirstExpression } from "./helpers/index.js";
8
+ import { t as tPlugin } from "../i18n/index.js";
8
9
  import { messageTemplate } from "../pageControllers/validationOptions.js";
9
10
  import { convertToLanguageMessages } from "../../../utils/type-utils.js";
10
11
 
@@ -26,24 +27,43 @@ export class EastingNorthingField extends FormComponent {
26
27
  const eastingMax = schema?.easting?.max ?? DEFAULT_EASTING_MAX;
27
28
  const northingMin = schema?.northing?.min ?? DEFAULT_NORTHING_MIN;
28
29
  const northingMax = schema?.northing?.max ?? DEFAULT_NORTHING_MAX;
29
- const eastingRequired = 'Enter easting';
30
- const northingRequired = 'Enter northing';
31
- const eastingDigitsMessage = `{{#label}} for ${lowerFirst(this.label)} must be between 1 and 6 digits`;
32
- const northingDigitsMessage = `{{#label}} for ${lowerFirst(this.label)} must be between 1 and 7 digits`;
30
+ const fieldLabel = lowerFirst(this.label);
31
+ const eastingDigitsMessage = tPlugin('components.eastingNorthingField.eastingDigits', 'en-GB', {
32
+ fieldLabel
33
+ });
34
+ const northingDigitsMessage = tPlugin('components.eastingNorthingField.northingDigits', 'en-GB', {
35
+ fieldLabel
36
+ });
33
37
  const customValidationMessages = convertToLanguageMessages({
34
- 'any.required': eastingRequired,
35
- 'number.base': eastingRequired,
36
- 'number.min': `{{#label}} for ${lowerFirst(this.label)} must be between {{#limit}} and ${eastingMax}`,
37
- 'number.max': `{{#label}} for ${lowerFirst(this.label)} must be between ${eastingMin} and {{#limit}}`,
38
+ 'any.required': tPlugin('components.eastingNorthingField.eastingRequired', 'en-GB'),
39
+ 'number.base': tPlugin('components.eastingNorthingField.eastingRequired', 'en-GB'),
40
+ 'number.min': tPlugin('components.eastingNorthingField.eastingRange', 'en-GB', {
41
+ fieldLabel,
42
+ min: eastingMin,
43
+ max: eastingMax
44
+ }),
45
+ 'number.max': tPlugin('components.eastingNorthingField.eastingRange', 'en-GB', {
46
+ fieldLabel,
47
+ min: eastingMin,
48
+ max: eastingMax
49
+ }),
38
50
  'number.precision': eastingDigitsMessage,
39
51
  'number.integer': eastingDigitsMessage,
40
52
  'number.unsafe': eastingDigitsMessage
41
53
  });
42
54
  const northingValidationMessages = convertToLanguageMessages({
43
- 'any.required': northingRequired,
44
- 'number.base': northingRequired,
45
- 'number.min': `{{#label}} for ${lowerFirst(this.label)} must be between {{#limit}} and ${northingMax}`,
46
- 'number.max': `{{#label}} for ${lowerFirst(this.label)} must be between ${northingMin} and {{#limit}}`,
55
+ 'any.required': tPlugin('components.eastingNorthingField.northingRequired', 'en-GB'),
56
+ 'number.base': tPlugin('components.eastingNorthingField.northingRequired', 'en-GB'),
57
+ 'number.min': tPlugin('components.eastingNorthingField.northingRange', 'en-GB', {
58
+ fieldLabel,
59
+ min: northingMin,
60
+ max: northingMax
61
+ }),
62
+ 'number.max': tPlugin('components.eastingNorthingField.northingRange', 'en-GB', {
63
+ fieldLabel,
64
+ min: northingMin,
65
+ max: northingMax
66
+ }),
47
67
  'number.precision': northingDigitsMessage,
48
68
  'number.integer': northingDigitsMessage,
49
69
  'number.unsafe': northingDigitsMessage
@@ -51,7 +71,7 @@ export class EastingNorthingField extends FormComponent {
51
71
  this.collection = new ComponentCollection([{
52
72
  type: ComponentType.NumberField,
53
73
  name: `${name}__easting`,
54
- title: 'Easting',
74
+ title: 'components.eastingNorthingField.easting',
55
75
  schema: {
56
76
  min: eastingMin,
57
77
  max: eastingMax,
@@ -66,7 +86,7 @@ export class EastingNorthingField extends FormComponent {
66
86
  }, {
67
87
  type: ComponentType.NumberField,
68
88
  name: `${name}__northing`,
69
- title: 'Northing',
89
+ title: 'components.eastingNorthingField.northing',
70
90
  schema: {
71
91
  min: northingMin,
72
92
  max: northingMax,
@@ -92,7 +112,7 @@ export class EastingNorthingField extends FormComponent {
92
112
  const value = super.getFormValueFromState(state);
93
113
  return EastingNorthingField.isEastingNorthing(value) ? value : undefined;
94
114
  }
95
- getDisplayStringFromFormValue(value) {
115
+ getDisplayStringFromFormValue(value, _translator) {
96
116
  if (!value) {
97
117
  return '';
98
118
  }
@@ -100,9 +120,9 @@ export class EastingNorthingField extends FormComponent {
100
120
  // CYA page format: <<eastingvalue, northingvalue>>
101
121
  return `${value.easting}, ${value.northing}`;
102
122
  }
103
- getDisplayStringFromState(state) {
123
+ getDisplayStringFromState(state, translator) {
104
124
  const value = this.getFormValueFromState(state);
105
- return this.getDisplayStringFromFormValue(value);
125
+ return this.getDisplayStringFromFormValue(value, translator);
106
126
  }
107
127
  getContextValueFromFormValue(value) {
108
128
  if (!value) {
@@ -114,12 +134,12 @@ export class EastingNorthingField extends FormComponent {
114
134
  const value = this.getFormValueFromState(state);
115
135
  return this.getContextValueFromFormValue(value);
116
136
  }
117
- getViewModel(payload, errors) {
118
- const viewModel = super.getViewModel(payload, errors);
119
- return getLocationFieldViewModel(this, viewModel, payload, errors);
137
+ getViewModel(context) {
138
+ const viewModel = super.getViewModel(context);
139
+ return getLocationFieldViewModel(this, viewModel, context);
120
140
  }
121
- getViewErrors(errors) {
122
- const allErrors = this.getErrors(errors);
141
+ getViewErrors(translator, errors) {
142
+ const allErrors = this.getErrors(translator, errors);
123
143
  return deduplicateErrorsByHref(allErrors);
124
144
  }
125
145
  isState(value) {
@@ -1 +1 @@
1
- {"version":3,"file":"EastingNorthingField.js","names":["ComponentType","lowerFirst","ComponentCollection","FormComponent","isFormState","deduplicateErrorsByHref","getLocationFieldViewModel","NumberField","createLowerFirstExpression","messageTemplate","convertToLanguageMessages","DEFAULT_EASTING_MIN","DEFAULT_EASTING_MAX","DEFAULT_NORTHING_MIN","DEFAULT_NORTHING_MAX","EastingNorthingField","constructor","def","props","name","options","schema","isRequired","required","eastingMin","easting","min","eastingMax","max","northingMin","northing","northingMax","eastingRequired","northingRequired","eastingDigitsMessage","label","northingDigitsMessage","customValidationMessages","northingValidationMessages","collection","type","title","precision","optionalText","classes","parent","peers","formSchema","stateSchema","getFormValueFromState","state","value","isEastingNorthing","undefined","getDisplayStringFromFormValue","getDisplayStringFromState","getContextValueFromFormValue","getContextValueFromState","getViewModel","payload","errors","viewModel","getViewErrors","allErrors","getErrors","isState","getAllPossibleErrors","baseErrors","template","advancedSettingsErrors","isNumber"],"sources":["../../../../../src/server/plugins/engine/components/EastingNorthingField.ts"],"sourcesContent":["import {\n ComponentType,\n type EastingNorthingFieldComponent\n} from '@defra/forms-model'\nimport { type LanguageMessages, type ObjectSchema } from 'joi'\nimport lowerFirst from 'lodash/lowerFirst.js'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport {\n FormComponent,\n isFormState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport {\n deduplicateErrorsByHref,\n getLocationFieldViewModel\n} from '~/src/server/plugins/engine/components/LocationFieldHelpers.js'\nimport { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'\nimport { createLowerFirstExpression } from '~/src/server/plugins/engine/components/helpers/index.js'\nimport { type EastingNorthingState } from '~/src/server/plugins/engine/components/types.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type ErrorMessageTemplateList,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { convertToLanguageMessages } from '~/src/server/utils/type-utils.js'\n\n// British National Grid coordinate limits\nconst DEFAULT_EASTING_MIN = 0\nconst DEFAULT_EASTING_MAX = 700000\nconst DEFAULT_NORTHING_MIN = 0\nconst DEFAULT_NORTHING_MAX = 1300000\n\nexport class EastingNorthingField extends FormComponent {\n declare options: EastingNorthingFieldComponent['options']\n declare formSchema: ObjectSchema<FormPayload>\n declare stateSchema: ObjectSchema<FormState>\n declare collection: ComponentCollection\n\n constructor(\n def: EastingNorthingFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { name, options, schema } = def\n\n const isRequired = options.required !== false\n\n const eastingMin = schema?.easting?.min ?? DEFAULT_EASTING_MIN\n const eastingMax = schema?.easting?.max ?? DEFAULT_EASTING_MAX\n const northingMin = schema?.northing?.min ?? DEFAULT_NORTHING_MIN\n const northingMax = schema?.northing?.max ?? DEFAULT_NORTHING_MAX\n\n const eastingRequired = 'Enter easting'\n const northingRequired = 'Enter northing'\n\n const eastingDigitsMessage = `{{#label}} for ${lowerFirst(this.label)} must be between 1 and 6 digits`\n const northingDigitsMessage = `{{#label}} for ${lowerFirst(this.label)} must be between 1 and 7 digits`\n\n const customValidationMessages: LanguageMessages =\n convertToLanguageMessages({\n 'any.required': eastingRequired,\n 'number.base': eastingRequired,\n 'number.min': `{{#label}} for ${lowerFirst(this.label)} must be between {{#limit}} and ${eastingMax}`,\n 'number.max': `{{#label}} for ${lowerFirst(this.label)} must be between ${eastingMin} and {{#limit}}`,\n 'number.precision': eastingDigitsMessage,\n 'number.integer': eastingDigitsMessage,\n 'number.unsafe': eastingDigitsMessage\n })\n\n const northingValidationMessages: LanguageMessages =\n convertToLanguageMessages({\n 'any.required': northingRequired,\n 'number.base': northingRequired,\n 'number.min': `{{#label}} for ${lowerFirst(this.label)} must be between {{#limit}} and ${northingMax}`,\n 'number.max': `{{#label}} for ${lowerFirst(this.label)} must be between ${northingMin} and {{#limit}}`,\n 'number.precision': northingDigitsMessage,\n 'number.integer': northingDigitsMessage,\n 'number.unsafe': northingDigitsMessage\n })\n\n this.collection = new ComponentCollection(\n [\n {\n type: ComponentType.NumberField,\n name: `${name}__easting`,\n title: 'Easting',\n schema: {\n min: eastingMin,\n max: eastingMax,\n precision: 0\n },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-10',\n customValidationMessages\n }\n },\n {\n type: ComponentType.NumberField,\n name: `${name}__northing`,\n title: 'Northing',\n schema: {\n min: northingMin,\n max: northingMax,\n precision: 0\n },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-10',\n customValidationMessages: northingValidationMessages\n }\n }\n ],\n { ...props, parent: this },\n {\n peers: [`${name}__easting`, `${name}__northing`]\n }\n )\n\n this.options = options\n this.formSchema = this.collection.formSchema\n this.stateSchema = this.collection.stateSchema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const value = super.getFormValueFromState(state)\n return EastingNorthingField.isEastingNorthing(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(\n value: EastingNorthingState | undefined\n ): string {\n if (!value) {\n return ''\n }\n\n // CYA page format: <<eastingvalue, northingvalue>>\n return `${value.easting}, ${value.northing}`\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value)\n }\n\n getContextValueFromFormValue(\n value: EastingNorthingState | undefined\n ): string | null {\n if (!value) {\n return null\n }\n\n return `Easting: ${value.easting}\\nNorthing: ${value.northing}`\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getContextValueFromFormValue(value)\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const viewModel = super.getViewModel(payload, errors)\n return getLocationFieldViewModel(this, viewModel, payload, errors)\n }\n\n getViewErrors(\n errors?: FormSubmissionError[]\n ): FormSubmissionError[] | undefined {\n const allErrors = this.getErrors(errors)\n return deduplicateErrorsByHref(allErrors)\n }\n\n isState(value?: FormStateValue | FormState) {\n return EastingNorthingField.isEastingNorthing(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return EastingNorthingField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'required', template: messageTemplate.required },\n {\n type: 'eastingFormat',\n template: createLowerFirstExpression(\n 'Easting for {{lowerFirst(#title)}} must be between 1 and 6 digits'\n )\n },\n {\n type: 'northingFormat',\n template: createLowerFirstExpression(\n 'Northing for {{lowerFirst(#title)}} must be between 1 and 7 digits'\n )\n }\n ],\n advancedSettingsErrors: [\n {\n type: 'eastingMin',\n template: createLowerFirstExpression(\n `Easting for {{lowerFirst(#title)}} must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`\n )\n },\n {\n type: 'eastingMax',\n template: createLowerFirstExpression(\n `Easting for {{lowerFirst(#title)}} must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`\n )\n },\n {\n type: 'northingMin',\n template: createLowerFirstExpression(\n `Northing for {{lowerFirst(#title)}} must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`\n )\n },\n {\n type: 'northingMax',\n template: createLowerFirstExpression(\n `Northing for {{lowerFirst(#title)}} must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`\n )\n }\n ]\n }\n }\n\n static isEastingNorthing(\n value?: FormStateValue | FormState\n ): value is EastingNorthingState {\n return (\n isFormState(value) &&\n NumberField.isNumber(value.easting) &&\n NumberField.isNumber(value.northing)\n )\n }\n}\n"],"mappings":"AAAA,SACEA,aAAa,QAER,oBAAoB;AAE3B,OAAOC,UAAU,MAAM,sBAAsB;AAE7C,SAASC,mBAAmB;AAC5B,SACEC,aAAa,EACbC,WAAW;AAEb,SACEC,uBAAuB,EACvBC,yBAAyB;AAE3B,SAASC,WAAW;AACpB,SAASC,0BAA0B;AAEnC,SAASC,eAAe;AASxB,SAASC,yBAAyB;;AAElC;AACA,MAAMC,mBAAmB,GAAG,CAAC;AAC7B,MAAMC,mBAAmB,GAAG,MAAM;AAClC,MAAMC,oBAAoB,GAAG,CAAC;AAC9B,MAAMC,oBAAoB,GAAG,OAAO;AAEpC,OAAO,MAAMC,oBAAoB,SAASZ,aAAa,CAAC;EAMtDa,WAAWA,CACTC,GAAkC,EAClCC,KAAqD,EACrD;IACA,KAAK,CAACD,GAAG,EAAEC,KAAK,CAAC;IAEjB,MAAM;MAAEC,IAAI;MAAEC,OAAO;MAAEC;IAAO,CAAC,GAAGJ,GAAG;IAErC,MAAMK,UAAU,GAAGF,OAAO,CAACG,QAAQ,KAAK,KAAK;IAE7C,MAAMC,UAAU,GAAGH,MAAM,EAAEI,OAAO,EAAEC,GAAG,IAAIf,mBAAmB;IAC9D,MAAMgB,UAAU,GAAGN,MAAM,EAAEI,OAAO,EAAEG,GAAG,IAAIhB,mBAAmB;IAC9D,MAAMiB,WAAW,GAAGR,MAAM,EAAES,QAAQ,EAAEJ,GAAG,IAAIb,oBAAoB;IACjE,MAAMkB,WAAW,GAAGV,MAAM,EAAES,QAAQ,EAAEF,GAAG,IAAId,oBAAoB;IAEjE,MAAMkB,eAAe,GAAG,eAAe;IACvC,MAAMC,gBAAgB,GAAG,gBAAgB;IAEzC,MAAMC,oBAAoB,GAAG,kBAAkBjC,UAAU,CAAC,IAAI,CAACkC,KAAK,CAAC,iCAAiC;IACtG,MAAMC,qBAAqB,GAAG,kBAAkBnC,UAAU,CAAC,IAAI,CAACkC,KAAK,CAAC,iCAAiC;IAEvG,MAAME,wBAA0C,GAC9C3B,yBAAyB,CAAC;MACxB,cAAc,EAAEsB,eAAe;MAC/B,aAAa,EAAEA,eAAe;MAC9B,YAAY,EAAE,kBAAkB/B,UAAU,CAAC,IAAI,CAACkC,KAAK,CAAC,mCAAmCR,UAAU,EAAE;MACrG,YAAY,EAAE,kBAAkB1B,UAAU,CAAC,IAAI,CAACkC,KAAK,CAAC,oBAAoBX,UAAU,iBAAiB;MACrG,kBAAkB,EAAEU,oBAAoB;MACxC,gBAAgB,EAAEA,oBAAoB;MACtC,eAAe,EAAEA;IACnB,CAAC,CAAC;IAEJ,MAAMI,0BAA4C,GAChD5B,yBAAyB,CAAC;MACxB,cAAc,EAAEuB,gBAAgB;MAChC,aAAa,EAAEA,gBAAgB;MAC/B,YAAY,EAAE,kBAAkBhC,UAAU,CAAC,IAAI,CAACkC,KAAK,CAAC,mCAAmCJ,WAAW,EAAE;MACtG,YAAY,EAAE,kBAAkB9B,UAAU,CAAC,IAAI,CAACkC,KAAK,CAAC,oBAAoBN,WAAW,iBAAiB;MACtG,kBAAkB,EAAEO,qBAAqB;MACzC,gBAAgB,EAAEA,qBAAqB;MACvC,eAAe,EAAEA;IACnB,CAAC,CAAC;IAEJ,IAAI,CAACG,UAAU,GAAG,IAAIrC,mBAAmB,CACvC,CACE;MACEsC,IAAI,EAAExC,aAAa,CAACO,WAAW;MAC/BY,IAAI,EAAE,GAAGA,IAAI,WAAW;MACxBsB,KAAK,EAAE,SAAS;MAChBpB,MAAM,EAAE;QACNK,GAAG,EAAEF,UAAU;QACfI,GAAG,EAAED,UAAU;QACfe,SAAS,EAAE;MACb,CAAC;MACDtB,OAAO,EAAE;QACPG,QAAQ,EAAED,UAAU;QACpBqB,YAAY,EAAE,IAAI;QAClBC,OAAO,EAAE,uBAAuB;QAChCP;MACF;IACF,CAAC,EACD;MACEG,IAAI,EAAExC,aAAa,CAACO,WAAW;MAC/BY,IAAI,EAAE,GAAGA,IAAI,YAAY;MACzBsB,KAAK,EAAE,UAAU;MACjBpB,MAAM,EAAE;QACNK,GAAG,EAAEG,WAAW;QAChBD,GAAG,EAAEG,WAAW;QAChBW,SAAS,EAAE;MACb,CAAC;MACDtB,OAAO,EAAE;QACPG,QAAQ,EAAED,UAAU;QACpBqB,YAAY,EAAE,IAAI;QAClBC,OAAO,EAAE,uBAAuB;QAChCP,wBAAwB,EAAEC;MAC5B;IACF,CAAC,CACF,EACD;MAAE,GAAGpB,KAAK;MAAE2B,MAAM,EAAE;IAAK,CAAC,EAC1B;MACEC,KAAK,EAAE,CAAC,GAAG3B,IAAI,WAAW,EAAE,GAAGA,IAAI,YAAY;IACjD,CACF,CAAC;IAED,IAAI,CAACC,OAAO,GAAGA,OAAO;IACtB,IAAI,CAAC2B,UAAU,GAAG,IAAI,CAACR,UAAU,CAACQ,UAAU;IAC5C,IAAI,CAACC,WAAW,GAAG,IAAI,CAACT,UAAU,CAACS,WAAW;EAChD;EAEAC,qBAAqBA,CAACC,KAA0B,EAAE;IAChD,MAAMC,KAAK,GAAG,KAAK,CAACF,qBAAqB,CAACC,KAAK,CAAC;IAChD,OAAOnC,oBAAoB,CAACqC,iBAAiB,CAACD,KAAK,CAAC,GAAGA,KAAK,GAAGE,SAAS;EAC1E;EAEAC,6BAA6BA,CAC3BH,KAAuC,EAC/B;IACR,IAAI,CAACA,KAAK,EAAE;MACV,OAAO,EAAE;IACX;;IAEA;IACA,OAAO,GAAGA,KAAK,CAAC1B,OAAO,KAAK0B,KAAK,CAACrB,QAAQ,EAAE;EAC9C;EAEAyB,yBAAyBA,CAACL,KAA0B,EAAE;IACpD,MAAMC,KAAK,GAAG,IAAI,CAACF,qBAAqB,CAACC,KAAK,CAAC;IAE/C,OAAO,IAAI,CAACI,6BAA6B,CAACH,KAAK,CAAC;EAClD;EAEAK,4BAA4BA,CAC1BL,KAAuC,EACxB;IACf,IAAI,CAACA,KAAK,EAAE;MACV,OAAO,IAAI;IACb;IAEA,OAAO,YAAYA,KAAK,CAAC1B,OAAO,eAAe0B,KAAK,CAACrB,QAAQ,EAAE;EACjE;EAEA2B,wBAAwBA,CAACP,KAA0B,EAAE;IACnD,MAAMC,KAAK,GAAG,IAAI,CAACF,qBAAqB,CAACC,KAAK,CAAC;IAE/C,OAAO,IAAI,CAACM,4BAA4B,CAACL,KAAK,CAAC;EACjD;EAEAO,YAAYA,CAACC,OAAoB,EAAEC,MAA8B,EAAE;IACjE,MAAMC,SAAS,GAAG,KAAK,CAACH,YAAY,CAACC,OAAO,EAAEC,MAAM,CAAC;IACrD,OAAOtD,yBAAyB,CAAC,IAAI,EAAEuD,SAAS,EAAEF,OAAO,EAAEC,MAAM,CAAC;EACpE;EAEAE,aAAaA,CACXF,MAA8B,EACK;IACnC,MAAMG,SAAS,GAAG,IAAI,CAACC,SAAS,CAACJ,MAAM,CAAC;IACxC,OAAOvD,uBAAuB,CAAC0D,SAAS,CAAC;EAC3C;EAEAE,OAAOA,CAACd,KAAkC,EAAE;IAC1C,OAAOpC,oBAAoB,CAACqC,iBAAiB,CAACD,KAAK,CAAC;EACtD;;EAEA;AACF;AACA;EACEe,oBAAoBA,CAAA,EAA6B;IAC/C,OAAOnD,oBAAoB,CAACmD,oBAAoB,CAAC,CAAC;EACpD;;EAEA;AACF;AACA;EACE,OAAOA,oBAAoBA,CAAA,EAA6B;IACtD,OAAO;MACLC,UAAU,EAAE,CACV;QAAE3B,IAAI,EAAE,UAAU;QAAE4B,QAAQ,EAAE3D,eAAe,CAACc;MAAS,CAAC,EACxD;QACEiB,IAAI,EAAE,eAAe;QACrB4B,QAAQ,EAAE5D,0BAA0B,CAClC,mEACF;MACF,CAAC,EACD;QACEgC,IAAI,EAAE,gBAAgB;QACtB4B,QAAQ,EAAE5D,0BAA0B,CAClC,oEACF;MACF,CAAC,CACF;MACD6D,sBAAsB,EAAE,CACtB;QACE7B,IAAI,EAAE,YAAY;QAClB4B,QAAQ,EAAE5D,0BAA0B,CAClC,sDAAsDG,mBAAmB,QAAQC,mBAAmB,EACtG;MACF,CAAC,EACD;QACE4B,IAAI,EAAE,YAAY;QAClB4B,QAAQ,EAAE5D,0BAA0B,CAClC,sDAAsDG,mBAAmB,QAAQC,mBAAmB,EACtG;MACF,CAAC,EACD;QACE4B,IAAI,EAAE,aAAa;QACnB4B,QAAQ,EAAE5D,0BAA0B,CAClC,uDAAuDK,oBAAoB,QAAQC,oBAAoB,EACzG;MACF,CAAC,EACD;QACE0B,IAAI,EAAE,aAAa;QACnB4B,QAAQ,EAAE5D,0BAA0B,CAClC,uDAAuDK,oBAAoB,QAAQC,oBAAoB,EACzG;MACF,CAAC;IAEL,CAAC;EACH;EAEA,OAAOsC,iBAAiBA,CACtBD,KAAkC,EACH;IAC/B,OACE/C,WAAW,CAAC+C,KAAK,CAAC,IAClB5C,WAAW,CAAC+D,QAAQ,CAACnB,KAAK,CAAC1B,OAAO,CAAC,IACnClB,WAAW,CAAC+D,QAAQ,CAACnB,KAAK,CAACrB,QAAQ,CAAC;EAExC;AACF","ignoreList":[]}
1
+ {"version":3,"file":"EastingNorthingField.js","names":["ComponentType","lowerFirst","ComponentCollection","FormComponent","isFormState","deduplicateErrorsByHref","getLocationFieldViewModel","NumberField","createLowerFirstExpression","t","tPlugin","messageTemplate","convertToLanguageMessages","DEFAULT_EASTING_MIN","DEFAULT_EASTING_MAX","DEFAULT_NORTHING_MIN","DEFAULT_NORTHING_MAX","EastingNorthingField","constructor","def","props","name","options","schema","isRequired","required","eastingMin","easting","min","eastingMax","max","northingMin","northing","northingMax","fieldLabel","label","eastingDigitsMessage","northingDigitsMessage","customValidationMessages","northingValidationMessages","collection","type","title","precision","optionalText","classes","parent","peers","formSchema","stateSchema","getFormValueFromState","state","value","isEastingNorthing","undefined","getDisplayStringFromFormValue","_translator","getDisplayStringFromState","translator","getContextValueFromFormValue","getContextValueFromState","getViewModel","context","viewModel","getViewErrors","errors","allErrors","getErrors","isState","getAllPossibleErrors","baseErrors","template","advancedSettingsErrors","isNumber"],"sources":["../../../../../src/server/plugins/engine/components/EastingNorthingField.ts"],"sourcesContent":["import {\n ComponentType,\n type EastingNorthingFieldComponent\n} from '@defra/forms-model'\nimport { type LanguageMessages, type ObjectSchema } from 'joi'\nimport lowerFirst from 'lodash/lowerFirst.js'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport {\n FormComponent,\n isFormState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport {\n deduplicateErrorsByHref,\n getLocationFieldViewModel\n} from '~/src/server/plugins/engine/components/LocationFieldHelpers.js'\nimport { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'\nimport { createLowerFirstExpression } from '~/src/server/plugins/engine/components/helpers/index.js'\nimport {\n type EastingNorthingState,\n type RenderContext\n} from '~/src/server/plugins/engine/components/types.js'\nimport { t as tPlugin } from '~/src/server/plugins/engine/i18n/index.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type ErrorMessageTemplateList,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { convertToLanguageMessages } from '~/src/server/utils/type-utils.js'\n\n// British National Grid coordinate limits\nconst DEFAULT_EASTING_MIN = 0\nconst DEFAULT_EASTING_MAX = 700000\nconst DEFAULT_NORTHING_MIN = 0\nconst DEFAULT_NORTHING_MAX = 1300000\n\nexport class EastingNorthingField extends FormComponent {\n declare options: EastingNorthingFieldComponent['options']\n declare formSchema: ObjectSchema<FormPayload>\n declare stateSchema: ObjectSchema<FormState>\n declare collection: ComponentCollection\n\n constructor(\n def: EastingNorthingFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { name, options, schema } = def\n\n const isRequired = options.required !== false\n\n const eastingMin = schema?.easting?.min ?? DEFAULT_EASTING_MIN\n const eastingMax = schema?.easting?.max ?? DEFAULT_EASTING_MAX\n const northingMin = schema?.northing?.min ?? DEFAULT_NORTHING_MIN\n const northingMax = schema?.northing?.max ?? DEFAULT_NORTHING_MAX\n\n const fieldLabel = lowerFirst(this.label)\n\n const eastingDigitsMessage = tPlugin(\n 'components.eastingNorthingField.eastingDigits',\n 'en-GB',\n { fieldLabel }\n )\n const northingDigitsMessage = tPlugin(\n 'components.eastingNorthingField.northingDigits',\n 'en-GB',\n { fieldLabel }\n )\n\n const customValidationMessages: LanguageMessages =\n convertToLanguageMessages({\n 'any.required': tPlugin(\n 'components.eastingNorthingField.eastingRequired',\n 'en-GB'\n ),\n 'number.base': tPlugin(\n 'components.eastingNorthingField.eastingRequired',\n 'en-GB'\n ),\n 'number.min': tPlugin(\n 'components.eastingNorthingField.eastingRange',\n 'en-GB',\n {\n fieldLabel,\n min: eastingMin,\n max: eastingMax\n }\n ),\n 'number.max': tPlugin(\n 'components.eastingNorthingField.eastingRange',\n 'en-GB',\n {\n fieldLabel,\n min: eastingMin,\n max: eastingMax\n }\n ),\n 'number.precision': eastingDigitsMessage,\n 'number.integer': eastingDigitsMessage,\n 'number.unsafe': eastingDigitsMessage\n })\n\n const northingValidationMessages: LanguageMessages =\n convertToLanguageMessages({\n 'any.required': tPlugin(\n 'components.eastingNorthingField.northingRequired',\n 'en-GB'\n ),\n 'number.base': tPlugin(\n 'components.eastingNorthingField.northingRequired',\n 'en-GB'\n ),\n 'number.min': tPlugin(\n 'components.eastingNorthingField.northingRange',\n 'en-GB',\n {\n fieldLabel,\n min: northingMin,\n max: northingMax\n }\n ),\n 'number.max': tPlugin(\n 'components.eastingNorthingField.northingRange',\n 'en-GB',\n {\n fieldLabel,\n min: northingMin,\n max: northingMax\n }\n ),\n 'number.precision': northingDigitsMessage,\n 'number.integer': northingDigitsMessage,\n 'number.unsafe': northingDigitsMessage\n })\n\n this.collection = new ComponentCollection(\n [\n {\n type: ComponentType.NumberField,\n name: `${name}__easting`,\n title: 'components.eastingNorthingField.easting',\n schema: {\n min: eastingMin,\n max: eastingMax,\n precision: 0\n },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-10',\n customValidationMessages\n }\n },\n {\n type: ComponentType.NumberField,\n name: `${name}__northing`,\n title: 'components.eastingNorthingField.northing',\n schema: {\n min: northingMin,\n max: northingMax,\n precision: 0\n },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-10',\n customValidationMessages: northingValidationMessages\n }\n }\n ],\n { ...props, parent: this },\n {\n peers: [`${name}__easting`, `${name}__northing`]\n }\n )\n\n this.options = options\n this.formSchema = this.collection.formSchema\n this.stateSchema = this.collection.stateSchema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const value = super.getFormValueFromState(state)\n return EastingNorthingField.isEastingNorthing(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(\n value: EastingNorthingState | undefined,\n _translator: Translator\n ): string {\n if (!value) {\n return ''\n }\n\n // CYA page format: <<eastingvalue, northingvalue>>\n return `${value.easting}, ${value.northing}`\n }\n\n getDisplayStringFromState(\n state: FormSubmissionState,\n translator: Translator\n ) {\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value, translator)\n }\n\n getContextValueFromFormValue(\n value: EastingNorthingState | undefined\n ): string | null {\n if (!value) {\n return null\n }\n\n return `Easting: ${value.easting}\\nNorthing: ${value.northing}`\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getContextValueFromFormValue(value)\n }\n\n getViewModel(context: RenderContext) {\n const viewModel = super.getViewModel(context)\n return getLocationFieldViewModel(this, viewModel, context)\n }\n\n getViewErrors(\n translator: Translator,\n errors?: FormSubmissionError[]\n ): FormSubmissionError[] | undefined {\n const allErrors = this.getErrors(translator, errors)\n return deduplicateErrorsByHref(allErrors)\n }\n\n isState(value?: FormStateValue | FormState) {\n return EastingNorthingField.isEastingNorthing(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return EastingNorthingField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'required', template: messageTemplate.required },\n {\n type: 'eastingFormat',\n template: createLowerFirstExpression(\n 'Easting for {{lowerFirst(#title)}} must be between 1 and 6 digits'\n )\n },\n {\n type: 'northingFormat',\n template: createLowerFirstExpression(\n 'Northing for {{lowerFirst(#title)}} must be between 1 and 7 digits'\n )\n }\n ],\n advancedSettingsErrors: [\n {\n type: 'eastingMin',\n template: createLowerFirstExpression(\n `Easting for {{lowerFirst(#title)}} must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`\n )\n },\n {\n type: 'eastingMax',\n template: createLowerFirstExpression(\n `Easting for {{lowerFirst(#title)}} must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`\n )\n },\n {\n type: 'northingMin',\n template: createLowerFirstExpression(\n `Northing for {{lowerFirst(#title)}} must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`\n )\n },\n {\n type: 'northingMax',\n template: createLowerFirstExpression(\n `Northing for {{lowerFirst(#title)}} must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`\n )\n }\n ]\n }\n }\n\n static isEastingNorthing(\n value?: FormStateValue | FormState\n ): value is EastingNorthingState {\n return (\n isFormState(value) &&\n NumberField.isNumber(value.easting) &&\n NumberField.isNumber(value.northing)\n )\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,10 +1,11 @@
1
1
  import { type EmailAddressFieldComponent } from '@defra/forms-model';
2
2
  import { FormComponent } from '../../../../server/plugins/engine/components/FormComponent.js';
3
- import { type ErrorMessageTemplateList, type FormPayload, type FormSubmissionError } from '../../../../server/plugins/engine/types.js';
3
+ import { type RenderContext } from '../../../../server/plugins/engine/components/types.js';
4
+ import { type ErrorMessageTemplateList } from '../../../../server/plugins/engine/types.js';
4
5
  export declare class EmailAddressField extends FormComponent {
5
6
  options: EmailAddressFieldComponent['options'];
6
7
  constructor(def: EmailAddressFieldComponent, props: ConstructorParameters<typeof FormComponent>[1]);
7
- getViewModel(payload: FormPayload, errors?: FormSubmissionError[]): {
8
+ getViewModel(context: RenderContext): {
8
9
  type: string;
9
10
  label: {
10
11
  text: string;
@@ -16,11 +17,11 @@ export declare class EmailAddressField extends FormComponent {
16
17
  id?: string;
17
18
  text: string;
18
19
  };
19
- prefix?: import("./types.js").ComponentText;
20
- suffix?: import("./types.js").ComponentText;
20
+ prefix?: import("../../../../server/plugins/engine/components/types.js").ComponentText;
21
+ suffix?: import("../../../../server/plugins/engine/components/types.js").ComponentText;
21
22
  classes?: string;
22
23
  condition?: string;
23
- errors?: FormSubmissionError[];
24
+ errors?: import("../../../../server/plugins/engine/types.js").FormSubmissionError[];
24
25
  errorMessage?: {
25
26
  text: string;
26
27
  };
@@ -30,28 +31,24 @@ export declare class EmailAddressField extends FormComponent {
30
31
  autocomplete?: string;
31
32
  maxlength?: number;
32
33
  multiple?: string;
33
- accept
34
- /**
35
- * For error preview page that shows all possible errors on a component
36
- */
37
- ?: string;
34
+ accept?: string;
38
35
  inputmode?: string;
39
36
  };
40
- content?: import("./types.js").Content | import("./types.js").Content[] | string;
37
+ content?: import("../../../../server/plugins/engine/components/types.js").Content | import("../../../../server/plugins/engine/components/types.js").Content[] | string;
41
38
  maxlength?: number;
42
39
  maxwords?: number;
43
40
  rows?: number;
44
- items?: import("./types.js").ListItem[] | import("./types.js").DateInputItem[];
41
+ items?: import("../../../../server/plugins/engine/components/types.js").ListItem[] | import("../../../../server/plugins/engine/components/types.js").DateInputItem[];
45
42
  fieldset?: {
46
43
  attributes?: string | Record<string, string>;
47
- legend?: import("./types.js").Label;
44
+ legend?: import("../../../../server/plugins/engine/components/types.js").Label;
48
45
  };
49
46
  formGroup?: {
50
47
  classes?: string;
51
48
  attributes?: string | Record<string, string>;
52
49
  };
53
50
  showFieldsetError?: boolean;
54
- components?: import("./types.js").ComponentViewModel[];
51
+ components?: import("../../../../server/plugins/engine/components/types.js").ComponentViewModel[];
55
52
  upload?: {
56
53
  count: number;
57
54
  summaryList: import("../../../../server/plugins/engine/types.js").SummaryList;
@@ -26,8 +26,8 @@ export class EmailAddressField extends FormComponent {
26
26
  this.stateSchema = formSchema.default(null).allow(null);
27
27
  this.options = options;
28
28
  }
29
- getViewModel(payload, errors) {
30
- const viewModel = super.getViewModel(payload, errors);
29
+ getViewModel(context) {
30
+ const viewModel = super.getViewModel(context);
31
31
  const {
32
32
  attributes
33
33
  } = viewModel;
@@ -1 +1 @@
1
- {"version":3,"file":"EmailAddressField.js","names":["preventUnicodeInEmail","joi","FormComponent","messageTemplate","EmailAddressField","constructor","def","props","options","formSchema","string","trim","email","custom","value","helpers","label","required","allow","customValidationMessage","message","messages","customValidationMessages","default","stateSchema","getViewModel","payload","errors","viewModel","attributes","autocomplete","type","getAllPossibleErrors","baseErrors","template","format","unicode","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/EmailAddressField.ts"],"sourcesContent":["import {\n preventUnicodeInEmail,\n type EmailAddressFieldComponent\n} from '@defra/forms-model'\nimport joi, { type CustomHelpers } from 'joi'\n\nimport { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type ErrorMessageTemplateList,\n type FormPayload,\n type FormSubmissionError\n} from '~/src/server/plugins/engine/types.js'\n\nexport class EmailAddressField extends FormComponent {\n declare options: EmailAddressFieldComponent['options']\n\n constructor(\n def: EmailAddressFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options } = def\n\n let formSchema = joi\n .string()\n .trim()\n .email()\n .custom((value, helpers: CustomHelpers<string>) =>\n preventUnicodeInEmail(value, helpers)\n )\n .label(this.label)\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.allow('')\n }\n\n if (options.customValidationMessage) {\n const message = options.customValidationMessage\n\n formSchema = formSchema.messages({\n 'any.required': message,\n 'string.empty': message,\n 'string.email': message\n })\n } else if (options.customValidationMessages) {\n formSchema = formSchema.messages(options.customValidationMessages)\n }\n\n this.formSchema = formSchema.default('')\n this.stateSchema = formSchema.default(null).allow(null)\n this.options = options\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const viewModel = super.getViewModel(payload, errors)\n const { attributes } = viewModel\n\n attributes.autocomplete = 'email'\n\n return {\n ...viewModel,\n type: 'email'\n }\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return EmailAddressField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'required', template: messageTemplate.required },\n { type: 'format', template: messageTemplate.format },\n { type: 'unicode', template: messageTemplate.unicode }\n ],\n advancedSettingsErrors: []\n }\n }\n}\n"],"mappings":"AAAA,SACEA,qBAAqB,QAEhB,oBAAoB;AAC3B,OAAOC,GAAG,MAA8B,KAAK;AAE7C,SAASC,aAAa;AACtB,SAASC,eAAe;AAOxB,OAAO,MAAMC,iBAAiB,SAASF,aAAa,CAAC;EAGnDG,WAAWA,CACTC,GAA+B,EAC/BC,KAAqD,EACrD;IACA,KAAK,CAACD,GAAG,EAAEC,KAAK,CAAC;IAEjB,MAAM;MAAEC;IAAQ,CAAC,GAAGF,GAAG;IAEvB,IAAIG,UAAU,GAAGR,GAAG,CACjBS,MAAM,CAAC,CAAC,CACRC,IAAI,CAAC,CAAC,CACNC,KAAK,CAAC,CAAC,CACPC,MAAM,CAAC,CAACC,KAAK,EAAEC,OAA8B,KAC5Cf,qBAAqB,CAACc,KAAK,EAAEC,OAAO,CACtC,CAAC,CACAC,KAAK,CAAC,IAAI,CAACA,KAAK,CAAC,CACjBC,QAAQ,CAAC,CAAC;IAEb,IAAIT,OAAO,CAACS,QAAQ,KAAK,KAAK,EAAE;MAC9BR,UAAU,GAAGA,UAAU,CAACS,KAAK,CAAC,EAAE,CAAC;IACnC;IAEA,IAAIV,OAAO,CAACW,uBAAuB,EAAE;MACnC,MAAMC,OAAO,GAAGZ,OAAO,CAACW,uBAAuB;MAE/CV,UAAU,GAAGA,UAAU,CAACY,QAAQ,CAAC;QAC/B,cAAc,EAAED,OAAO;QACvB,cAAc,EAAEA,OAAO;QACvB,cAAc,EAAEA;MAClB,CAAC,CAAC;IACJ,CAAC,MAAM,IAAIZ,OAAO,CAACc,wBAAwB,EAAE;MAC3Cb,UAAU,GAAGA,UAAU,CAACY,QAAQ,CAACb,OAAO,CAACc,wBAAwB,CAAC;IACpE;IAEA,IAAI,CAACb,UAAU,GAAGA,UAAU,CAACc,OAAO,CAAC,EAAE,CAAC;IACxC,IAAI,CAACC,WAAW,GAAGf,UAAU,CAACc,OAAO,CAAC,IAAI,CAAC,CAACL,KAAK,CAAC,IAAI,CAAC;IACvD,IAAI,CAACV,OAAO,GAAGA,OAAO;EACxB;EAEAiB,YAAYA,CAACC,OAAoB,EAAEC,MAA8B,EAAE;IACjE,MAAMC,SAAS,GAAG,KAAK,CAACH,YAAY,CAACC,OAAO,EAAEC,MAAM,CAAC;IACrD,MAAM;MAAEE;IAAW,CAAC,GAAGD,SAAS;IAEhCC,UAAU,CAACC,YAAY,GAAG,OAAO;IAEjC,OAAO;MACL,GAAGF,SAAS;MACZG,IAAI,EAAE;IACR,CAAC;EACH;;EAEA;AACF;AACA;EACEC,oBAAoBA,CAAA,EAA6B;IAC/C,OAAO5B,iBAAiB,CAAC4B,oBAAoB,CAAC,CAAC;EACjD;;EAEA;AACF;AACA;EACE,OAAOA,oBAAoBA,CAAA,EAA6B;IACtD,OAAO;MACLC,UAAU,EAAE,CACV;QAAEF,IAAI,EAAE,UAAU;QAAEG,QAAQ,EAAE/B,eAAe,CAACc;MAAS,CAAC,EACxD;QAAEc,IAAI,EAAE,QAAQ;QAAEG,QAAQ,EAAE/B,eAAe,CAACgC;MAAO,CAAC,EACpD;QAAEJ,IAAI,EAAE,SAAS;QAAEG,QAAQ,EAAE/B,eAAe,CAACiC;MAAQ,CAAC,CACvD;MACDC,sBAAsB,EAAE;IAC1B,CAAC;EACH;AACF","ignoreList":[]}
1
+ {"version":3,"file":"EmailAddressField.js","names":["preventUnicodeInEmail","joi","FormComponent","messageTemplate","EmailAddressField","constructor","def","props","options","formSchema","string","trim","email","custom","value","helpers","label","required","allow","customValidationMessage","message","messages","customValidationMessages","default","stateSchema","getViewModel","context","viewModel","attributes","autocomplete","type","getAllPossibleErrors","baseErrors","template","format","unicode","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/EmailAddressField.ts"],"sourcesContent":["import {\n preventUnicodeInEmail,\n type EmailAddressFieldComponent\n} from '@defra/forms-model'\nimport joi, { type CustomHelpers } from 'joi'\n\nimport { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type RenderContext } from '~/src/server/plugins/engine/components/types.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport { type ErrorMessageTemplateList } from '~/src/server/plugins/engine/types.js'\n\nexport class EmailAddressField extends FormComponent {\n declare options: EmailAddressFieldComponent['options']\n\n constructor(\n def: EmailAddressFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options } = def\n\n let formSchema = joi\n .string()\n .trim()\n .email()\n .custom((value, helpers: CustomHelpers<string>) =>\n preventUnicodeInEmail(value, helpers)\n )\n .label(this.label)\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.allow('')\n }\n\n if (options.customValidationMessage) {\n const message = options.customValidationMessage\n\n formSchema = formSchema.messages({\n 'any.required': message,\n 'string.empty': message,\n 'string.email': message\n })\n } else if (options.customValidationMessages) {\n formSchema = formSchema.messages(options.customValidationMessages)\n }\n\n this.formSchema = formSchema.default('')\n this.stateSchema = formSchema.default(null).allow(null)\n this.options = options\n }\n\n getViewModel(context: RenderContext) {\n const viewModel = super.getViewModel(context)\n const { attributes } = viewModel\n\n attributes.autocomplete = 'email'\n\n return {\n ...viewModel,\n type: 'email'\n }\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return EmailAddressField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'required', template: messageTemplate.required },\n { type: 'format', template: messageTemplate.format },\n { type: 'unicode', template: messageTemplate.unicode }\n ],\n advancedSettingsErrors: []\n }\n }\n}\n"],"mappings":"AAAA,SACEA,qBAAqB,QAEhB,oBAAoB;AAC3B,OAAOC,GAAG,MAA8B,KAAK;AAE7C,SAASC,aAAa;AAEtB,SAASC,eAAe;AAGxB,OAAO,MAAMC,iBAAiB,SAASF,aAAa,CAAC;EAGnDG,WAAWA,CACTC,GAA+B,EAC/BC,KAAqD,EACrD;IACA,KAAK,CAACD,GAAG,EAAEC,KAAK,CAAC;IAEjB,MAAM;MAAEC;IAAQ,CAAC,GAAGF,GAAG;IAEvB,IAAIG,UAAU,GAAGR,GAAG,CACjBS,MAAM,CAAC,CAAC,CACRC,IAAI,CAAC,CAAC,CACNC,KAAK,CAAC,CAAC,CACPC,MAAM,CAAC,CAACC,KAAK,EAAEC,OAA8B,KAC5Cf,qBAAqB,CAACc,KAAK,EAAEC,OAAO,CACtC,CAAC,CACAC,KAAK,CAAC,IAAI,CAACA,KAAK,CAAC,CACjBC,QAAQ,CAAC,CAAC;IAEb,IAAIT,OAAO,CAACS,QAAQ,KAAK,KAAK,EAAE;MAC9BR,UAAU,GAAGA,UAAU,CAACS,KAAK,CAAC,EAAE,CAAC;IACnC;IAEA,IAAIV,OAAO,CAACW,uBAAuB,EAAE;MACnC,MAAMC,OAAO,GAAGZ,OAAO,CAACW,uBAAuB;MAE/CV,UAAU,GAAGA,UAAU,CAACY,QAAQ,CAAC;QAC/B,cAAc,EAAED,OAAO;QACvB,cAAc,EAAEA,OAAO;QACvB,cAAc,EAAEA;MAClB,CAAC,CAAC;IACJ,CAAC,MAAM,IAAIZ,OAAO,CAACc,wBAAwB,EAAE;MAC3Cb,UAAU,GAAGA,UAAU,CAACY,QAAQ,CAACb,OAAO,CAACc,wBAAwB,CAAC;IACpE;IAEA,IAAI,CAACb,UAAU,GAAGA,UAAU,CAACc,OAAO,CAAC,EAAE,CAAC;IACxC,IAAI,CAACC,WAAW,GAAGf,UAAU,CAACc,OAAO,CAAC,IAAI,CAAC,CAACL,KAAK,CAAC,IAAI,CAAC;IACvD,IAAI,CAACV,OAAO,GAAGA,OAAO;EACxB;EAEAiB,YAAYA,CAACC,OAAsB,EAAE;IACnC,MAAMC,SAAS,GAAG,KAAK,CAACF,YAAY,CAACC,OAAO,CAAC;IAC7C,MAAM;MAAEE;IAAW,CAAC,GAAGD,SAAS;IAEhCC,UAAU,CAACC,YAAY,GAAG,OAAO;IAEjC,OAAO;MACL,GAAGF,SAAS;MACZG,IAAI,EAAE;IACR,CAAC;EACH;;EAEA;AACF;AACA;EACEC,oBAAoBA,CAAA,EAA6B;IAC/C,OAAO3B,iBAAiB,CAAC2B,oBAAoB,CAAC,CAAC;EACjD;;EAEA;AACF;AACA;EACE,OAAOA,oBAAoBA,CAAA,EAA6B;IACtD,OAAO;MACLC,UAAU,EAAE,CACV;QAAEF,IAAI,EAAE,UAAU;QAAEG,QAAQ,EAAE9B,eAAe,CAACc;MAAS,CAAC,EACxD;QAAEa,IAAI,EAAE,QAAQ;QAAEG,QAAQ,EAAE9B,eAAe,CAAC+B;MAAO,CAAC,EACpD;QAAEJ,IAAI,EAAE,SAAS;QAAEG,QAAQ,EAAE9B,eAAe,CAACgC;MAAQ,CAAC,CACvD;MACDC,sBAAsB,EAAE;IAC1B,CAAC;EACH;AACF","ignoreList":[]}
@@ -1,8 +1,10 @@
1
1
  import { type FileUploadFieldComponent, type FormMetadata } from '@defra/forms-model';
2
2
  import joi, { type ArraySchema } from 'joi';
3
3
  import { FormComponent } from '../../../../server/plugins/engine/components/FormComponent.js';
4
- import { type ErrorMessageTemplateList, type FileState, type FileUpload, type FileUploadMetadata, type FormContext, type FormPayload, type FormState, type FormStateValue, type FormSubmissionError, type FormSubmissionState, type SummaryList, type UploadState, type UploadStatusFileResponse, type UploadStatusResponse } from '../../../../server/plugins/engine/types.js';
5
- import { type FormQuery, type FormRequestPayload } from '../../../../server/routes/types.js';
4
+ import { type RenderContext } from '../../../../server/plugins/engine/components/types.js';
5
+ import { type Translator } from '../../../../server/plugins/engine/i18n/types.js';
6
+ import { type ErrorMessageTemplateList, type FileState, type FileUpload, type FileUploadMetadata, type FormContext, type FormState, type FormStateValue, type FormSubmissionState, type SummaryList, type UploadState, type UploadStatusFileResponse, type UploadStatusResponse } from '../../../../server/plugins/engine/types.js';
7
+ import { type FormRequestPayload } from '../../../../server/routes/types.js';
6
8
  export declare const uploadIdSchema: joi.StringSchema<string>;
7
9
  export declare const fileSchema: joi.ObjectSchema<FileUpload>;
8
10
  export declare const tempFileSchema: joi.ObjectSchema<FileUpload>;
@@ -21,11 +23,11 @@ export declare class FileUploadField extends FormComponent {
21
23
  constructor(def: FileUploadFieldComponent, props: ConstructorParameters<typeof FormComponent>[1]);
22
24
  getFormValueFromState(state: FormSubmissionState): UploadState | undefined;
23
25
  getFormValue(value?: FormStateValue | FormState): UploadState | undefined;
24
- getDisplayStringFromFormValue(files: FileState[] | undefined): string;
25
- getDisplayStringFromState(state: FormSubmissionState): string;
26
+ getDisplayStringFromFormValue(files: FileState[] | undefined, translator: Translator): string;
27
+ getDisplayStringFromState(state: FormSubmissionState, translator: Translator): string;
26
28
  getContextValueFromFormValue(files: UploadState | undefined): string[] | null;
27
29
  getContextValueFromState(state: FormSubmissionState): string[] | null;
28
- getViewModel(payload: FormPayload, errors?: FormSubmissionError[], query?: FormQuery): {
30
+ getViewModel(context: RenderContext): {
29
31
  upload: {
30
32
  count: number;
31
33
  summaryList: SummaryList;
@@ -42,11 +44,11 @@ export declare class FileUploadField extends FormComponent {
42
44
  id?: string;
43
45
  text: string;
44
46
  };
45
- prefix?: import("./types.js").ComponentText;
46
- suffix?: import("./types.js").ComponentText;
47
+ prefix?: import("../../../../server/plugins/engine/components/types.js").ComponentText;
48
+ suffix?: import("../../../../server/plugins/engine/components/types.js").ComponentText;
47
49
  classes?: string;
48
50
  condition?: string;
49
- errors?: FormSubmissionError[];
51
+ errors?: import("../../../../server/plugins/engine/types.js").FormSubmissionError[];
50
52
  errorMessage?: {
51
53
  text: string;
52
54
  };
@@ -59,21 +61,21 @@ export declare class FileUploadField extends FormComponent {
59
61
  accept?: string;
60
62
  inputmode?: string;
61
63
  };
62
- content?: import("./types.js").Content | import("./types.js").Content[] | string;
64
+ content?: import("../../../../server/plugins/engine/components/types.js").Content | import("../../../../server/plugins/engine/components/types.js").Content[] | string;
63
65
  maxlength?: number;
64
66
  maxwords?: number;
65
67
  rows?: number;
66
- items?: import("./types.js").ListItem[] | import("./types.js").DateInputItem[];
68
+ items?: import("../../../../server/plugins/engine/components/types.js").ListItem[] | import("../../../../server/plugins/engine/components/types.js").DateInputItem[];
67
69
  fieldset?: {
68
70
  attributes?: string | Record<string, string>;
69
- legend?: import("./types.js").Label;
71
+ legend?: import("../../../../server/plugins/engine/components/types.js").Label;
70
72
  };
71
73
  formGroup?: {
72
74
  classes?: string;
73
75
  attributes?: string | Record<string, string>;
74
76
  };
75
77
  showFieldsetError?: boolean;
76
- components?: import("./types.js").ComponentViewModel[];
78
+ components?: import("../../../../server/plugins/engine/components/types.js").ComponentViewModel[];
77
79
  };
78
80
  isValue(value?: FormStateValue | FormState): value is UploadState;
79
81
  /**
@@ -5,6 +5,7 @@ import { InvalidComponentStateError } from "../pageControllers/errors.js";
5
5
  import { messageTemplate } from "../pageControllers/validationOptions.js";
6
6
  import { FileStatus, UploadStatus } from "../types.js";
7
7
  import { render } from "../../nunjucks/index.js";
8
+ import { resolveLanguage } from "../../../utils/utils.js";
8
9
  export const uploadIdSchema = joi.string().uuid().required();
9
10
  export const fileSchema = joi.object({
10
11
  fileId: joi.string().uuid().required(),
@@ -83,16 +84,17 @@ export class FileUploadField extends FormComponent {
83
84
  getFormValue(value) {
84
85
  return this.isValue(value) ? value : undefined;
85
86
  }
86
- getDisplayStringFromFormValue(files) {
87
+ getDisplayStringFromFormValue(files, translator) {
87
88
  if (!files?.length) {
88
89
  return '';
89
90
  }
90
- const unit = files.length === 1 ? 'file' : 'files';
91
- return `Uploaded ${files.length} ${unit}`;
91
+ return translator.t('components.fileUploadField.filesCount', {
92
+ count: files.length
93
+ });
92
94
  }
93
- getDisplayStringFromState(state) {
95
+ getDisplayStringFromState(state, translator) {
94
96
  const files = this.getFormValueFromState(state);
95
- return this.getDisplayStringFromFormValue(files);
97
+ return this.getDisplayStringFromFormValue(files, translator);
96
98
  }
97
99
  getContextValueFromFormValue(files) {
98
100
  return files?.map(({
@@ -103,16 +105,20 @@ export class FileUploadField extends FormComponent {
103
105
  const files = this.getFormValueFromState(state);
104
106
  return this.getContextValueFromFormValue(files);
105
107
  }
106
- getViewModel(payload, errors, query = {}) {
108
+ getViewModel(context) {
109
+ const {
110
+ errors,
111
+ isForceAccess = false
112
+ } = context;
113
+ const {
114
+ t
115
+ } = context.translator;
107
116
  const {
108
117
  options,
109
118
  page,
110
119
  schema
111
120
  } = this;
112
-
113
- // Allow preview URL direct access
114
- const isForceAccess = 'force' in query;
115
- const viewModel = super.getViewModel(payload, errors);
121
+ const viewModel = super.getViewModel(context);
116
122
  const {
117
123
  attributes,
118
124
  id,
@@ -133,7 +139,7 @@ export class FileUploadField extends FormComponent {
133
139
  } = form;
134
140
  const tag = {
135
141
  classes: 'govuk-tag--green',
136
- text: 'Uploaded'
142
+ text: t('components.fileUploadField.uploaded')
137
143
  };
138
144
  const valueHtml = render.view('components/fileuploadfield-value.html', {
139
145
  context: {
@@ -217,6 +223,10 @@ export class FileUploadField extends FormComponent {
217
223
  return FileUploadField.getAllPossibleErrors();
218
224
  }
219
225
  async onSubmit(request, metadata, context) {
226
+ const language = resolveLanguage(request);
227
+ const {
228
+ t
229
+ } = this.model.createTranslator(language);
220
230
  const notificationEmail = metadata.notificationEmail;
221
231
  if (!notificationEmail) {
222
232
  // this should not happen because notificationEmail is checked further up
@@ -249,7 +259,7 @@ export class FileUploadField extends FormComponent {
249
259
  // Failed to persist files. We can't recover from this, the only real way we can recover the submissions is
250
260
  // by resetting the problematic components and letting the user re-try.
251
261
  // Scenarios: file missing from S3, invalid retrieval key (timing problem), etc.
252
- throw new InvalidComponentStateError(this, 'There was a problem with your uploaded files. Re-upload them before submitting the form again.');
262
+ throw new InvalidComponentStateError(this, t('components.fileUploadField.uploadFailed'));
253
263
  }
254
264
  throw error;
255
265
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FileUploadField.js","names":["Boom","joi","FormComponent","isUploadState","InvalidComponentStateError","messageTemplate","FileStatus","UploadStatus","render","uploadIdSchema","string","uuid","required","fileSchema","object","fileId","filename","contentLength","number","tempFileSchema","append","fileStatus","valid","complete","rejected","pending","errorMessage","optional","formFileSchema","metadataSchema","keys","retrievalKey","email","tempStatusSchema","uploadStatus","ready","metadata","form","file","array","items","single","numberOfRejectedFiles","formStatusSchema","itemSchema","uploadId","tempItemSchema","status","formItemSchema","FileUploadField","constructor","def","props","options","schema","formSchema","label","length","max","min","stateSchema","default","allow","getFormValueFromState","state","name","getFormValue","value","isValue","undefined","getDisplayStringFromFormValue","files","unit","getDisplayStringFromState","getContextValueFromFormValue","map","getContextValueFromState","getViewModel","payload","errors","query","page","isForceAccess","viewModel","attributes","id","filtered","filter","count","rows","item","index","tag","classes","text","valueHtml","view","context","params","trim","keyHtml","path","href","getHref","push","visuallyHiddenText","key","html","actions","accept","allowsMultiple","summaryList","multiple","upload","getAllPossibleErrors","onSubmit","request","notificationEmail","Error","app","model","services","formSubmissionService","values","initiatedRetrievalKey","persistFiles","error","isBoom","output","statusCode","baseErrors","type","template","selectRequired","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/FileUploadField.ts"],"sourcesContent":["import {\n type FileUploadFieldComponent,\n type FormMetadata\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport joi, { type ArraySchema } from 'joi'\n\nimport {\n FormComponent,\n isUploadState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { InvalidComponentStateError } from '~/src/server/plugins/engine/pageControllers/errors.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n FileStatus,\n UploadStatus,\n type ErrorMessageTemplateList,\n type FileState,\n type FileUpload,\n type FileUploadMetadata,\n type FormContext,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState,\n type SummaryList,\n type SummaryListAction,\n type SummaryListRow,\n type UploadState,\n type UploadStatusFileResponse,\n type UploadStatusResponse\n} from '~/src/server/plugins/engine/types.js'\nimport { render } from '~/src/server/plugins/nunjucks/index.js'\nimport {\n type FormQuery,\n type FormRequestPayload\n} from '~/src/server/routes/types.js'\n\nexport const uploadIdSchema = joi.string().uuid().required()\n\nexport const fileSchema = joi\n .object<FileUpload>({\n fileId: joi.string().uuid().required(),\n filename: joi.string().required(),\n contentLength: joi.number().required()\n })\n .required()\n\nexport const tempFileSchema = fileSchema.append({\n fileStatus: joi\n .string()\n .valid(FileStatus.complete, FileStatus.rejected, FileStatus.pending)\n .required(),\n errorMessage: joi.string().optional()\n})\n\nexport const formFileSchema = fileSchema.append({\n fileStatus: joi.string().valid(FileStatus.complete).required()\n})\n\nexport const metadataSchema = joi\n .object<FileUploadMetadata>()\n .keys({\n retrievalKey: joi.string().email().required()\n })\n .required()\n\nexport const tempStatusSchema = joi\n .object<UploadStatusFileResponse>({\n uploadStatus: joi\n .string()\n .valid(UploadStatus.ready, UploadStatus.pending)\n .required(),\n metadata: metadataSchema,\n form: joi\n .object()\n .required()\n .keys({\n file: joi.array().items(tempFileSchema).single().required()\n }),\n numberOfRejectedFiles: joi.number().optional()\n })\n .required()\n\nexport const formStatusSchema = joi\n .object<UploadStatusResponse>({\n uploadStatus: joi.string().valid(UploadStatus.ready).required(),\n metadata: metadataSchema,\n form: joi.object().required().keys({\n file: formFileSchema\n }),\n numberOfRejectedFiles: joi.number().required()\n })\n .required()\n\nexport const itemSchema = joi.object<FileState>({\n uploadId: uploadIdSchema\n})\n\nexport const tempItemSchema = itemSchema.append({\n status: tempStatusSchema\n})\n\nexport const formItemSchema = itemSchema.append({\n status: formStatusSchema\n})\n\nexport class FileUploadField extends FormComponent {\n declare options: FileUploadFieldComponent['options']\n declare schema: FileUploadFieldComponent['schema']\n declare formSchema: ArraySchema<FileState>\n declare stateSchema: ArraySchema<FileState>\n\n constructor(\n def: FileUploadFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options, schema } = def\n\n let formSchema = joi\n .array<FileState>()\n .label(this.label)\n .single()\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.optional()\n }\n\n if (typeof schema.length !== 'number') {\n if (typeof schema.max === 'number') {\n formSchema = formSchema.max(schema.max)\n }\n\n if (typeof schema.min === 'number') {\n formSchema = formSchema.min(schema.min)\n } else if (options.required !== false) {\n formSchema = formSchema.min(1)\n }\n } else {\n formSchema = formSchema.length(schema.length)\n }\n\n this.formSchema = formSchema.items(formItemSchema)\n this.stateSchema = formSchema\n .items(formItemSchema)\n .default(null)\n .allow(null)\n\n this.options = options\n this.schema = schema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const { name } = this\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(files: FileState[] | undefined): string {\n if (!files?.length) {\n return ''\n }\n\n const unit = files.length === 1 ? 'file' : 'files'\n return `Uploaded ${files.length} ${unit}`\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const files = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(files)\n }\n\n getContextValueFromFormValue(\n files: UploadState | undefined\n ): string[] | null {\n return files?.map(({ status }) => status.form.file.fileId) ?? null\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const files = this.getFormValueFromState(state)\n return this.getContextValueFromFormValue(files)\n }\n\n getViewModel(\n payload: FormPayload,\n errors?: FormSubmissionError[],\n query: FormQuery = {}\n ) {\n const { options, page, schema } = this\n\n // Allow preview URL direct access\n const isForceAccess = 'force' in query\n\n const viewModel = super.getViewModel(payload, errors)\n const { attributes, id, value } = viewModel\n\n const files = this.getFormValue(value) ?? []\n const filtered = files.filter(\n (file) => file.status.form.file.fileStatus === FileStatus.complete\n )\n const count = filtered.length\n\n const rows: SummaryListRow[] = filtered.map((item, index) => {\n const { status } = item\n const { form } = status\n const { file } = form\n\n const tag = { classes: 'govuk-tag--green', text: 'Uploaded' }\n\n const valueHtml = render\n .view('components/fileuploadfield-value.html', {\n context: { params: { tag } }\n })\n .trim()\n\n const keyHtml = render\n .view('components/fileuploadfield-key.html', {\n context: {\n params: {\n name: file.filename,\n errorMessage: errors && file.errorMessage\n }\n }\n })\n .trim()\n\n const items: SummaryListAction[] = []\n\n // Remove summary list actions from previews\n if (!isForceAccess) {\n const path = `/${file.fileId}/confirm-delete`\n const href = page?.getHref(`${page.path}${path}`) ?? '#'\n\n items.push({\n href,\n text: 'Remove',\n classes: 'govuk-link--no-visited-state',\n attributes: { id: `${id}__${index}` },\n visuallyHiddenText: file.filename\n })\n }\n\n return {\n key: {\n html: keyHtml\n },\n value: {\n html: valueHtml\n },\n actions: {\n items\n }\n } satisfies SummaryListRow\n })\n\n // Set up the `accept` attribute\n if ('accept' in options && options.accept) {\n attributes.accept = options.accept\n }\n\n // Allow multiple file selection when schema permits more than 1 file\n const allowsMultiple = schema.max !== 1 && schema.length !== 1\n\n const summaryList: SummaryList = {\n classes: 'govuk-summary-list--long-key',\n rows\n }\n\n return {\n ...viewModel,\n\n // File input can't have a initial value\n value: '',\n\n // Override the component name we send to CDP\n name: 'file',\n\n // Enable multi-file selection in the file picker\n ...(allowsMultiple && { multiple: true }),\n\n upload: {\n count,\n summaryList\n }\n }\n }\n\n isValue(value?: FormStateValue | FormState): value is UploadState {\n return isUploadState(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FileUploadField.getAllPossibleErrors()\n }\n\n async onSubmit(\n request: FormRequestPayload,\n metadata: FormMetadata,\n context: FormContext\n ) {\n const notificationEmail = metadata.notificationEmail\n\n if (!notificationEmail) {\n // this should not happen because notificationEmail is checked further up\n // the chain in SummaryPageController before submitForm is called.\n throw new Error('Unexpected missing notificationEmail in metadata')\n }\n\n if (!request.app.model?.services.formSubmissionService) {\n throw new Error('No form submission service available in app model')\n }\n\n const { formSubmissionService } = request.app.model.services\n const values = this.getFormValueFromState(context.state) ?? []\n\n const files = values.map((value) => ({\n fileId: value.status.form.file.fileId,\n initiatedRetrievalKey: value.status.metadata.retrievalKey\n }))\n\n if (!files.length) {\n return\n }\n\n try {\n await formSubmissionService.persistFiles(files, notificationEmail)\n } catch (error) {\n if (\n Boom.isBoom(error) &&\n (error.output.statusCode === 403 || // Forbidden - retrieval key invalid\n error.output.statusCode === 404 || // Not Found - file not found\n error.output.statusCode === 410) // Gone - file expired (took to long to submit, etc)\n ) {\n // Failed to persist files. We can't recover from this, the only real way we can recover the submissions is\n // by resetting the problematic components and letting the user re-try.\n // Scenarios: file missing from S3, invalid retrieval key (timing problem), etc.\n throw new InvalidComponentStateError(\n this,\n 'There was a problem with your uploaded files. Re-upload them before submitting the form again.'\n )\n }\n\n throw error\n }\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'selectRequired', template: messageTemplate.selectRequired },\n {\n type: 'filesMimes',\n template: 'The selected file must be a {{#limit}}'\n },\n {\n type: 'filesSize',\n template: 'The selected file must be smaller than 100MB'\n },\n { type: 'filesEmpty', template: 'The selected file is empty' },\n { type: 'filesVirus', template: 'The selected file contains a virus' },\n {\n type: 'filesPartial',\n template: 'The selected file has not fully uploaded'\n },\n {\n type: 'filesError',\n template: 'The selected file could not be uploaded – try again'\n }\n ],\n advancedSettingsErrors: [\n {\n type: 'filesMin',\n template: 'You must upload {{#limit}} files or more'\n },\n {\n type: 'filesMax',\n template: 'You can only upload {{#limit}} files or less'\n },\n {\n type: 'filesExact',\n template: 'You must upload exactly {{#limit}} files'\n }\n ]\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"FileUploadField.js","names":["Boom","joi","FormComponent","isUploadState","InvalidComponentStateError","messageTemplate","FileStatus","UploadStatus","render","resolveLanguage","uploadIdSchema","string","uuid","required","fileSchema","object","fileId","filename","contentLength","number","tempFileSchema","append","fileStatus","valid","complete","rejected","pending","errorMessage","optional","formFileSchema","metadataSchema","keys","retrievalKey","email","tempStatusSchema","uploadStatus","ready","metadata","form","file","array","items","single","numberOfRejectedFiles","formStatusSchema","itemSchema","uploadId","tempItemSchema","status","formItemSchema","FileUploadField","constructor","def","props","options","schema","formSchema","label","length","max","min","stateSchema","default","allow","getFormValueFromState","state","name","getFormValue","value","isValue","undefined","getDisplayStringFromFormValue","files","translator","t","count","getDisplayStringFromState","getContextValueFromFormValue","map","getContextValueFromState","getViewModel","context","errors","isForceAccess","page","viewModel","attributes","id","filtered","filter","rows","item","index","tag","classes","text","valueHtml","view","params","trim","keyHtml","path","href","getHref","push","visuallyHiddenText","key","html","actions","accept","allowsMultiple","summaryList","multiple","upload","getAllPossibleErrors","onSubmit","request","language","model","createTranslator","notificationEmail","Error","app","services","formSubmissionService","values","initiatedRetrievalKey","persistFiles","error","isBoom","output","statusCode","baseErrors","type","template","selectRequired","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/FileUploadField.ts"],"sourcesContent":["import {\n type FileUploadFieldComponent,\n type FormMetadata\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport joi, { type ArraySchema } from 'joi'\n\nimport {\n FormComponent,\n isUploadState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type RenderContext } from '~/src/server/plugins/engine/components/types.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { InvalidComponentStateError } from '~/src/server/plugins/engine/pageControllers/errors.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n FileStatus,\n UploadStatus,\n type ErrorMessageTemplateList,\n type FileState,\n type FileUpload,\n type FileUploadMetadata,\n type FormContext,\n type FormState,\n type FormStateValue,\n type FormSubmissionState,\n type SummaryList,\n type SummaryListAction,\n type SummaryListRow,\n type UploadState,\n type UploadStatusFileResponse,\n type UploadStatusResponse\n} from '~/src/server/plugins/engine/types.js'\nimport { render } from '~/src/server/plugins/nunjucks/index.js'\nimport { type FormRequestPayload } from '~/src/server/routes/types.js'\nimport { resolveLanguage } from '~/src/server/utils/utils.js'\n\nexport const uploadIdSchema = joi.string().uuid().required()\n\nexport const fileSchema = joi\n .object<FileUpload>({\n fileId: joi.string().uuid().required(),\n filename: joi.string().required(),\n contentLength: joi.number().required()\n })\n .required()\n\nexport const tempFileSchema = fileSchema.append({\n fileStatus: joi\n .string()\n .valid(FileStatus.complete, FileStatus.rejected, FileStatus.pending)\n .required(),\n errorMessage: joi.string().optional()\n})\n\nexport const formFileSchema = fileSchema.append({\n fileStatus: joi.string().valid(FileStatus.complete).required()\n})\n\nexport const metadataSchema = joi\n .object<FileUploadMetadata>()\n .keys({\n retrievalKey: joi.string().email().required()\n })\n .required()\n\nexport const tempStatusSchema = joi\n .object<UploadStatusFileResponse>({\n uploadStatus: joi\n .string()\n .valid(UploadStatus.ready, UploadStatus.pending)\n .required(),\n metadata: metadataSchema,\n form: joi\n .object()\n .required()\n .keys({\n file: joi.array().items(tempFileSchema).single().required()\n }),\n numberOfRejectedFiles: joi.number().optional()\n })\n .required()\n\nexport const formStatusSchema = joi\n .object<UploadStatusResponse>({\n uploadStatus: joi.string().valid(UploadStatus.ready).required(),\n metadata: metadataSchema,\n form: joi.object().required().keys({\n file: formFileSchema\n }),\n numberOfRejectedFiles: joi.number().required()\n })\n .required()\n\nexport const itemSchema = joi.object<FileState>({\n uploadId: uploadIdSchema\n})\n\nexport const tempItemSchema = itemSchema.append({\n status: tempStatusSchema\n})\n\nexport const formItemSchema = itemSchema.append({\n status: formStatusSchema\n})\n\nexport class FileUploadField extends FormComponent {\n declare options: FileUploadFieldComponent['options']\n declare schema: FileUploadFieldComponent['schema']\n declare formSchema: ArraySchema<FileState>\n declare stateSchema: ArraySchema<FileState>\n\n constructor(\n def: FileUploadFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options, schema } = def\n\n let formSchema = joi\n .array<FileState>()\n .label(this.label)\n .single()\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.optional()\n }\n\n if (typeof schema.length !== 'number') {\n if (typeof schema.max === 'number') {\n formSchema = formSchema.max(schema.max)\n }\n\n if (typeof schema.min === 'number') {\n formSchema = formSchema.min(schema.min)\n } else if (options.required !== false) {\n formSchema = formSchema.min(1)\n }\n } else {\n formSchema = formSchema.length(schema.length)\n }\n\n this.formSchema = formSchema.items(formItemSchema)\n this.stateSchema = formSchema\n .items(formItemSchema)\n .default(null)\n .allow(null)\n\n this.options = options\n this.schema = schema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const { name } = this\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(\n files: FileState[] | undefined,\n translator: Translator\n ): string {\n if (!files?.length) {\n return ''\n }\n\n return translator.t('components.fileUploadField.filesCount', {\n count: files.length\n })\n }\n\n getDisplayStringFromState(\n state: FormSubmissionState,\n translator: Translator\n ) {\n const files = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(files, translator)\n }\n\n getContextValueFromFormValue(\n files: UploadState | undefined\n ): string[] | null {\n return files?.map(({ status }) => status.form.file.fileId) ?? null\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const files = this.getFormValueFromState(state)\n return this.getContextValueFromFormValue(files)\n }\n\n getViewModel(context: RenderContext) {\n const { errors, isForceAccess = false } = context\n const { t } = context.translator\n const { options, page, schema } = this\n\n const viewModel = super.getViewModel(context)\n const { attributes, id, value } = viewModel\n\n const files = this.getFormValue(value) ?? []\n const filtered = files.filter(\n (file) => file.status.form.file.fileStatus === FileStatus.complete\n )\n const count = filtered.length\n\n const rows: SummaryListRow[] = filtered.map((item, index) => {\n const { status } = item\n const { form } = status\n const { file } = form\n\n const tag = {\n classes: 'govuk-tag--green',\n text: t('components.fileUploadField.uploaded')\n }\n\n const valueHtml = render\n .view('components/fileuploadfield-value.html', {\n context: { params: { tag } }\n })\n .trim()\n\n const keyHtml = render\n .view('components/fileuploadfield-key.html', {\n context: {\n params: {\n name: file.filename,\n errorMessage: errors && file.errorMessage\n }\n }\n })\n .trim()\n\n const items: SummaryListAction[] = []\n\n // Remove summary list actions from previews\n if (!isForceAccess) {\n const path = `/${file.fileId}/confirm-delete`\n const href = page?.getHref(`${page.path}${path}`) ?? '#'\n\n items.push({\n href,\n text: 'Remove',\n classes: 'govuk-link--no-visited-state',\n attributes: { id: `${id}__${index}` },\n visuallyHiddenText: file.filename\n })\n }\n\n return {\n key: {\n html: keyHtml\n },\n value: {\n html: valueHtml\n },\n actions: {\n items\n }\n } satisfies SummaryListRow\n })\n\n // Set up the `accept` attribute\n if ('accept' in options && options.accept) {\n attributes.accept = options.accept\n }\n\n // Allow multiple file selection when schema permits more than 1 file\n const allowsMultiple = schema.max !== 1 && schema.length !== 1\n\n const summaryList: SummaryList = {\n classes: 'govuk-summary-list--long-key',\n rows\n }\n\n return {\n ...viewModel,\n\n // File input can't have a initial value\n value: '',\n\n // Override the component name we send to CDP\n name: 'file',\n\n // Enable multi-file selection in the file picker\n ...(allowsMultiple && { multiple: true }),\n\n upload: {\n count,\n summaryList\n }\n }\n }\n\n isValue(value?: FormStateValue | FormState): value is UploadState {\n return isUploadState(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FileUploadField.getAllPossibleErrors()\n }\n\n async onSubmit(\n request: FormRequestPayload,\n metadata: FormMetadata,\n context: FormContext\n ) {\n const language = resolveLanguage(request)\n const { t } = this.model.createTranslator(language)\n\n const notificationEmail = metadata.notificationEmail\n\n if (!notificationEmail) {\n // this should not happen because notificationEmail is checked further up\n // the chain in SummaryPageController before submitForm is called.\n throw new Error('Unexpected missing notificationEmail in metadata')\n }\n\n if (!request.app.model?.services.formSubmissionService) {\n throw new Error('No form submission service available in app model')\n }\n\n const { formSubmissionService } = request.app.model.services\n const values = this.getFormValueFromState(context.state) ?? []\n\n const files = values.map((value) => ({\n fileId: value.status.form.file.fileId,\n initiatedRetrievalKey: value.status.metadata.retrievalKey\n }))\n\n if (!files.length) {\n return\n }\n\n try {\n await formSubmissionService.persistFiles(files, notificationEmail)\n } catch (error) {\n if (\n Boom.isBoom(error) &&\n (error.output.statusCode === 403 || // Forbidden - retrieval key invalid\n error.output.statusCode === 404 || // Not Found - file not found\n error.output.statusCode === 410) // Gone - file expired (took to long to submit, etc)\n ) {\n // Failed to persist files. We can't recover from this, the only real way we can recover the submissions is\n // by resetting the problematic components and letting the user re-try.\n // Scenarios: file missing from S3, invalid retrieval key (timing problem), etc.\n throw new InvalidComponentStateError(\n this,\n t('components.fileUploadField.uploadFailed')\n )\n }\n\n throw error\n }\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'selectRequired', template: messageTemplate.selectRequired },\n {\n type: 'filesMimes',\n template: 'The selected file must be a {{#limit}}'\n },\n {\n type: 'filesSize',\n template: 'The selected file must be smaller than 100MB'\n },\n { type: 'filesEmpty', template: 'The selected file is empty' },\n { type: 'filesVirus', template: 'The selected file contains a virus' },\n {\n type: 'filesPartial',\n template: 'The selected file has not fully uploaded'\n },\n {\n type: 'filesError',\n template: 'The selected file could not be uploaded – try again'\n }\n ],\n advancedSettingsErrors: [\n {\n type: 'filesMin',\n template: 'You must upload {{#limit}} files or more'\n },\n {\n type: 'filesMax',\n template: 'You can only upload {{#limit}} files or less'\n },\n {\n type: 'filesExact',\n template: 'You must upload exactly {{#limit}} files'\n }\n ]\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}