@defra/forms-engine-plugin 4.0.5 → 4.0.7

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 (83) hide show
  1. package/.public/stylesheets/application.min.css +2 -2
  2. package/.public/stylesheets/application.min.css.map +1 -1
  3. package/.server/client/stylesheets/_location-input.scss +60 -0
  4. package/.server/client/stylesheets/application.scss +1 -6
  5. package/.server/client/stylesheets/shared.scss +8 -0
  6. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +28 -0
  7. package/.server/server/plugins/engine/components/ComponentBase.d.ts +1 -1
  8. package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
  9. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +121 -0
  10. package/.server/server/plugins/engine/components/EastingNorthingField.js +166 -0
  11. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -0
  12. package/.server/server/plugins/engine/components/LatLongField.d.ts +121 -0
  13. package/.server/server/plugins/engine/components/LatLongField.js +164 -0
  14. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -0
  15. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +134 -0
  16. package/.server/server/plugins/engine/components/LocationFieldBase.js +85 -0
  17. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -0
  18. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +108 -0
  19. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +96 -0
  20. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -0
  21. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +19 -0
  22. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +40 -0
  23. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -0
  24. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +19 -0
  25. package/.server/server/plugins/engine/components/OsGridRefField.js +56 -0
  26. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -0
  27. package/.server/server/plugins/engine/components/helpers/components.d.ts +3 -4
  28. package/.server/server/plugins/engine/components/helpers/components.js +21 -29
  29. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  30. package/.server/server/plugins/engine/components/index.d.ts +4 -0
  31. package/.server/server/plugins/engine/components/index.js +4 -0
  32. package/.server/server/plugins/engine/components/index.js.map +1 -1
  33. package/.server/server/plugins/engine/components/markdownParser.d.ts +2 -0
  34. package/.server/server/plugins/engine/components/markdownParser.js +28 -0
  35. package/.server/server/plugins/engine/components/markdownParser.js.map +1 -0
  36. package/.server/server/plugins/engine/components/types.d.ts +10 -0
  37. package/.server/server/plugins/engine/components/types.js.map +1 -1
  38. package/.server/server/plugins/engine/pageControllers/helpers/pages.js +7 -0
  39. package/.server/server/plugins/engine/pageControllers/helpers/pages.js.map +1 -1
  40. package/.server/server/plugins/engine/types/index.d.ts +1 -1
  41. package/.server/server/plugins/engine/types/index.js.map +1 -1
  42. package/.server/server/plugins/engine/types.d.ts +2 -2
  43. package/.server/server/plugins/engine/types.js.map +1 -1
  44. package/.server/server/plugins/engine/views/components/_location-field-base.html +53 -0
  45. package/.server/server/plugins/engine/views/components/eastingnorthingfield.html +5 -0
  46. package/.server/server/plugins/engine/views/components/latlongfield.html +5 -0
  47. package/.server/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +13 -0
  48. package/.server/server/plugins/engine/views/components/osgridreffield.html +13 -0
  49. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  50. package/package.json +3 -3
  51. package/src/client/stylesheets/_location-input.scss +60 -0
  52. package/src/client/stylesheets/application.scss +1 -6
  53. package/src/client/stylesheets/shared.scss +8 -0
  54. package/src/server/forms/register-as-a-unicorn-breeder.yaml +28 -0
  55. package/src/server/plugins/engine/components/ComponentBase.ts +1 -1
  56. package/src/server/plugins/engine/components/EastingNorthingField.test.ts +665 -0
  57. package/src/server/plugins/engine/components/EastingNorthingField.ts +224 -0
  58. package/src/server/plugins/engine/components/LatLongField.test.ts +700 -0
  59. package/src/server/plugins/engine/components/LatLongField.ts +213 -0
  60. package/src/server/plugins/engine/components/LocationFieldBase.test.ts +253 -0
  61. package/src/server/plugins/engine/components/LocationFieldBase.ts +152 -0
  62. package/src/server/plugins/engine/components/LocationFieldHelpers.test.ts +338 -0
  63. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +123 -0
  64. package/src/server/plugins/engine/components/NationalGridFieldNumberField.test.ts +438 -0
  65. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +52 -0
  66. package/src/server/plugins/engine/components/OsGridRefField.test.ts +469 -0
  67. package/src/server/plugins/engine/components/OsGridRefField.ts +71 -0
  68. package/src/server/plugins/engine/components/helpers/components.test.ts +270 -0
  69. package/src/server/plugins/engine/components/helpers/components.ts +39 -47
  70. package/src/server/plugins/engine/components/helpers/helpers.test.ts +71 -1
  71. package/src/server/plugins/engine/components/index.ts +4 -0
  72. package/src/server/plugins/engine/components/markdownParser.ts +40 -0
  73. package/src/server/plugins/engine/components/types.ts +14 -0
  74. package/src/server/plugins/engine/outputFormatters/adapter/v1.location.test.ts +356 -0
  75. package/src/server/plugins/engine/pageControllers/helpers/helpers.test.ts +4 -0
  76. package/src/server/plugins/engine/pageControllers/helpers/pages.ts +8 -0
  77. package/src/server/plugins/engine/types/index.ts +2 -0
  78. package/src/server/plugins/engine/types.ts +4 -0
  79. package/src/server/plugins/engine/views/components/_location-field-base.html +53 -0
  80. package/src/server/plugins/engine/views/components/eastingnorthingfield.html +5 -0
  81. package/src/server/plugins/engine/views/components/latlongfield.html +5 -0
  82. package/src/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +13 -0
  83. package/src/server/plugins/engine/views/components/osgridreffield.html +13 -0
