@defra/forms-engine-plugin 5.0.0-alpha.11 → 5.0.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.server/server/plugins/engine/components/CheckboxesField.d.ts +20 -2
- package/.server/server/plugins/engine/components/CheckboxesField.js +24 -12
- package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
- package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +2 -0
- package/.server/server/plugins/engine/components/EastingNorthingField.js +1 -1
- package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
- package/.server/server/plugins/engine/components/FileUploadField.d.ts +10 -1
- package/.server/server/plugins/engine/components/FileUploadField.js +18 -6
- package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
- package/.server/server/plugins/engine/components/GeospatialField.d.ts +21 -0
- package/.server/server/plugins/engine/components/GeospatialField.js +32 -9
- package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
- package/.server/server/plugins/engine/components/LatLongField.d.ts +2 -0
- package/.server/server/plugins/engine/components/LocationFieldBase.js +4 -1
- package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
- package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +2 -0
- package/.server/server/plugins/engine/components/LocationFieldHelpers.js +7 -1
- package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +5 -0
- package/.server/server/plugins/engine/components/helpers/geospatial.js +25 -16
- package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -1
- package/.server/server/plugins/engine/form-availability.d.ts +3 -2
- package/.server/server/plugins/engine/form-availability.js +3 -2
- package/.server/server/plugins/engine/form-availability.js.map +1 -1
- package/.server/server/plugins/engine/form-context.js +2 -2
- package/.server/server/plugins/engine/form-context.js.map +1 -1
- package/.server/server/plugins/engine/i18n/buildValidationMessages.d.ts +1 -1
- package/.server/server/plugins/engine/i18n/buildValidationMessages.js +30 -9
- package/.server/server/plugins/engine/i18n/buildValidationMessages.js.map +1 -1
- package/.server/server/plugins/engine/i18n/translations/cy.json +66 -10
- package/.server/server/plugins/engine/i18n/translations/en-GB.json +29 -10
- package/.server/server/plugins/engine/i18n/types.d.ts +1 -0
- package/.server/server/plugins/engine/i18n/types.js.map +1 -1
- package/.server/server/plugins/engine/models/unavailable-view-model.d.ts +11 -2
- package/.server/server/plugins/engine/models/unavailable-view-model.js +23 -4
- package/.server/server/plugins/engine/models/unavailable-view-model.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.js +1 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
- package/.server/server/plugins/engine/unavailable-response.js +5 -2
- package/.server/server/plugins/engine/unavailable-response.js.map +1 -1
- package/.server/server/plugins/engine/views/components/_location-field-base.html +1 -1
- package/.server/server/plugins/engine/views/unavailable.html +14 -11
- package/package.json +1 -1
- package/src/server/plugins/engine/components/CheckboxesField.ts +34 -13
- package/src/server/plugins/engine/components/EastingNorthingField.ts +1 -1
- package/src/server/plugins/engine/components/FileUploadField.ts +26 -6
- package/src/server/plugins/engine/components/GeospatialField.ts +43 -11
- package/src/server/plugins/engine/components/LocationFieldBase.ts +3 -1
- package/src/server/plugins/engine/components/LocationFieldHelpers.ts +7 -1
- package/src/server/plugins/engine/components/helpers/geospatial.ts +32 -22
- package/src/server/plugins/engine/form-availability.ts +8 -2
- package/src/server/plugins/engine/form-context.ts +4 -2
- package/src/server/plugins/engine/i18n/buildValidationMessages.ts +15 -10
- package/src/server/plugins/engine/i18n/translations/cy.json +66 -10
- package/src/server/plugins/engine/i18n/translations/en-GB.json +29 -10
- package/src/server/plugins/engine/i18n/types.ts +1 -0
- package/src/server/plugins/engine/models/unavailable-view-model.ts +26 -5
- package/src/server/plugins/engine/pageControllers/validationOptions.ts +2 -2
- package/src/server/plugins/engine/unavailable-response.ts +6 -2
- package/src/server/plugins/engine/views/components/_location-field-base.html +1 -1
- package/src/server/plugins/engine/views/unavailable.html +14 -11
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type CheckboxesFieldComponent, type Item } from '@defra/forms-model'
|
|
2
|
-
import joi, { type ArraySchema
|
|
2
|
+
import joi, { type ArraySchema } from 'joi'
|
|
3
3
|
|
|
4
|
+
import { EN_GB } from '../../../constants.js'
|
|
4
5
|
import { isFormValue } from './FormComponent.js'
|
|
5
6
|
import { SelectionControlField } from './SelectionControlField.js'
|
|
6
|
-
import {
|
|
7
|
+
import { t as tPlugin } from '../i18n/index.js'
|
|
7
8
|
import { type Translator } from '../i18n/types.js'
|
|
8
9
|
import { type FormModel } from '../models/FormModel.js'
|
|
9
10
|
import { type QuestionPageController } from '../pageControllers/QuestionPageController.js'
|
|
@@ -20,6 +21,7 @@ export class CheckboxesField extends SelectionControlField {
|
|
|
20
21
|
declare schema: CheckboxesFieldComponent['schema']
|
|
21
22
|
declare formSchema: ArraySchema<string> | ArraySchema<number>
|
|
22
23
|
declare stateSchema: ArraySchema<string> | ArraySchema<number>
|
|
24
|
+
declare limits: { min?: number; max?: number; length?: number }
|
|
23
25
|
|
|
24
26
|
constructor(
|
|
25
27
|
def: CheckboxesFieldComponent,
|
|
@@ -42,11 +44,8 @@ export class CheckboxesField extends SelectionControlField {
|
|
|
42
44
|
.single()
|
|
43
45
|
.label(this.label)
|
|
44
46
|
.required()
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
'array.max': messageTemplate.arrayMax,
|
|
48
|
-
'array.length': messageTemplate.arrayLength
|
|
49
|
-
})
|
|
47
|
+
|
|
48
|
+
const limits: { min?: number; max?: number; length?: number } = {}
|
|
50
49
|
|
|
51
50
|
if (options.required === false) {
|
|
52
51
|
formSchema = formSchema.optional()
|
|
@@ -54,16 +53,25 @@ export class CheckboxesField extends SelectionControlField {
|
|
|
54
53
|
|
|
55
54
|
if (typeof schema?.length === 'number') {
|
|
56
55
|
formSchema = formSchema.length(schema.length)
|
|
56
|
+
limits.length = schema.length
|
|
57
57
|
} else {
|
|
58
58
|
if (typeof schema?.min === 'number') {
|
|
59
59
|
formSchema = formSchema.min(schema.min)
|
|
60
|
+
limits.min = schema.min
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
if (typeof schema?.max === 'number') {
|
|
63
64
|
formSchema = formSchema.max(schema.max)
|
|
65
|
+
limits.max = schema.max
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
|
|
69
|
+
this.limits = limits
|
|
70
|
+
|
|
71
|
+
formSchema = formSchema.messages(
|
|
72
|
+
CheckboxesField.buildErrorMessages(EN_GB, limits)
|
|
73
|
+
)
|
|
74
|
+
|
|
67
75
|
this.formSchema = formSchema.default([])
|
|
68
76
|
this.stateSchema = formSchema.default(null).allow(null)
|
|
69
77
|
this.options = options
|
|
@@ -135,13 +143,9 @@ export class CheckboxesField extends SelectionControlField {
|
|
|
135
143
|
}
|
|
136
144
|
|
|
137
145
|
getValidationMessagesOverride(translator: Translator) {
|
|
138
|
-
const {
|
|
146
|
+
const { language } = translator
|
|
139
147
|
return {
|
|
140
|
-
[this.name]:
|
|
141
|
-
'array.min': buildValidationMessages(t).arrayMin,
|
|
142
|
-
'array.max': buildValidationMessages(t).arrayMax,
|
|
143
|
-
'array.length': buildValidationMessages(t).arrayLength
|
|
144
|
-
} as LanguageMessages
|
|
148
|
+
[this.name]: CheckboxesField.buildErrorMessages(language, this.limits)
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
|
|
@@ -181,4 +185,21 @@ export class CheckboxesField extends SelectionControlField {
|
|
|
181
185
|
|
|
182
186
|
return value.every(isFormValue)
|
|
183
187
|
}
|
|
188
|
+
|
|
189
|
+
static buildErrorMessages(
|
|
190
|
+
language: string,
|
|
191
|
+
limits: { min?: number; max?: number; length?: number } = {}
|
|
192
|
+
) {
|
|
193
|
+
return {
|
|
194
|
+
'array.min': tPlugin('validation.arrayMin', language, {
|
|
195
|
+
count: limits.min ?? 1
|
|
196
|
+
}),
|
|
197
|
+
'array.max': tPlugin('validation.arrayMax', language, {
|
|
198
|
+
count: limits.max ?? 1
|
|
199
|
+
}),
|
|
200
|
+
'array.length': tPlugin('validation.arrayLength', language, {
|
|
201
|
+
count: limits.length ?? 1
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
}
|
|
184
205
|
}
|
|
@@ -187,7 +187,7 @@ export class EastingNorthingField extends FormComponent {
|
|
|
187
187
|
if (err.context?.country) {
|
|
188
188
|
err.text = translator.t(
|
|
189
189
|
'components.eastingNorthingField.wrongCountry',
|
|
190
|
-
{ country: err.context.country }
|
|
190
|
+
{ country: translator.t(`common.${err.context.country}`) }
|
|
191
191
|
)
|
|
192
192
|
}
|
|
193
193
|
})
|
|
@@ -113,6 +113,7 @@ export class FileUploadField extends FormComponent {
|
|
|
113
113
|
declare schema: FileUploadFieldComponent['schema']
|
|
114
114
|
declare formSchema: ArraySchema<FileState>
|
|
115
115
|
declare stateSchema: ArraySchema<FileState>
|
|
116
|
+
declare limits: { min?: number; max?: number; length?: number }
|
|
116
117
|
|
|
117
118
|
constructor(
|
|
118
119
|
def: FileUploadFieldComponent,
|
|
@@ -132,21 +133,31 @@ export class FileUploadField extends FormComponent {
|
|
|
132
133
|
formSchema = formSchema.optional()
|
|
133
134
|
}
|
|
134
135
|
|
|
136
|
+
const limits: { min?: number; max?: number; length?: number } = {}
|
|
137
|
+
|
|
135
138
|
if (typeof schema.length !== 'number') {
|
|
136
139
|
if (typeof schema.max === 'number') {
|
|
137
140
|
formSchema = formSchema.max(schema.max)
|
|
141
|
+
limits.max = schema.max
|
|
138
142
|
}
|
|
139
143
|
|
|
140
144
|
if (typeof schema.min === 'number') {
|
|
141
145
|
formSchema = formSchema.min(schema.min)
|
|
146
|
+
limits.min = schema.min
|
|
142
147
|
} else if (options.required !== false) {
|
|
143
148
|
formSchema = formSchema.min(1)
|
|
149
|
+
limits.min = 1
|
|
144
150
|
}
|
|
145
151
|
} else {
|
|
146
152
|
formSchema = formSchema.length(schema.length)
|
|
153
|
+
limits.length = schema.length
|
|
147
154
|
}
|
|
148
155
|
|
|
149
|
-
|
|
156
|
+
this.limits = limits
|
|
157
|
+
|
|
158
|
+
formSchema = formSchema.messages(
|
|
159
|
+
FileUploadField.buildErrorMessages(EN_GB, limits)
|
|
160
|
+
)
|
|
150
161
|
|
|
151
162
|
this.formSchema = formSchema.items(formItemSchema)
|
|
152
163
|
this.stateSchema = formSchema
|
|
@@ -309,7 +320,7 @@ export class FileUploadField extends FormComponent {
|
|
|
309
320
|
getValidationMessagesOverride(translator: Translator) {
|
|
310
321
|
const { language } = translator
|
|
311
322
|
return {
|
|
312
|
-
[this.name]: FileUploadField.buildErrorMessages(language)
|
|
323
|
+
[this.name]: FileUploadField.buildErrorMessages(language, this.limits)
|
|
313
324
|
}
|
|
314
325
|
}
|
|
315
326
|
|
|
@@ -417,11 +428,20 @@ export class FileUploadField extends FormComponent {
|
|
|
417
428
|
}
|
|
418
429
|
}
|
|
419
430
|
|
|
420
|
-
static buildErrorMessages(
|
|
431
|
+
static buildErrorMessages(
|
|
432
|
+
language: string,
|
|
433
|
+
limits: { min?: number; max?: number; length?: number } = {}
|
|
434
|
+
) {
|
|
421
435
|
return {
|
|
422
|
-
'array.min': tPlugin('validation.filesMin', language
|
|
423
|
-
|
|
424
|
-
|
|
436
|
+
'array.min': tPlugin('validation.filesMin', language, {
|
|
437
|
+
count: limits.min ?? 1
|
|
438
|
+
}),
|
|
439
|
+
'array.max': tPlugin('validation.filesMax', language, {
|
|
440
|
+
count: limits.max ?? 1
|
|
441
|
+
}),
|
|
442
|
+
'array.length': tPlugin('validation.filesLength', language, {
|
|
443
|
+
count: limits.length ?? 1
|
|
444
|
+
})
|
|
425
445
|
}
|
|
426
446
|
}
|
|
427
447
|
}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { type GeospatialFieldComponent } from '@defra/forms-model'
|
|
2
2
|
import { type ArraySchema } from 'joi'
|
|
3
3
|
|
|
4
|
+
import { EN_GB } from '../../../constants.js'
|
|
4
5
|
import { type ComponentBase } from './ComponentBase.js'
|
|
5
6
|
import {
|
|
6
7
|
FormComponent,
|
|
7
8
|
isGeospatialState
|
|
8
9
|
} from './FormComponent.js'
|
|
9
10
|
import { getMapLayers } from './LocationFieldHelpers.js'
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
determineLimits,
|
|
13
|
+
getGeospatialSchema
|
|
14
|
+
} from './helpers/geospatial.js'
|
|
11
15
|
import { type RenderContext } from './types.js'
|
|
16
|
+
import { t as tPlugin } from '../i18n/index.js'
|
|
12
17
|
import { type Translator } from '../i18n/types.js'
|
|
13
18
|
import { messageTemplate } from '../pageControllers/validationOptions.js'
|
|
14
19
|
import {
|
|
@@ -24,6 +29,7 @@ export class GeospatialField extends FormComponent {
|
|
|
24
29
|
declare options: GeospatialFieldComponent['options']
|
|
25
30
|
declare formSchema: ArraySchema<GeospatialState>
|
|
26
31
|
declare stateSchema: ArraySchema<GeospatialState>
|
|
32
|
+
declare limits: { min?: number; max?: number; length?: number }
|
|
27
33
|
|
|
28
34
|
constructor(
|
|
29
35
|
def: GeospatialFieldComponent,
|
|
@@ -33,20 +39,24 @@ export class GeospatialField extends FormComponent {
|
|
|
33
39
|
|
|
34
40
|
const { options } = def
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
let formSchema = getGeospatialSchema(def).label(this.label)
|
|
43
|
+
|
|
44
|
+
const isOptional = options.required === false
|
|
45
|
+
const limits = determineLimits(def, isOptional)
|
|
46
|
+
|
|
47
|
+
formSchema = formSchema.messages(
|
|
48
|
+
GeospatialField.buildErrorMessages(EN_GB, limits)
|
|
49
|
+
)
|
|
41
50
|
|
|
42
51
|
this.formSchema = formSchema
|
|
43
52
|
this.stateSchema = formSchema.default(null)
|
|
44
53
|
|
|
45
|
-
if (
|
|
54
|
+
if (isOptional) {
|
|
46
55
|
this.stateSchema = this.stateSchema.allow(null)
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
this.options = options
|
|
59
|
+
this.limits = limits
|
|
50
60
|
}
|
|
51
61
|
|
|
52
62
|
getFormValueFromState(state: FormSubmissionState) {
|
|
@@ -127,9 +137,7 @@ export class GeospatialField extends FormComponent {
|
|
|
127
137
|
'components.geospatialField.validation.wrongCountry',
|
|
128
138
|
{
|
|
129
139
|
count: Number(err.path[1]) + 1,
|
|
130
|
-
country: translator.t(
|
|
131
|
-
`common.${(err.context.country as string).toLowerCase()}`
|
|
132
|
-
)
|
|
140
|
+
country: translator.t(`common.${err.context.country}`)
|
|
133
141
|
}
|
|
134
142
|
)
|
|
135
143
|
}
|
|
@@ -149,6 +157,13 @@ export class GeospatialField extends FormComponent {
|
|
|
149
157
|
return isGeospatialState(value)
|
|
150
158
|
}
|
|
151
159
|
|
|
160
|
+
getValidationMessagesOverride(translator: Translator) {
|
|
161
|
+
const { language } = translator
|
|
162
|
+
return {
|
|
163
|
+
[this.name]: GeospatialField.buildErrorMessages(language, this.limits)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
152
167
|
/**
|
|
153
168
|
* For error preview page that shows all possible errors on a component
|
|
154
169
|
*/
|
|
@@ -169,11 +184,28 @@ export class GeospatialField extends FormComponent {
|
|
|
169
184
|
{ type: 'required', template: messageTemplate.selectRequired },
|
|
170
185
|
{
|
|
171
186
|
type: 'array.min',
|
|
172
|
-
template: '{{#title}} must contain at least 1
|
|
187
|
+
template: '{{#title}} must contain at least 1 item'
|
|
173
188
|
},
|
|
174
189
|
{ type: 'object.invalidjson', template: messageTemplate.format }
|
|
175
190
|
],
|
|
176
191
|
advancedSettingsErrors: []
|
|
177
192
|
}
|
|
178
193
|
}
|
|
194
|
+
|
|
195
|
+
static buildErrorMessages(
|
|
196
|
+
language: string,
|
|
197
|
+
limits: { min?: number; max?: number; length?: number } = {}
|
|
198
|
+
) {
|
|
199
|
+
return {
|
|
200
|
+
'array.min': tPlugin('validation.featuresMin', language, {
|
|
201
|
+
count: limits.min ?? 1
|
|
202
|
+
}),
|
|
203
|
+
'array.max': tPlugin('validation.featuresMax', language, {
|
|
204
|
+
count: limits.max ?? 1
|
|
205
|
+
}),
|
|
206
|
+
'array.length': tPlugin('validation.featuresLength', language, {
|
|
207
|
+
count: limits.length ?? 1
|
|
208
|
+
})
|
|
209
|
+
}
|
|
210
|
+
}
|
|
179
211
|
}
|
|
@@ -125,9 +125,11 @@ export abstract class LocationFieldBase extends FormComponent {
|
|
|
125
125
|
const viewModel = super.getViewModel(context)
|
|
126
126
|
|
|
127
127
|
if (this.instructionText) {
|
|
128
|
+
const { tComponent } = context.translator
|
|
128
129
|
return {
|
|
129
130
|
...viewModel,
|
|
130
|
-
instructionText:
|
|
131
|
+
instructionText:
|
|
132
|
+
tComponent(this.def, 'instructionText') || this.instructionText
|
|
131
133
|
}
|
|
132
134
|
}
|
|
133
135
|
|
|
@@ -198,9 +198,15 @@ export function getLocationFieldViewModel(
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
if (component.options.instructionText) {
|
|
201
|
+
const { t, tComponent } = context.translator
|
|
202
|
+
|
|
201
203
|
return {
|
|
202
204
|
...result,
|
|
203
|
-
|
|
205
|
+
instructionSummary: t('components.locationFieldBase.howToFind'),
|
|
206
|
+
instructionText:
|
|
207
|
+
tComponent(component.def, 'instructionText') ||
|
|
208
|
+
component.options.instructionText,
|
|
209
|
+
t
|
|
204
210
|
}
|
|
205
211
|
}
|
|
206
212
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
GeospatialFieldOptionsCountryEnum,
|
|
3
2
|
type GeospatialFieldComponent,
|
|
4
3
|
type GeospatialFieldOptionsCountry
|
|
5
4
|
} from '@defra/forms-model'
|
|
@@ -20,13 +19,6 @@ import {
|
|
|
20
19
|
} from '../../types.js'
|
|
21
20
|
import { countries } from '../../../map/routes/index.js'
|
|
22
21
|
|
|
23
|
-
const countriesDesc: Record<GeospatialFieldOptionsCountryEnum, string> = {
|
|
24
|
-
[GeospatialFieldOptionsCountryEnum.England]: 'England',
|
|
25
|
-
[GeospatialFieldOptionsCountryEnum.NorthernIreland]: 'Northern Ireland',
|
|
26
|
-
[GeospatialFieldOptionsCountryEnum.Scotland]: 'Scotland',
|
|
27
|
-
[GeospatialFieldOptionsCountryEnum.Wales]: 'Wales'
|
|
28
|
-
}
|
|
29
|
-
|
|
30
22
|
const Joi = JoiBase.extend({
|
|
31
23
|
type: 'array',
|
|
32
24
|
base: JoiBase.array(),
|
|
@@ -103,25 +95,43 @@ const featureSchema = Joi.object<Feature>().keys({
|
|
|
103
95
|
geometry: featureGeometrySchema
|
|
104
96
|
})
|
|
105
97
|
|
|
106
|
-
function
|
|
107
|
-
|
|
108
|
-
|
|
98
|
+
export function determineLimits(
|
|
99
|
+
def: GeospatialFieldComponent,
|
|
100
|
+
isOptional: boolean
|
|
109
101
|
) {
|
|
110
|
-
const {
|
|
111
|
-
const
|
|
112
|
-
|
|
102
|
+
const { schema: constraints } = def
|
|
103
|
+
const limits: { min?: number; max?: number; length?: number } = {}
|
|
113
104
|
if (typeof constraints?.length === 'number') {
|
|
114
|
-
|
|
105
|
+
limits.length = constraints.length
|
|
115
106
|
} else {
|
|
116
107
|
if (typeof constraints?.min === 'number') {
|
|
117
|
-
|
|
108
|
+
limits.min = constraints.min
|
|
118
109
|
} else if (!isOptional) {
|
|
119
|
-
|
|
110
|
+
limits.min = 1
|
|
120
111
|
}
|
|
121
112
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
113
|
+
limits.max = typeof constraints?.max === 'number' ? constraints.max : 50
|
|
114
|
+
}
|
|
115
|
+
return limits
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function applySchemaConstraints(
|
|
119
|
+
schema: JoiBase.ArraySchema<Feature[]>,
|
|
120
|
+
def: GeospatialFieldComponent
|
|
121
|
+
) {
|
|
122
|
+
const { options } = def
|
|
123
|
+
const isOptional = options.required === false
|
|
124
|
+
|
|
125
|
+
const limits = determineLimits(def, isOptional)
|
|
126
|
+
|
|
127
|
+
if (limits.length !== undefined) {
|
|
128
|
+
schema = schema.length(limits.length)
|
|
129
|
+
}
|
|
130
|
+
if (limits.min !== undefined) {
|
|
131
|
+
schema = schema.min(limits.min)
|
|
132
|
+
}
|
|
133
|
+
if (limits.max !== undefined) {
|
|
134
|
+
schema = schema.max(limits.max)
|
|
125
135
|
}
|
|
126
136
|
|
|
127
137
|
if (isOptional) {
|
|
@@ -161,7 +171,7 @@ export function getGeospatialSchema(
|
|
|
161
171
|
|
|
162
172
|
if (!result) {
|
|
163
173
|
return helpers.error('any.custom', {
|
|
164
|
-
country
|
|
174
|
+
country
|
|
165
175
|
})
|
|
166
176
|
}
|
|
167
177
|
|
|
@@ -212,7 +222,7 @@ export function getEastingNorthingCountryValidator(
|
|
|
212
222
|
return helpers.error(
|
|
213
223
|
'any.custom',
|
|
214
224
|
{
|
|
215
|
-
country
|
|
225
|
+
country
|
|
216
226
|
},
|
|
217
227
|
{ path: [field.name] }
|
|
218
228
|
)
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
FormStatus,
|
|
3
|
+
type FormDefinition,
|
|
4
|
+
type FormMetadata
|
|
5
|
+
} from '@defra/forms-model'
|
|
2
6
|
import Boom from '@hapi/boom'
|
|
3
7
|
|
|
4
8
|
export interface OfflineBoomData {
|
|
5
9
|
offline: true
|
|
6
10
|
metadata: FormMetadata
|
|
11
|
+
definition: FormDefinition | undefined
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
/**
|
|
@@ -13,6 +18,7 @@ export interface OfflineBoomData {
|
|
|
13
18
|
*/
|
|
14
19
|
export function assertFormAvailable(
|
|
15
20
|
metadata: FormMetadata,
|
|
21
|
+
definition: FormDefinition | undefined,
|
|
16
22
|
formState: FormStatus,
|
|
17
23
|
isPreview: boolean
|
|
18
24
|
): void {
|
|
@@ -21,7 +27,7 @@ export function assertFormAvailable(
|
|
|
21
27
|
formState === FormStatus.Live &&
|
|
22
28
|
!isPreview
|
|
23
29
|
) {
|
|
24
|
-
const data: OfflineBoomData = { offline: true, metadata }
|
|
30
|
+
const data: OfflineBoomData = { offline: true, metadata, definition }
|
|
25
31
|
throw Boom.boomify(new Error(`Form ${metadata.slug} is offline`), {
|
|
26
32
|
statusCode: 503,
|
|
27
33
|
data
|
|
@@ -56,13 +56,14 @@ export async function getFormModel(
|
|
|
56
56
|
const formState = resolveState(state)
|
|
57
57
|
|
|
58
58
|
const metadata = await formsService.getFormMetadata(slug)
|
|
59
|
-
assertFormAvailable(metadata, formState, isPreview)
|
|
60
59
|
|
|
61
60
|
const definition = await formsService.getFormDefinition(
|
|
62
61
|
metadata.id,
|
|
63
62
|
formState
|
|
64
63
|
)
|
|
65
64
|
|
|
65
|
+
assertFormAvailable(metadata, definition, formState, isPreview)
|
|
66
|
+
|
|
66
67
|
if (!definition) {
|
|
67
68
|
throw Boom.notFound(
|
|
68
69
|
`No definition found for form metadata ${metadata.id} (${slug}) ${state}`
|
|
@@ -145,7 +146,6 @@ export async function resolveFormModel(
|
|
|
145
146
|
const metadata = await formsService.getFormMetadata(slug)
|
|
146
147
|
const formState = resolveState(state)
|
|
147
148
|
const isPreview = options.isPreview ?? isPreviewState(state, options)
|
|
148
|
-
assertFormAvailable(metadata, formState, isPreview)
|
|
149
149
|
const stateMetadata = metadata[formState]
|
|
150
150
|
|
|
151
151
|
if (!stateMetadata) {
|
|
@@ -199,6 +199,8 @@ export async function resolveFormModel(
|
|
|
199
199
|
cache.set(cacheKey, entry)
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
assertFormAvailable(metadata, entry.model.def, formState, isPreview)
|
|
203
|
+
|
|
202
204
|
return entry.model
|
|
203
205
|
}
|
|
204
206
|
|
|
@@ -16,7 +16,9 @@ const opts = {
|
|
|
16
16
|
* because Joi cannot resolve custom functions from a plain string.
|
|
17
17
|
* Plain strings with only built-in tokens ({{#label}}, {{#limit}}) work without wrapping.
|
|
18
18
|
*/
|
|
19
|
-
export function buildValidationMessages(
|
|
19
|
+
export function buildValidationMessages(
|
|
20
|
+
t: (key: string, options?: Record<string, unknown>) => string
|
|
21
|
+
) {
|
|
20
22
|
return {
|
|
21
23
|
// Expressions — contain lowerFirst custom function
|
|
22
24
|
required: joi.expression(t('validation.required'), opts) as JoiExpression,
|
|
@@ -57,15 +59,18 @@ export function buildValidationMessages(t: (key: string) => string) {
|
|
|
57
59
|
dateMax: t('components.dateField.validation.dateMax'),
|
|
58
60
|
|
|
59
61
|
unicode: t('validation.unicode'),
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
// These generic templates are shared across fields with differing limits, so a
|
|
63
|
+
// fixed singular count is used here — components needing accurate singular/plural
|
|
64
|
+
// text (e.g. FileUploadField) build their own per-instance messages instead.
|
|
65
|
+
arrayMin: t('validation.arrayMin', { count: 1 }),
|
|
66
|
+
arrayMax: t('validation.arrayMax', { count: 1 }),
|
|
67
|
+
arrayLength: t('validation.arrayLength', { count: 1 }),
|
|
68
|
+
featuresMin: t('validation.featuresMin', { count: 1 }),
|
|
69
|
+
featuresMax: t('validation.featuresMax', { count: 1 }),
|
|
70
|
+
featuresLength: t('validation.featuresLength', { count: 1 }),
|
|
71
|
+
filesMin: t('validation.filesMin', { count: 1 }),
|
|
72
|
+
filesMax: t('validation.filesMax', { count: 1 }),
|
|
73
|
+
filesLength: t('validation.filesLength', { count: 1 })
|
|
69
74
|
}
|
|
70
75
|
}
|
|
71
76
|
|
|
@@ -16,15 +16,61 @@
|
|
|
16
16
|
"numberMax": "Rhaid i {{#label}} fod yn {{#limit}} neu is",
|
|
17
17
|
"maxWords": "Rhaid i {{#label}} fod yn {{#limit}} o eiriau neu lai",
|
|
18
18
|
"unicode": "Mae {{#label}} yn cynnwys nodau annilys, er enghraifft, dashes hirion",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
19
|
+
"arrayMin_zero": "Dewiswch o leiaf 1 opsiwn o'r rhestr",
|
|
20
|
+
"arrayMin_one": "Dewiswch o leiaf {{#limit}} opsiwn o'r rhestr",
|
|
21
|
+
"arrayMin_two": "Dewiswch o leiaf ddau opsiwn o'r rhestr",
|
|
22
|
+
"arrayMin_few": "Dewiswch o leiaf {{#limit}} opsiwn o'r rhestr",
|
|
23
|
+
"arrayMin_many": "Dewiswch o leiaf {{#limit}} opsiwn o'r rhestr",
|
|
24
|
+
"arrayMin_other": "Dewiswch o leiaf {{#limit}} opsiwn o'r rhestr",
|
|
25
|
+
"arrayMax_zero": "Dim ond {{#limit}} opsiynau y gellir eu dewis o'r rhestr",
|
|
26
|
+
"arrayMax_one": "Dim ond {{#limit}} opsiwn y gellir ei ddewis o'r rhestr",
|
|
27
|
+
"arrayMax_two": "Dim ond dwy opsiwn y gellir eu dewis o'r rhestr",
|
|
28
|
+
"arrayMax_few": "Dim ond {{#limit}} opsiwn y gellir eu dewis o'r rhestr",
|
|
29
|
+
"arrayMax_many": "Dim ond {{#limit}} opsiwn y gellir eu dewis o'r rhestr",
|
|
30
|
+
"arrayMax_other": "Dim ond {{#limit}} opsiwn y gellir eu dewis o'r rhestr",
|
|
31
|
+
"arrayLength_zero": "Dewiswch 0 opsiwn yn unig o'r rhestr",
|
|
32
|
+
"arrayLength_one": "Dewiswch un opsiwn yn unig o'r rhestr",
|
|
33
|
+
"arrayLength_two": "Dewiswch {{#limit}} opsiwn yn unig o'r rhestr",
|
|
34
|
+
"arrayLength_few": "Dewiswch {{#limit}} opsiwn yn unig o'r rhestr",
|
|
35
|
+
"arrayLength_many": "Dewiswch {{#limit}} opsiwn yn unig o'r rhestr",
|
|
36
|
+
"arrayLength_other": "Dewiswch {{#limit}} opsiwn yn unig o'r rhestr",
|
|
37
|
+
|
|
38
|
+
"featuresMin_zero": "Diffiniwch o leiaf {{#limit}} nodwedd",
|
|
39
|
+
"featuresMin_one": "Diffiniwch o leiaf un nodwedd",
|
|
40
|
+
"featuresMin_two": "Diffiniwch o leiaf {{#limit}} nodwedd",
|
|
41
|
+
"featuresMin_few": "Diffiniwch o leiaf {{#limit}} nodwedd",
|
|
42
|
+
"featuresMin_many": "Diffiniwch o leiaf {{#limit}} nodwedd",
|
|
43
|
+
"featuresMin_other": "Diffiniwch o leiaf {{#limit}} nodwedd",
|
|
44
|
+
"featuresMax_zero": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
|
|
45
|
+
"featuresMax_one": "Dim ond {{#limit}} nodwedd y gellir ei diffinio",
|
|
46
|
+
"featuresMax_two": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
|
|
47
|
+
"featuresMax_few": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
|
|
48
|
+
"featuresMax_many": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
|
|
49
|
+
"featuresMax_other": "Dim ond {{#limit}} nodwedd y gellir eu diffinio",
|
|
50
|
+
"featuresLength_zero": "Diffiniwch yn union {{#limit}} nodwedd",
|
|
51
|
+
"featuresLength_one": "Diffiniwch un nodwedd yn union",
|
|
52
|
+
"featuresLength_two": "Diffiniwch nodweddion {{#limit}} yn union",
|
|
53
|
+
"featuresLength_few": "Diffiniwch nodweddion {{#limit}} yn union",
|
|
54
|
+
"featuresLength_many": "Diffiniwch nodweddion {{#limit}} yn union",
|
|
55
|
+
"featuresLength_other": "Diffiniwch nodweddion {{#limit}} yn union",
|
|
56
|
+
"filesMin_zero": "Rhaid i chi uwchlwytho {{#limit}} ffeil neu fwy",
|
|
57
|
+
"filesMin_one": "Rhaid i chi uwchlwytho un ffeil neu fwy",
|
|
58
|
+
"filesMin_two": "Rhaid i chi uwchlwytho {{#limit}} o ffeiliau neu fwy",
|
|
59
|
+
"filesMin_few": "Rhaid i chi uwchlwytho {{#limit}} o ffeiliau neu fwy",
|
|
60
|
+
"filesMin_many": "Rhaid i chi uwchlwytho {{#limit}} o ffeiliau neu fwy",
|
|
61
|
+
"filesMin_other": "Rhaid i chi uwchlwytho {{#limit}} o ffeiliau neu fwy",
|
|
62
|
+
"filesMax_zero": "Dim ond {{#limit}} ffeil neu lai y gallwch eu huwchlwytho",
|
|
63
|
+
"filesMax_one": "Dim ond un ffeil neu lai y gallwch ei huwchlwytho",
|
|
64
|
+
"filesMax_two": "Dim ond {{#limit}} o ffeiliau neu lai y gallwch eu huwchlwytho",
|
|
65
|
+
"filesMax_few": "Dim ond {{#limit}} o ffeiliau neu lai y gallwch eu huwchlwytho",
|
|
66
|
+
"filesMax_many": "Dim ond {{#limit}} o ffeiliau neu lai y gallwch eu huwchlwytho",
|
|
67
|
+
"filesMax_other": "Dim ond {{#limit}} o ffeiliau neu lai y gallwch eu huwchlwytho",
|
|
68
|
+
"filesLength_zero": "Rhaid i chi uwchlwytho union {{#limit}} ffeil",
|
|
69
|
+
"filesLength_one": "Rhaid i chi uwchlwytho union un ffeil",
|
|
70
|
+
"filesLength_two": "Rhaid i chi uwchlwytho'n union {{#limit}} o ffeiliau",
|
|
71
|
+
"filesLength_few": "Rhaid i chi uwchlwytho'n union {{#limit}} o ffeiliau",
|
|
72
|
+
"filesLength_many": "Rhaid i chi uwchlwytho'n union {{#limit}} o ffeiliau",
|
|
73
|
+
"filesLength_other": "Rhaid i chi uwchlwytho'n union {{#limit}} o ffeiliau"
|
|
28
74
|
},
|
|
29
75
|
|
|
30
76
|
"errors": {
|
|
@@ -44,7 +90,7 @@
|
|
|
44
90
|
"and": "a",
|
|
45
91
|
"england": "Lloegr",
|
|
46
92
|
"wales": "Cymru",
|
|
47
|
-
"
|
|
93
|
+
"northern-ireland": "Gogledd Iwerddon",
|
|
48
94
|
"scotland": "Yr Alban",
|
|
49
95
|
"sendFeedback": "Anfon adborth"
|
|
50
96
|
},
|
|
@@ -161,6 +207,16 @@
|
|
|
161
207
|
"bannerForce": "Rhagolwg o ffurflen [[previewMode]] yw hon. Peidiwch â rhoi gwybodaeth bersonol.",
|
|
162
208
|
"bannerText": "Dyma ragolwg o dudalen ffurflen [[previewMode]] rydych chi'n ei golygu.",
|
|
163
209
|
"previousPages": "Mae'n dibynnu ar atebion o dudalennau cynharach yn y ffurflen. Yn y fersiwn fyw, bydd angen i ddefnyddwyr gwblhau'r cwestiynau hynny yn gyntaf."
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
"formUnavailable": {
|
|
213
|
+
"title": "Mae'n ddrwg gennyf, nid yw'r ffurflen hon ar gael",
|
|
214
|
+
"subHeading": "Nid yw '[[formTitle]]' ar gael mwyach.",
|
|
215
|
+
"contactDetailsHeading": "Manylion cyswllt ar gyfer [[organisationName]]",
|
|
216
|
+
"telephone": "Ffôn",
|
|
217
|
+
"callCharges": "Dysgwch am gostau galwadau",
|
|
218
|
+
"email": "E-bost",
|
|
219
|
+
"onlineContactForm": "Ffurflen gyswllt ar-lein"
|
|
164
220
|
}
|
|
165
221
|
},
|
|
166
222
|
|