@defra/forms-engine-plugin 5.0.0-alpha.1 → 5.0.0-alpha.10

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 (278) hide show
  1. package/.public/javascripts/application.min.js +1 -1
  2. package/.public/javascripts/application.min.js.map +1 -1
  3. package/.public/javascripts/shared.min.js +1 -1
  4. package/.public/javascripts/shared.min.js.map +1 -1
  5. package/.public/stylesheets/application.min.css.map +1 -1
  6. package/.server/client/javascripts/file-upload.js +5 -3
  7. package/.server/client/javascripts/file-upload.js.map +1 -1
  8. package/.server/client/javascripts/geospatial-map.js +31 -26
  9. package/.server/client/javascripts/geospatial-map.js.map +1 -1
  10. package/.server/client/javascripts/location-map.js +9 -1
  11. package/.server/client/javascripts/location-map.js.map +1 -1
  12. package/.server/client/javascripts/maps.d.ts +5 -0
  13. package/.server/client/javascripts/maps.js +6 -0
  14. package/.server/client/javascripts/maps.js.map +1 -0
  15. package/.server/client/javascripts/shared.d.ts +1 -3
  16. package/.server/client/javascripts/shared.js +1 -3
  17. package/.server/client/javascripts/shared.js.map +1 -1
  18. package/.server/client/javascripts/sssi-dataset.d.ts +18 -20
  19. package/.server/client/javascripts/sssi-dataset.js +37 -39
  20. package/.server/client/javascripts/sssi-dataset.js.map +1 -1
  21. package/.server/client/stylesheets/maps.scss +4 -0
  22. package/.server/client/stylesheets/shared.scss +1 -5
  23. package/.server/server/constants.d.ts +2 -0
  24. package/.server/server/constants.js +2 -0
  25. package/.server/server/constants.js.map +1 -1
  26. package/.server/server/plugins/engine/components/AutocompleteField.d.ts +9 -3
  27. package/.server/server/plugins/engine/components/AutocompleteField.js +12 -0
  28. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
  29. package/.server/server/plugins/engine/components/CheckboxesField.d.ts +4 -1
  30. package/.server/server/plugins/engine/components/CheckboxesField.js +13 -0
  31. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
  32. package/.server/server/plugins/engine/components/ComponentBase.d.ts +1 -0
  33. package/.server/server/plugins/engine/components/ComponentBase.js +2 -0
  34. package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
  35. package/.server/server/plugins/engine/components/ComponentCollection.js +11 -6
  36. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  37. package/.server/server/plugins/engine/components/DatePartsField.d.ts +6 -3
  38. package/.server/server/plugins/engine/components/DatePartsField.js +12 -7
  39. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  40. package/.server/server/plugins/engine/components/DeclarationField.d.ts +5 -2
  41. package/.server/server/plugins/engine/components/DeclarationField.js +6 -4
  42. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  43. package/.server/server/plugins/engine/components/Details.d.ts +1 -0
  44. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +26 -2
  45. package/.server/server/plugins/engine/components/EastingNorthingField.js +93 -54
  46. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  47. package/.server/server/plugins/engine/components/EmailAddressField.d.ts +4 -1
  48. package/.server/server/plugins/engine/components/EmailAddressField.js +2 -1
  49. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -1
  50. package/.server/server/plugins/engine/components/FileUploadField.d.ts +12 -0
  51. package/.server/server/plugins/engine/components/FileUploadField.js +20 -2
  52. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
  53. package/.server/server/plugins/engine/components/FormComponent.d.ts +5 -1
  54. package/.server/server/plugins/engine/components/FormComponent.js +5 -2
  55. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  56. package/.server/server/plugins/engine/components/GeospatialField.d.ts +1 -0
  57. package/.server/server/plugins/engine/components/GeospatialField.js +1 -1
  58. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  59. package/.server/server/plugins/engine/components/Html.d.ts +1 -0
  60. package/.server/server/plugins/engine/components/InsetText.d.ts +1 -0
  61. package/.server/server/plugins/engine/components/LatLongField.d.ts +26 -2
  62. package/.server/server/plugins/engine/components/LatLongField.js +85 -48
  63. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  64. package/.server/server/plugins/engine/components/List.d.ts +1 -0
  65. package/.server/server/plugins/engine/components/ListFormComponent.d.ts +1 -0
  66. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +8 -2
  67. package/.server/server/plugins/engine/components/LocationFieldBase.js +18 -5
  68. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
  69. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +5 -2
  70. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +10 -11
  71. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  72. package/.server/server/plugins/engine/components/Markdown.d.ts +1 -0
  73. package/.server/server/plugins/engine/components/Markdown.js +1 -1
  74. package/.server/server/plugins/engine/components/Markdown.js.map +1 -1
  75. package/.server/server/plugins/engine/components/MonthYearField.d.ts +5 -2
  76. package/.server/server/plugins/engine/components/MonthYearField.js +13 -9
  77. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  78. package/.server/server/plugins/engine/components/MultilineTextField.d.ts +1 -0
  79. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +2 -1
  80. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +4 -3
  81. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -1
  82. package/.server/server/plugins/engine/components/NotificationBanner.d.ts +1 -0
  83. package/.server/server/plugins/engine/components/NumberField.d.ts +5 -0
  84. package/.server/server/plugins/engine/components/NumberField.js +16 -0
  85. package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
  86. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +2 -1
  87. package/.server/server/plugins/engine/components/OsGridRefField.js +4 -3
  88. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -1
  89. package/.server/server/plugins/engine/components/PaymentField.d.ts +3 -0
  90. package/.server/server/plugins/engine/components/PaymentField.js +17 -6
  91. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  92. package/.server/server/plugins/engine/components/SelectField.d.ts +1 -0
  93. package/.server/server/plugins/engine/components/SelectionControlField.d.ts +1 -0
  94. package/.server/server/plugins/engine/components/TelephoneNumberField.d.ts +1 -0
  95. package/.server/server/plugins/engine/components/UkAddressField.d.ts +1 -0
  96. package/.server/server/plugins/engine/components/UkAddressField.js +23 -8
  97. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  98. package/.server/server/plugins/engine/components/YesNoField.d.ts +5 -2
  99. package/.server/server/plugins/engine/components/YesNoField.js +17 -8
  100. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  101. package/.server/server/plugins/engine/components/helpers/components.js +1 -2
  102. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  103. package/.server/server/plugins/engine/components/helpers/index.d.ts +7 -0
  104. package/.server/server/plugins/engine/components/helpers/index.js +13 -1
  105. package/.server/server/plugins/engine/components/helpers/index.js.map +1 -1
  106. package/.server/server/plugins/engine/components/types.d.ts +1 -0
  107. package/.server/server/plugins/engine/components/types.js.map +1 -1
  108. package/.server/server/plugins/engine/helpers.d.ts +22 -2
  109. package/.server/server/plugins/engine/helpers.js +44 -5
  110. package/.server/server/plugins/engine/helpers.js.map +1 -1
  111. package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +3 -0
  112. package/.server/server/plugins/engine/i18n/buildValidationMessages.js +10 -7
  113. package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -1
  114. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +4 -4
  115. package/.server/server/plugins/engine/i18n/createFormTranslator.js +33 -4
  116. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -1
  117. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +1 -1
  118. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +9 -0
  119. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -1
  120. package/.server/server/plugins/engine/i18n/form.d.ts +13 -0
  121. package/.server/server/plugins/engine/i18n/form.js +35 -0
  122. package/.server/server/plugins/engine/i18n/form.js.map +1 -0
  123. package/.server/server/plugins/engine/i18n/languages.d.ts +10 -0
  124. package/.server/server/plugins/engine/i18n/languages.js +19 -0
  125. package/.server/server/plugins/engine/i18n/languages.js.map +1 -0
  126. package/.server/server/plugins/engine/i18n/translations/cy.json +73 -6
  127. package/.server/server/plugins/engine/i18n/translations/en-GB.json +43 -4
  128. package/.server/server/plugins/engine/i18n/types.d.ts +2 -0
  129. package/.server/server/plugins/engine/i18n/types.js.map +1 -1
  130. package/.server/server/plugins/engine/index.d.ts +4 -0
  131. package/.server/server/plugins/engine/index.js +4 -0
  132. package/.server/server/plugins/engine/index.js.map +1 -1
  133. package/.server/server/plugins/engine/models/FormModel.d.ts +0 -4
  134. package/.server/server/plugins/engine/models/FormModel.js +9 -15
  135. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  136. package/.server/server/plugins/engine/models/SummaryViewModel.js +9 -4
  137. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  138. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +3 -5
  139. package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
  140. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  141. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  142. package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +2 -0
  143. package/.server/server/plugins/engine/outputFormatters/machine/v2.js +2 -0
  144. package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
  145. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +1 -1
  146. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +22 -9
  147. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  148. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -1
  149. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +7 -3
  150. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  151. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +3 -4
  152. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -1
  153. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +10 -4
  154. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  155. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +1 -1
  156. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +3 -3
  157. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  158. package/.server/server/plugins/engine/pageControllers/validationOptions.js +23 -2
  159. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
  160. package/.server/server/plugins/engine/types/schema.js +1 -0
  161. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  162. package/.server/server/plugins/engine/types.d.ts +1 -0
  163. package/.server/server/plugins/engine/types.js.map +1 -1
  164. package/.server/server/plugins/engine/views/components/fileuploadfield.html +1 -1
  165. package/.server/server/plugins/engine/views/components/multilinetextfield.html +12 -1
  166. package/.server/server/plugins/engine/views/components/paymentfield.html +1 -1
  167. package/.server/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  168. package/.server/server/plugins/engine/views/partials/preview-banner.html +3 -1
  169. package/.server/server/plugins/nunjucks/filters/applyUrlParam.d.ts +9 -0
  170. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  171. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js.map +1 -0
  172. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js +17 -0
  173. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js.map +1 -0
  174. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  175. package/.server/server/plugins/nunjucks/filters/index.d.ts +1 -0
  176. package/.server/server/plugins/nunjucks/filters/index.js +1 -0
  177. package/.server/server/plugins/nunjucks/filters/index.js.map +1 -1
  178. package/.server/server/plugins/payment/helper.d.ts +11 -1
  179. package/.server/server/plugins/payment/helper.js +18 -2
  180. package/.server/server/plugins/payment/helper.js.map +1 -1
  181. package/.server/server/plugins/payment/helper.test.js +2 -1
  182. package/.server/server/plugins/payment/helper.test.js.map +1 -1
  183. package/.server/server/plugins/payment/service.d.ts +2 -1
  184. package/.server/server/plugins/payment/service.js +5 -2
  185. package/.server/server/plugins/payment/service.js.map +1 -1
  186. package/.server/server/plugins/payment/service.test.js +7 -3
  187. package/.server/server/plugins/payment/service.test.js.map +1 -1
  188. package/.server/server/plugins/payment/types.d.ts +4 -0
  189. package/.server/server/plugins/payment/types.js +1 -0
  190. package/.server/server/plugins/payment/types.js.map +1 -1
  191. package/.server/server/plugins/postcode-lookup/models/index.d.ts +249 -3
  192. package/.server/server/plugins/postcode-lookup/models/index.js +87 -33
  193. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  194. package/.server/server/plugins/postcode-lookup/routes/index.d.ts +15 -1
  195. package/.server/server/plugins/postcode-lookup/routes/index.js +47 -15
  196. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  197. package/.server/server/plugins/postcode-lookup/routes/index.test.js +84 -0
  198. package/.server/server/plugins/postcode-lookup/routes/index.test.js.map +1 -0
  199. package/.server/server/plugins/postcode-lookup/types.d.ts +12 -0
  200. package/.server/server/plugins/postcode-lookup/types.js +6 -1
  201. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  202. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  203. package/.server/server/utils/type-utils.d.ts +1 -2
  204. package/.server/server/utils/type-utils.js +0 -3
  205. package/.server/server/utils/type-utils.js.map +1 -1
  206. package/package.json +8 -2
  207. package/src/client/javascripts/file-upload.js +10 -3
  208. package/src/client/javascripts/geospatial-map.js +32 -30
  209. package/src/client/javascripts/location-map.js +7 -1
  210. package/src/client/javascripts/maps.js +5 -0
  211. package/src/client/javascripts/shared.js +1 -3
  212. package/src/client/javascripts/sssi-dataset.js +39 -41
  213. package/src/client/stylesheets/maps.scss +4 -0
  214. package/src/client/stylesheets/shared.scss +1 -5
  215. package/src/server/constants.js +2 -0
  216. package/src/server/plugins/engine/components/AutocompleteField.ts +13 -0
  217. package/src/server/plugins/engine/components/CheckboxesField.ts +13 -1
  218. package/src/server/plugins/engine/components/ComponentBase.ts +2 -0
  219. package/src/server/plugins/engine/components/ComponentCollection.ts +16 -11
  220. package/src/server/plugins/engine/components/DatePartsField.ts +20 -9
  221. package/src/server/plugins/engine/components/DeclarationField.ts +7 -6
  222. package/src/server/plugins/engine/components/EastingNorthingField.ts +154 -89
  223. package/src/server/plugins/engine/components/EmailAddressField.ts +2 -1
  224. package/src/server/plugins/engine/components/FileUploadField.ts +21 -2
  225. package/src/server/plugins/engine/components/FormComponent.ts +6 -5
  226. package/src/server/plugins/engine/components/GeospatialField.ts +6 -1
  227. package/src/server/plugins/engine/components/LatLongField.ts +128 -58
  228. package/src/server/plugins/engine/components/LocationFieldBase.ts +23 -6
  229. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +14 -11
  230. package/src/server/plugins/engine/components/Markdown.ts +2 -3
  231. package/src/server/plugins/engine/components/MonthYearField.ts +20 -15
  232. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +9 -3
  233. package/src/server/plugins/engine/components/NumberField.ts +21 -1
  234. package/src/server/plugins/engine/components/OsGridRefField.ts +9 -3
  235. package/src/server/plugins/engine/components/PaymentField.ts +15 -5
  236. package/src/server/plugins/engine/components/UkAddressField.ts +30 -7
  237. package/src/server/plugins/engine/components/YesNoField.ts +17 -9
  238. package/src/server/plugins/engine/components/helpers/components.ts +1 -2
  239. package/src/server/plugins/engine/components/helpers/index.ts +19 -0
  240. package/src/server/plugins/engine/components/types.ts +1 -0
  241. package/src/server/plugins/engine/helpers.ts +52 -5
  242. package/src/server/plugins/engine/i18n/buildValidationMessages.ts +10 -7
  243. package/src/server/plugins/engine/i18n/createFormTranslator.ts +62 -11
  244. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +7 -1
  245. package/src/server/plugins/engine/i18n/form.ts +54 -0
  246. package/src/server/plugins/engine/i18n/languages.ts +19 -0
  247. package/src/server/plugins/engine/i18n/translations/cy.json +73 -6
  248. package/src/server/plugins/engine/i18n/translations/en-GB.json +43 -4
  249. package/src/server/plugins/engine/i18n/types.ts +2 -0
  250. package/src/server/plugins/engine/index.ts +7 -0
  251. package/src/server/plugins/engine/models/FormModel.ts +9 -15
  252. package/src/server/plugins/engine/models/SummaryViewModel.ts +6 -5
  253. package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +3 -6
  254. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -1
  255. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +3 -0
  256. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +18 -8
  257. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +10 -5
  258. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +2 -2
  259. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +15 -4
  260. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +6 -3
  261. package/src/server/plugins/engine/pageControllers/validationOptions.ts +27 -2
  262. package/src/server/plugins/engine/types/schema.ts +1 -0
  263. package/src/server/plugins/engine/types.ts +1 -0
  264. package/src/server/plugins/engine/views/components/fileuploadfield.html +1 -1
  265. package/src/server/plugins/engine/views/components/multilinetextfield.html +12 -1
  266. package/src/server/plugins/engine/views/components/paymentfield.html +1 -1
  267. package/src/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  268. package/src/server/plugins/engine/views/partials/preview-banner.html +3 -1
  269. package/src/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  270. package/src/server/plugins/nunjucks/filters/index.js +1 -0
  271. package/src/server/plugins/payment/helper.js +22 -2
  272. package/src/server/plugins/payment/service.js +6 -2
  273. package/src/server/plugins/payment/types.js +1 -0
  274. package/src/server/plugins/postcode-lookup/models/index.js +75 -43
  275. package/src/server/plugins/postcode-lookup/routes/index.js +73 -16
  276. package/src/server/plugins/postcode-lookup/types.js +6 -1
  277. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  278. package/src/server/utils/type-utils.ts +1 -11