@@ -0,0 +1,224 @@
1
+ import {
2
+ ComponentType,
3
+ type EastingNorthingFieldComponent
4
+ } from '@defra/forms-model'
5
+ import { type LanguageMessages, type ObjectSchema } from 'joi'
6
+
7
+ import { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'
8
+ import {
9
+ FormComponent,
10
+ isFormState
11
+ } from '~/src/server/plugins/engine/components/FormComponent.js'
12
+ import {
13
+ createLocationFieldValidator,
14
+ getLocationFieldViewModel
15
+ } from '~/src/server/plugins/engine/components/LocationFieldHelpers.js'
16
+ import { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'
17
+ import { type EastingNorthingState } from '~/src/server/plugins/engine/components/types.js'
18
+ import { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'
19
+ import {
20
+ type ErrorMessageTemplateList,
21
+ type FormPayload,
22
+ type FormState,
23
+ type FormStateValue,
24
+ type FormSubmissionError,
25
+ type FormSubmissionState
26
+ } from '~/src/server/plugins/engine/types.js'
27
+ import { convertToLanguageMessages } from '~/src/server/utils/type-utils.js'
28
+
29
+ // British National Grid coordinate limits
30
+ const DEFAULT_EASTING_MIN = 0
31
+ const DEFAULT_EASTING_MAX = 70000
32
+ const DEFAULT_NORTHING_MIN = 0
33
+ const DEFAULT_NORTHING_MAX = 1300000
34
+
35
+ export class EastingNorthingField extends FormComponent {
36
+ declare options: EastingNorthingFieldComponent['options']
37
+ declare formSchema: ObjectSchema<FormPayload>
38
+ declare stateSchema: ObjectSchema<FormState>
39
+ declare collection: ComponentCollection
40
+
41
+ constructor(
42
+ def: EastingNorthingFieldComponent,
43
+ props: ConstructorParameters<typeof FormComponent>[1]
44
+ ) {
45
+ super(def, props)
46
+
47
+ const { name, options, schema } = def
48
+
49
+ const isRequired = options.required !== false
50
+
51
+ const eastingMin = schema?.easting?.min ?? DEFAULT_EASTING_MIN
52
+ const eastingMax = schema?.easting?.max ?? DEFAULT_EASTING_MAX
53
+ const northingMin = schema?.northing?.min ?? DEFAULT_NORTHING_MIN
54
+ const northingMax = schema?.northing?.max ?? DEFAULT_NORTHING_MAX
55
+
56
+ const customValidationMessages: LanguageMessages =
57
+ convertToLanguageMessages({
58
+ 'any.required': messageTemplate.objectMissing,
59
+ 'number.base': messageTemplate.objectMissing,
60
+ 'number.min': `{{#label}} for ${this.title} must be between {{#limit}} and ${eastingMax}`,
61
+ 'number.max': `{{#label}} for ${this.title} must be between ${eastingMin} and {{#limit}}`,
62
+ 'number.precision': `{{#label}} for ${this.title} must be between 1 and 5 digits`,
63
+ 'number.integer': `{{#label}} for ${this.title} must be between 1 and 5 digits`,
64
+ 'number.unsafe': `{{#label}} for ${this.title} must be between 1 and 5 digits`
65
+ })
66
+
67
+ const northingValidationMessages: LanguageMessages =
68
+ convertToLanguageMessages({
69
+ 'any.required': messageTemplate.objectMissing,
70
+ 'number.base': messageTemplate.objectMissing,
71
+ 'number.min': `{{#label}} for ${this.title} must be between {{#limit}} and ${northingMax}`,
72
+ 'number.max': `{{#label}} for ${this.title} must be between ${northingMin} and {{#limit}}`,
73
+ 'number.precision': `{{#label}} for ${this.title} must be between 1 and 7 digits`,
74
+ 'number.integer': `{{#label}} for ${this.title} must be between 1 and 7 digits`,
75
+ 'number.unsafe': `{{#label}} for ${this.title} must be between 1 and 7 digits`
76
+ })
77
+
78
+ this.collection = new ComponentCollection(
79
+ [
80
+ {
81
+ type: ComponentType.NumberField,
82
+ name: `${name}__easting`,
83
+ title: 'Easting',
84
+ schema: { min: eastingMin, max: eastingMax, precision: 0 },
85
+ options: {
86
+ required: isRequired,
87
+ optionalText: true,
88
+ classes: 'govuk-input--width-10',
89
+ customValidationMessages
90
+ }
91
+ },
92
+ {
93
+ type: ComponentType.NumberField,
94
+ name: `${name}__northing`,
95
+ title: 'Northing',
96
+ schema: { min: northingMin, max: northingMax, precision: 0 },
97
+ options: {
98
+ required: isRequired,
99
+ optionalText: true,
100
+ classes: 'govuk-input--width-10',
101
+ customValidationMessages: northingValidationMessages
102
+ }
103
+ }
104
+ ],
105
+ { ...props, parent: this },
106
+ {
107
+ custom: getValidatorEastingNorthing(this),
108
+ peers: [`${name}__easting`, `${name}__northing`]
109
+ }
110
+ )
111
+
112
+ this.options = options
113
+ this.formSchema = this.collection.formSchema
114
+ this.stateSchema = this.collection.stateSchema
115
+ }
116
+
117
+ getFormValueFromState(state: FormSubmissionState) {
118
+ const value = super.getFormValueFromState(state)
119
+ return EastingNorthingField.isEastingNorthing(value) ? value : undefined
120
+ }
121
+
122
+ getDisplayStringFromFormValue(
123
+ value: EastingNorthingState | undefined
124
+ ): string {
125
+ if (!value) {
126
+ return ''
127
+ }
128
+
129
+ // CYA page format: <<northingvalue, eastingvalue>>
130
+ return `${value.northing}, ${value.easting}`
131
+ }
132
+
133
+ getDisplayStringFromState(state: FormSubmissionState) {
134
+ const value = this.getFormValueFromState(state)
135
+
136
+ return this.getDisplayStringFromFormValue(value)
137
+ }
138
+
139
+ getContextValueFromFormValue(
140
+ value: EastingNorthingState | undefined
141
+ ): string | null {
142
+ if (!value) {
143
+ return null
144
+ }
145
+
146
+ // Output format: Northing: <<entry>>\nEasting: <<entry>>
147
+ return `Northing: ${value.northing}\nEasting: ${value.easting}`
148
+ }
149
+
150
+ getContextValueFromState(state: FormSubmissionState) {
151
+ const value = this.getFormValueFromState(state)
152
+
153
+ return this.getContextValueFromFormValue(value)
154
+ }
155
+
156
+ getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
157
+ const viewModel = super.getViewModel(payload, errors)
158
+ return getLocationFieldViewModel(this, viewModel, payload, errors)
159
+ }
160
+
161
+ isState(value?: FormStateValue | FormState) {
162
+ return EastingNorthingField.isEastingNorthing(value)
163
+ }
164
+
165
+ /**
166
+ * For error preview page that shows all possible errors on a component
167
+ */
168
+ getAllPossibleErrors(): ErrorMessageTemplateList {
169
+ return EastingNorthingField.getAllPossibleErrors()
170
+ }
171
+
172
+ /**
173
+ * Static version of getAllPossibleErrors that doesn't require a component instance.
174
+ */
175
+ static getAllPossibleErrors(): ErrorMessageTemplateList {
176
+ return {
177
+ baseErrors: [
178
+ { type: 'required', template: messageTemplate.required },
179
+ {
180
+ type: 'eastingFormat',
181
+ template:
182
+ 'Easting for [short description] must be between 1 and 5 digits'
183
+ },
184
+ {
185
+ type: 'northingFormat',
186
+ template:
187
+ 'Northing for [short description] must be between 1 and 7 digits'
188
+ }
189
+ ],
190
+ advancedSettingsErrors: [
191
+ {
192
+ type: 'eastingMin',
193
+ template: `Easting for [short description] must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`
194
+ },
195
+ {
196
+ type: 'eastingMax',
197
+ template: `Easting for [short description] must be between ${DEFAULT_EASTING_MIN} and ${DEFAULT_EASTING_MAX}`
198
+ },
199
+ {
200
+ type: 'northingMin',
201
+ template: `Northing for [short description] must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`
202
+ },
203
+ {
204
+ type: 'northingMax',
205
+ template: `Northing for [short description] must be between ${DEFAULT_NORTHING_MIN} and ${DEFAULT_NORTHING_MAX}`
206
+ }
207
+ ]
208
+ }
209
+ }
210
+
211
+ static isEastingNorthing(
212
+ value?: FormStateValue | FormState
213
+ ): value is EastingNorthingState {
214
+ return (
215
+ isFormState(value) &&
216
+ NumberField.isNumber(value.easting) &&
217
+ NumberField.isNumber(value.northing)
218
+ )
219
+ }
220
+ }
221
+
222
+ export function getValidatorEastingNorthing(component: EastingNorthingField) {
223
+ return createLocationFieldValidator(component)
224
+ }