@@ -4,11 +4,9 @@ import { ComponentCollection } from "./ComponentCollection.js";
4
4
  import { FormComponent, isFormState } from "./FormComponent.js";
5
5
  import { deduplicateErrorsByHref, getLocationFieldViewModel } from "./LocationFieldHelpers.js";
6
6
  import { NumberField } from "./NumberField.js";
7
- import { createLowerFirstExpression } from "./helpers/index.js";
7
+ import { createLowerFirstExpression, getTranslatedLabel } from "./helpers/index.js";
8
8
  import { t as tPlugin } from "../i18n/index.js";
9
9
  import { messageTemplate } from "../pageControllers/validationOptions.js";
10
- import { convertToLanguageMessages } from "../../../utils/type-utils.js";
11
-
12
10
  // British National Grid coordinate limits
13
11
  const DEFAULT_EASTING_MIN = 0;
14
12
  const DEFAULT_EASTING_MAX = 700000;
@@ -23,51 +21,16 @@ export class EastingNorthingField extends FormComponent {
23
21
  schema
24
22
  } = def;
25
23
  const isRequired = options.required !== false;
26
- const eastingMin = schema?.easting?.min ?? DEFAULT_EASTING_MIN;
27
- const eastingMax = schema?.easting?.max ?? DEFAULT_EASTING_MAX;
28
- const northingMin = schema?.northing?.min ?? DEFAULT_NORTHING_MIN;
29
- const northingMax = schema?.northing?.max ?? DEFAULT_NORTHING_MAX;
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
- });
37
- const customValidationMessages = convertToLanguageMessages({
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
- }),
50
- 'number.precision': eastingDigitsMessage,
51
- 'number.integer': eastingDigitsMessage,
52
- 'number.unsafe': eastingDigitsMessage
53
- });
54
- const northingValidationMessages = convertToLanguageMessages({
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
- }),
67
- 'number.precision': northingDigitsMessage,
68
- 'number.integer': northingDigitsMessage,
69
- 'number.unsafe': northingDigitsMessage
70
- });
24
+ const {
25
+ eastingMin,
26
+ eastingMax,
27
+ northingMin,
28
+ northingMax
29
+ } = EastingNorthingField.getMinMax(schema);
30
+ const {
31
+ eastingValidationMessages,
32
+ northingValidationMessages
33
+ } = EastingNorthingField.buildErrorMessages(this.label, eastingMin, eastingMax, northingMin, northingMax, 'en-GB');
71
34
  this.collection = new ComponentCollection([{
72
35
  type: ComponentType.NumberField,
73
36
  name: `${name}__easting`,
@@ -81,7 +44,7 @@ export class EastingNorthingField extends FormComponent {
81
44
  required: isRequired,
82
45
  optionalText: true,
83
46
  classes: 'govuk-input--width-10',
84
- customValidationMessages
47
+ customValidationMessages: eastingValidationMessages
85
48
  }
86
49
  }, {
87
50
  type: ComponentType.NumberField,
@@ -112,13 +75,14 @@ export class EastingNorthingField extends FormComponent {
112
75
  const value = super.getFormValueFromState(state);
113
76
  return EastingNorthingField.isEastingNorthing(value) ? value : undefined;
114
77
  }
115
- getDisplayStringFromFormValue(value, _translator) {
78
+ getDisplayStringFromFormValue(value, translator) {
116
79
  if (!value) {
117
80
  return '';
118
81
  }
119
-
120
- // CYA page format: <<eastingvalue, northingvalue>>
121
- return `${value.easting}, ${value.northing}`;
82
+ const {
83
+ t
84
+ } = translator;
85
+ return `${t('components.eastingNorthingField.easting')}: ${value.easting}\n${t('components.eastingNorthingField.northing')}: ${value.northing}`;
122
86
  }
123
87
  getDisplayStringFromState(state, translator) {
124
88
  const value = this.getFormValueFromState(state);
@@ -128,7 +92,7 @@ export class EastingNorthingField extends FormComponent {
128
92
  if (!value) {
129
93
  return null;
130
94
  }
131
- return `Easting: ${value.easting}\nNorthing: ${value.northing}`;
95
+ return `${value.easting}, ${value.northing}`;
132
96
  }
133
97
  getContextValueFromState(state) {
134
98
  const value = this.getFormValueFromState(state);
@@ -145,6 +109,24 @@ export class EastingNorthingField extends FormComponent {
145
109
  isState(value) {
146
110
  return EastingNorthingField.isEastingNorthing(value);
147
111
  }
112
+ getValidationMessagesOverride(translator) {
113
+ const def = this.def;
114
+ const translatedLabel = getTranslatedLabel(def, translator);
115
+ const {
116
+ eastingMin,
117
+ eastingMax,
118
+ northingMin,
119
+ northingMax
120
+ } = EastingNorthingField.getMinMax(def.schema);
121
+ const {
122
+ eastingValidationMessages,
123
+ northingValidationMessages
124
+ } = EastingNorthingField.buildErrorMessages(translatedLabel, eastingMin, eastingMax, northingMin, northingMax, translator.language);
125
+ return {
126
+ [`${this.name}__easting`]: eastingValidationMessages,
127
+ [`${this.name}__northing`]: northingValidationMessages
128
+ };
129
+ }
148
130
 
149
131
  /**
150
132
  * For error preview page that shows all possible errors on a component
@@ -186,5 +168,62 @@ export class EastingNorthingField extends FormComponent {
186
168
  static isEastingNorthing(value) {
187
169
  return isFormState(value) && NumberField.isNumber(value.easting) && NumberField.isNumber(value.northing);
188
170
  }
171
+ static buildErrorMessages(label, eastingMin, eastingMax, northingMin, northingMax, language) {
172
+ const fieldLabel = lowerFirst(label);
173
+ const eastingDigitsMessage = tPlugin('components.eastingNorthingField.eastingDigits', language, {
174
+ fieldLabel
175
+ });
176
+ const northingDigitsMessage = tPlugin('components.eastingNorthingField.northingDigits', language, {
177
+ fieldLabel
178
+ });
179
+ const eastingValidationMessages = {
180
+ 'any.required': tPlugin('components.eastingNorthingField.eastingRequired', language),
181
+ 'number.base': tPlugin('components.eastingNorthingField.eastingRequired', language),
182
+ 'number.min': tPlugin('components.eastingNorthingField.eastingRange', language, {
183
+ fieldLabel,
184
+ min: eastingMin,
185
+ max: eastingMax
186
+ }),
187
+ 'number.max': tPlugin('components.eastingNorthingField.eastingRange', language, {
188
+ fieldLabel,
189
+ min: eastingMin,
190
+ max: eastingMax
191
+ }),
192
+ 'number.precision': eastingDigitsMessage,
193
+ 'number.integer': eastingDigitsMessage,
194
+ 'number.unsafe': eastingDigitsMessage
195
+ };
196
+ const northingValidationMessages = {
197
+ 'any.required': tPlugin('components.eastingNorthingField.northingRequired', language),
198
+ 'number.base': tPlugin('components.eastingNorthingField.northingRequired', language),
199
+ 'number.min': tPlugin('components.eastingNorthingField.northingRange', language, {
200
+ fieldLabel,
201
+ min: northingMin,
202
+ max: northingMax
203
+ }),
204
+ 'number.max': tPlugin('components.eastingNorthingField.northingRange', language, {
205
+ fieldLabel,
206
+ min: northingMin,
207
+ max: northingMax
208
+ }),
209
+ 'number.precision': northingDigitsMessage,
210
+ 'number.integer': northingDigitsMessage,
211
+ 'number.unsafe': northingDigitsMessage
212
+ };
213
+ return {
214
+ eastingValidationMessages,
215
+ northingValidationMessages
216
+ };
217
+ }
218
+
219
+ // Read schema values from def.schema with fallback defaults
220
+ static getMinMax(schema) {
221
+ return {
222
+ eastingMin: schema?.easting?.min ?? DEFAULT_EASTING_MIN,
223
+ eastingMax: schema?.easting?.max ?? DEFAULT_EASTING_MAX,
224
+ northingMin: schema?.northing?.min ?? DEFAULT_NORTHING_MIN,
225
+ northingMax: schema?.northing?.max ?? DEFAULT_NORTHING_MAX
226
+ };
227
+ }
189
228
  }
190
229
  //# sourceMappingURL=EastingNorthingField.js.map
@@ -1 +1 @@
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
+ {"version":3,"file":"EastingNorthingField.js","names":["ComponentType","lowerFirst","ComponentCollection","FormComponent","isFormState","deduplicateErrorsByHref","getLocationFieldViewModel","NumberField","createLowerFirstExpression","getTranslatedLabel","t","tPlugin","messageTemplate","DEFAULT_EASTING_MIN","DEFAULT_EASTING_MAX","DEFAULT_NORTHING_MIN","DEFAULT_NORTHING_MAX","EastingNorthingField","constructor","def","props","name","options","schema","isRequired","required","eastingMin","eastingMax","northingMin","northingMax","getMinMax","eastingValidationMessages","northingValidationMessages","buildErrorMessages","label","collection","type","title","min","max","precision","optionalText","classes","customValidationMessages","parent","peers","formSchema","stateSchema","getFormValueFromState","state","value","isEastingNorthing","undefined","getDisplayStringFromFormValue","translator","easting","northing","getDisplayStringFromState","getContextValueFromFormValue","getContextValueFromState","getViewModel","context","viewModel","getViewErrors","errors","allErrors","getErrors","isState","getValidationMessagesOverride","translatedLabel","language","getAllPossibleErrors","baseErrors","template","advancedSettingsErrors","isNumber","fieldLabel","eastingDigitsMessage","northingDigitsMessage"],"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 {\n createLowerFirstExpression,\n getTranslatedLabel\n} 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'\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, eastingMax, northingMin, northingMax } =\n EastingNorthingField.getMinMax(schema)\n\n const { eastingValidationMessages, northingValidationMessages } =\n EastingNorthingField.buildErrorMessages(\n this.label,\n eastingMin,\n eastingMax,\n northingMin,\n northingMax,\n 'en-GB'\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: eastingValidationMessages\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 const { t } = translator\n\n return `${t('components.eastingNorthingField.easting')}: ${value.easting}\\n${t('components.eastingNorthingField.northing')}: ${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 `${value.easting}, ${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 getValidationMessagesOverride(translator: Translator) {\n const def = this.def as EastingNorthingFieldComponent\n const translatedLabel = getTranslatedLabel(def, translator)\n const { eastingMin, eastingMax, northingMin, northingMax } =\n EastingNorthingField.getMinMax(def.schema)\n const { eastingValidationMessages, northingValidationMessages } =\n EastingNorthingField.buildErrorMessages(\n translatedLabel,\n eastingMin,\n eastingMax,\n northingMin,\n northingMax,\n translator.language\n )\n return {\n [`${this.name}__easting`]: eastingValidationMessages,\n [`${this.name}__northing`]: northingValidationMessages\n }\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 static buildErrorMessages(\n label: string,\n eastingMin: number,\n eastingMax: number,\n northingMin: number,\n northingMax: number,\n language: string\n ) {\n const fieldLabel = lowerFirst(label)\n\n const eastingDigitsMessage = tPlugin(\n 'components.eastingNorthingField.eastingDigits',\n language,\n { fieldLabel }\n )\n const northingDigitsMessage = tPlugin(\n 'components.eastingNorthingField.northingDigits',\n language,\n { fieldLabel }\n )\n\n const eastingValidationMessages: LanguageMessages = {\n 'any.required': tPlugin(\n 'components.eastingNorthingField.eastingRequired',\n language\n ),\n 'number.base': tPlugin(\n 'components.eastingNorthingField.eastingRequired',\n language\n ),\n 'number.min': tPlugin(\n 'components.eastingNorthingField.eastingRange',\n language,\n {\n fieldLabel,\n min: eastingMin,\n max: eastingMax\n }\n ),\n 'number.max': tPlugin(\n 'components.eastingNorthingField.eastingRange',\n language,\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 'any.required': tPlugin(\n 'components.eastingNorthingField.northingRequired',\n language\n ),\n 'number.base': tPlugin(\n 'components.eastingNorthingField.northingRequired',\n language\n ),\n 'number.min': tPlugin(\n 'components.eastingNorthingField.northingRange',\n language,\n {\n fieldLabel,\n min: northingMin,\n max: northingMax\n }\n ),\n 'number.max': tPlugin(\n 'components.eastingNorthingField.northingRange',\n language,\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 return {\n eastingValidationMessages,\n northingValidationMessages\n }\n }\n\n // Read schema values from def.schema with fallback defaults\n static getMinMax(\n schema:\n | {\n easting?: {\n min?: number\n max?: number\n }\n northing?: {\n min?: number\n max?: number\n }\n }\n | undefined\n ) {\n return {\n eastingMin: schema?.easting?.min ?? DEFAULT_EASTING_MIN,\n eastingMax: schema?.easting?.max ?? DEFAULT_EASTING_MAX,\n northingMin: schema?.northing?.min ?? DEFAULT_NORTHING_MIN,\n northingMax: schema?.northing?.max ?? DEFAULT_NORTHING_MAX\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -30,7 +30,9 @@ export declare class EmailAddressField extends FormComponent {
30
30
  attributes: {
31
31
  autocomplete?: string;
32
32
  maxlength?: number;
33
- multiple?: string;
33
+ multiple? /**
34
+ * Static version of getAllPossibleErrors that doesn't require a component instance.
35
+ */: string;
34
36
  accept?: string;
35
37
  inputmode?: string;
36
38
  };
@@ -52,6 +54,7 @@ export declare class EmailAddressField extends FormComponent {
52
54
  upload?: {
53
55
  count: number;
54
56
  summaryList: import("../../../../server/plugins/engine/types.js").SummaryList;
57
+ uploadingLabel?: string;
55
58
  };
56
59
  };
57
60
  /**
@@ -17,7 +17,8 @@ export class EmailAddressField extends FormComponent {
17
17
  formSchema = formSchema.messages({
18
18
  'any.required': message,
19
19
  'string.empty': message,
20
- 'string.email': message
20
+ 'string.email': message,
21
+ 'string.unicode': message
21
22
  });
22
23
  } else if (options.customValidationMessages) {
23
24
  formSchema = formSchema.messages(options.customValidationMessages);
@@ -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","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
+ {"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 'string.unicode': 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,OAAO;QACvB,gBAAgB,EAAEA;MACpB,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":[]}
@@ -78,6 +78,13 @@ export declare class FileUploadField extends FormComponent {
78
78
  components?: import("../../../../server/plugins/engine/components/types.js").ComponentViewModel[];
79
79
  };
80
80
  isValue(value?: FormStateValue | FormState): value is UploadState;
81
+ getValidationMessagesOverride(translator: Translator): {
82
+ [x: string]: {
83
+ 'array.min': string;
84
+ 'array.max': string;
85
+ 'array.length': string;
86
+ };
87
+ };
81
88
  /**
82
89
  * For error preview page that shows all possible errors on a component
83
90
  */
@@ -87,4 +94,9 @@ export declare class FileUploadField extends FormComponent {
87
94
  * Static version of getAllPossibleErrors that doesn't require a component instance.
88
95
  */
89
96
  static getAllPossibleErrors(): ErrorMessageTemplateList;
97
+ static buildErrorMessages(language: string): {
98
+ 'array.min': string;
99
+ 'array.max': string;
100
+ 'array.length': string;
101
+ };
90
102
  }
@@ -1,6 +1,8 @@
1
1
  import Boom from '@hapi/boom';
2
2
  import joi from 'joi';
3
+ import { EN_GB } from "../../../constants.js";
3
4
  import { FormComponent, isUploadState } from "./FormComponent.js";
5
+ import { t as tPlugin } from "../i18n/index.js";
4
6
  import { InvalidComponentStateError } from "../pageControllers/errors.js";
5
7
  import { messageTemplate } from "../pageControllers/validationOptions.js";
6
8
  import { FileStatus, UploadStatus } from "../types.js";
@@ -70,6 +72,7 @@ export class FileUploadField extends FormComponent {
70
72
  } else {
71
73
  formSchema = formSchema.length(schema.length);
72
74
  }
75
+ formSchema = formSchema.messages(FileUploadField.buildErrorMessages(EN_GB));
73
76
  this.formSchema = formSchema.items(formItemSchema);
74
77
  this.stateSchema = formSchema.items(formItemSchema).default(null).allow(null);
75
78
  this.options = options;
@@ -88,7 +91,7 @@ export class FileUploadField extends FormComponent {
88
91
  if (!files?.length) {
89
92
  return '';
90
93
  }
91
- return translator.t('components.fileUploadField.filesCount', {
94
+ return translator.t('pages.summary.fileUpload', {
92
95
  count: files.length
93
96
  });
94
97
  }
@@ -164,7 +167,7 @@ export class FileUploadField extends FormComponent {
164
167
  const href = page?.getHref(`${page.path}${path}`) ?? '#';
165
168
  items.push({
166
169
  href,
167
- text: 'Remove',
170
+ text: t('pages.fileUpload.remove'),
168
171
  classes: 'govuk-link--no-visited-state',
169
172
  attributes: {
170
173
  id: `${id}__${index}`
@@ -215,6 +218,14 @@ export class FileUploadField extends FormComponent {
215
218
  isValue(value) {
216
219
  return isUploadState(value);
217
220
  }
221
+ getValidationMessagesOverride(translator) {
222
+ const {
223
+ language
224
+ } = translator;
225
+ return {
226
+ [this.name]: FileUploadField.buildErrorMessages(language)
227
+ };
228
+ }
218
229
 
219
230
  /**
220
231
  * For error preview page that shows all possible errors on a component
@@ -304,5 +315,12 @@ export class FileUploadField extends FormComponent {
304
315
  }]
305
316
  };
306
317
  }
318
+ static buildErrorMessages(language) {
319
+ return {
320
+ 'array.min': tPlugin('validation.filesMin', language),
321
+ 'array.max': tPlugin('validation.filesMax', language),
322
+ 'array.length': tPlugin('validation.filesLength', language)
323
+ };
324
+ }
307
325
  }
308
326
  //# sourceMappingURL=FileUploadField.js.map
@@ -1 +1 @@
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":[]}
1
+ {"version":3,"file":"FileUploadField.js","names":["Boom","joi","EN_GB","FormComponent","isUploadState","t","tPlugin","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","messages","buildErrorMessages","stateSchema","default","allow","getFormValueFromState","state","name","getFormValue","value","isValue","undefined","getDisplayStringFromFormValue","files","translator","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","getValidationMessagesOverride","language","getAllPossibleErrors","onSubmit","request","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 { EN_GB } from '~/src/server/constants.js'\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 { t as tPlugin } from '~/src/server/plugins/engine/i18n/index.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 formSchema = formSchema.messages(FileUploadField.buildErrorMessages(EN_GB))\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('pages.summary.fileUpload', {\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: t('pages.fileUpload.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 getValidationMessagesOverride(translator: Translator) {\n const { language } = translator\n return {\n [this.name]: FileUploadField.buildErrorMessages(language)\n }\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 static buildErrorMessages(language: string) {\n return {\n 'array.min': tPlugin('validation.filesMin', language),\n 'array.max': tPlugin('validation.filesMax', language),\n 'array.length': tPlugin('validation.filesLength', language)\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -27,8 +27,11 @@ export declare class FormComponent extends ComponentBase {
27
27
  * Override in composite fields to return translated Joi message overrides for
28
28
  * their sub-fields, applied at validation time so schema-level English messages
29
29
  * are replaced with the correct language. Return null to skip message patching.
30
+ * The return object may contain message overrides at component-level, or sub-field-level.
31
+ * This would allow different error message overrides per field within a collection e.g.
32
+ * for EastingNothingField
30
33
  */
31
- getValidationMessagesOverride(_translator: Translator): LanguageMessages | null;
34
+ getValidationMessagesOverride(_translator: Translator): Record<string, LanguageMessages> | null;
32
35
  getViewModel({ payload, errors, translator, isForceAccess: _isForceAccess }: RenderContext): {
33
36
  label: {
34
37
  text: string;
@@ -76,6 +79,7 @@ export declare class FormComponent extends ComponentBase {
76
79
  upload?: {
77
80
  count: number;
78
81
  summaryList: import("../../../../server/plugins/engine/types.js").SummaryList;
82
+ uploadingLabel?: string;
79
83
  };
80
84
  };
81
85
  getDisplayStringFromFormValue(value: FormValue | FormPayload, _translator: Translator): string;
@@ -105,6 +105,9 @@ export class FormComponent extends ComponentBase {
105
105
  * Override in composite fields to return translated Joi message overrides for
106
106
  * their sub-fields, applied at validation time so schema-level English messages
107
107
  * are replaced with the correct language. Return null to skip message patching.
108
+ * The return object may contain message overrides at component-level, or sub-field-level.
109
+ * This would allow different error message overrides per field within a collection e.g.
110
+ * for EastingNothingField
108
111
  */
109
112
  getValidationMessagesOverride(_translator) {
110
113
  return null;
@@ -128,12 +131,12 @@ export class FormComponent extends ComponentBase {
128
131
  } = translator;
129
132
  const isRequired = !('required' in options) || options.required !== false;
130
133
  const hideOptional = 'optionalText' in options && options.optionalText;
131
- const resolvedTitle = tComponent(this, 'title') || title;
134
+ const resolvedTitle = tComponent(this.def, 'title') || title;
132
135
  const optionalTag = !isRequired && !hideOptional ? ` ${t('common.optional')}` : '';
133
136
  const label = `${resolvedTitle}${optionalTag}`;
134
137
  if (hint) {
135
138
  viewModel.hint = {
136
- text: tComponent(this, 'hint') || hint
139
+ text: tComponent(this.def, 'hint') || hint
137
140
  };
138
141
  }
139
142