@defra/forms-model 3.0.429 → 3.0.431
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/README.md +163 -1
- package/dist/module/common/pagination/index.js +2 -2
- package/dist/module/common/pagination/index.js.map +1 -1
- package/dist/module/common/search/index.js +4 -4
- package/dist/module/common/search/index.js.map +1 -1
- package/dist/module/common/sorting/index.js +2 -2
- package/dist/module/common/sorting/index.js.map +1 -1
- package/dist/module/form/form-definition/index.js +156 -156
- package/dist/module/form/form-definition/index.js.map +1 -1
- package/dist/module/form/form-editor/index.js +47 -37
- package/dist/module/form/form-editor/index.js.map +1 -1
- package/dist/module/form/form-editor/types.js.map +1 -1
- package/dist/module/form/form-manager/index.js +3 -3
- package/dist/module/form/form-manager/index.js.map +1 -1
- package/dist/module/form/form-metadata/index.js +34 -34
- package/dist/module/form/form-metadata/index.js.map +1 -1
- package/dist/module/form/form-submission/index.js +13 -13
- package/dist/module/form/form-submission/index.js.map +1 -1
- package/dist/module/types/joi-to-json.d.js +2 -0
- package/dist/module/types/joi-to-json.d.js.map +1 -0
- package/dist/types/common/pagination/index.d.ts.map +1 -1
- package/dist/types/common/search/index.d.ts.map +1 -1
- package/dist/types/common/sorting/index.d.ts.map +1 -1
- package/dist/types/form/form-definition/index.d.ts.map +1 -1
- package/dist/types/form/form-editor/index.d.ts +17 -7
- package/dist/types/form/form-editor/index.d.ts.map +1 -1
- package/dist/types/form/form-editor/types.d.ts +45 -1
- package/dist/types/form/form-editor/types.d.ts.map +1 -1
- package/dist/types/form/form-manager/index.d.ts.map +1 -1
- package/dist/types/form/form-metadata/index.d.ts.map +1 -1
- package/dist/types/form/form-submission/index.d.ts.map +1 -1
- package/package.json +6 -4
- package/scripts/generate-schemas.js +238 -0
- package/scripts/schema-modules/constants.js +39 -0
- package/scripts/schema-modules/schema-processors.js +109 -0
- package/scripts/schema-modules/schema-simplifiers.js +351 -0
- package/scripts/schema-modules/title-processors.js +327 -0
- package/scripts/schema-modules/types.js +21 -0
- package/scripts/schema-modules/utils.js +41 -0
- package/src/common/pagination/index.ts +8 -1
- package/src/common/search/index.ts +17 -3
- package/src/common/sorting/index.ts +8 -2
- package/src/form/form-definition/index.ts +567 -238
- package/src/form/form-editor/index.ts +207 -24
- package/src/form/form-editor/types.ts +69 -0
- package/src/form/form-manager/index.ts +11 -2
- package/src/form/form-metadata/index.ts +118 -40
- package/src/form/form-submission/index.ts +33 -10
- package/src/types/joi-to-json.d.ts +15 -0
@@ -17,6 +17,8 @@ export enum QuestionTypeSubGroup {
|
|
17
17
|
export const pageTypeSchema = Joi.string()
|
18
18
|
.required()
|
19
19
|
.valid('question', 'guidance')
|
20
|
+
.description('Type of page - either a question page or guidance page')
|
21
|
+
|
20
22
|
export const questionTypeSchema = Joi.string()
|
21
23
|
.required()
|
22
24
|
.valid(
|
@@ -32,6 +34,7 @@ export const questionTypeSchema = Joi.string()
|
|
32
34
|
ComponentType.RadiosField,
|
33
35
|
ComponentType.AutocompleteField
|
34
36
|
)
|
37
|
+
.description('The high-level type of question, including grouped types')
|
35
38
|
|
36
39
|
export const questionTypeFullSchema = Joi.string()
|
37
40
|
.required()
|
@@ -50,6 +53,7 @@ export const questionTypeFullSchema = Joi.string()
|
|
50
53
|
ComponentType.RadiosField,
|
51
54
|
ComponentType.AutocompleteField
|
52
55
|
)
|
56
|
+
.description('The specific component type to use for this question')
|
53
57
|
|
54
58
|
export const writtenAnswerSubSchema = Joi.string()
|
55
59
|
.required()
|
@@ -58,6 +62,8 @@ export const writtenAnswerSubSchema = Joi.string()
|
|
58
62
|
ComponentType.MultilineTextField,
|
59
63
|
ComponentType.NumberField
|
60
64
|
)
|
65
|
+
.description('Subtype for written answer questions')
|
66
|
+
|
61
67
|
export const dateSubSchema = Joi.string()
|
62
68
|
.required()
|
63
69
|
.valid(ComponentType.DatePartsField, ComponentType.MonthYearField)
|
@@ -69,59 +75,226 @@ export const listSubSchema = Joi.string()
|
|
69
75
|
ComponentType.RadiosField,
|
70
76
|
ComponentType.AutocompleteField
|
71
77
|
)
|
78
|
+
.description('Subtype for date-related questions')
|
79
|
+
|
80
|
+
export const nameSchema = Joi.string()
|
81
|
+
.trim()
|
82
|
+
.required()
|
83
|
+
.description('Unique identifier for the field')
|
84
|
+
|
85
|
+
export const questionSchema = Joi.string()
|
86
|
+
.trim()
|
87
|
+
.required()
|
88
|
+
.description('The question text displayed to the user')
|
89
|
+
|
90
|
+
export const hintTextSchema = Joi.string()
|
91
|
+
.trim()
|
92
|
+
.optional()
|
93
|
+
.allow('')
|
94
|
+
.description('Optional guidance text displayed below the question')
|
72
95
|
|
73
|
-
export const nameSchema = Joi.string().trim().required()
|
74
|
-
export const questionSchema = Joi.string().trim().required()
|
75
|
-
export const hintTextSchema = Joi.string().trim().optional().allow('')
|
76
96
|
export const questionOptionalSchema = Joi.string()
|
77
97
|
.trim()
|
78
98
|
.optional()
|
79
99
|
.valid('', 'true')
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
export const
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
export const
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
100
|
+
.description(
|
101
|
+
'Indicates whether a question is optional. Empty string or "true" values are accepted.'
|
102
|
+
)
|
103
|
+
|
104
|
+
export const exactFilesSchema = Joi.number()
|
105
|
+
.empty('')
|
106
|
+
.integer()
|
107
|
+
.min(1)
|
108
|
+
.max(25)
|
109
|
+
.description(
|
110
|
+
'Specifies the exact number of files required for upload. Must be between 1 and 25.'
|
111
|
+
)
|
112
|
+
|
113
|
+
export const minFilesSchema = Joi.number()
|
114
|
+
.empty('')
|
115
|
+
.integer()
|
116
|
+
.min(0)
|
117
|
+
.max(25)
|
118
|
+
.description(
|
119
|
+
'Minimum number of files required for upload. Must be between 0 and 25.'
|
120
|
+
)
|
121
|
+
|
122
|
+
export const maxFilesSchema = Joi.number()
|
123
|
+
.empty('')
|
124
|
+
.integer()
|
125
|
+
.min(1)
|
126
|
+
.max(25)
|
127
|
+
.description(
|
128
|
+
'Maximum number of files allowed for upload. Must be between 1 and 25.'
|
129
|
+
)
|
130
|
+
|
101
131
|
export const fileTypesSchema = Joi.array()
|
102
132
|
.items(Joi.string())
|
103
133
|
.single()
|
104
134
|
.empty(null)
|
105
135
|
.default([])
|
136
|
+
.description(
|
137
|
+
'Array of allowed file types. Can be provided as a single value or an array.'
|
138
|
+
)
|
139
|
+
|
106
140
|
export const documentTypesSchema = Joi.array()
|
107
141
|
.items(Joi.string())
|
108
142
|
.single()
|
109
143
|
.empty(null)
|
110
144
|
.default([])
|
145
|
+
.description(
|
146
|
+
'Array of allowed document types. Can be provided as a single value or an array.'
|
147
|
+
)
|
148
|
+
|
111
149
|
export const imageTypesSchema = Joi.array()
|
112
150
|
.items(Joi.string())
|
113
151
|
.single()
|
114
152
|
.empty(null)
|
115
153
|
.default([])
|
154
|
+
.description(
|
155
|
+
'Array of allowed image types. Can be provided as a single value or an array.'
|
156
|
+
)
|
157
|
+
|
116
158
|
export const tabularDataTypesSchema = Joi.array()
|
117
159
|
.items(Joi.string())
|
118
160
|
.single()
|
119
161
|
.empty(null)
|
120
162
|
.default([])
|
163
|
+
export const enhancedActionSchema = Joi.string()
|
164
|
+
.trim()
|
165
|
+
.optional()
|
166
|
+
.allow('')
|
167
|
+
.description('Action field that can include enhanced functionality')
|
168
|
+
|
169
|
+
export const radioIdSchema = Joi.string()
|
170
|
+
.trim()
|
171
|
+
.optional()
|
172
|
+
.allow('')
|
173
|
+
.description('Unique identifier for radio options')
|
174
|
+
|
175
|
+
export const radioLabelSchema = Joi.string()
|
176
|
+
.trim()
|
177
|
+
.required()
|
178
|
+
.description('The visible text shown next to radio options')
|
179
|
+
|
180
|
+
export const radioHintSchema = Joi.string()
|
181
|
+
.trim()
|
182
|
+
.optional()
|
183
|
+
.allow('')
|
184
|
+
.description(
|
185
|
+
'Optional hint text displayed with radio buttons to provide additional guidance'
|
186
|
+
)
|
187
|
+
|
188
|
+
export const radioValueSchema = Joi.string()
|
189
|
+
.trim()
|
190
|
+
.optional()
|
191
|
+
.allow('')
|
192
|
+
.description(
|
193
|
+
'Array of allowed tabular data types. Can be provided as a single value or an array.'
|
194
|
+
)
|
195
|
+
|
196
|
+
export const shortDescriptionSchema = Joi.string()
|
197
|
+
.trim()
|
198
|
+
.required()
|
199
|
+
.description('Brief description of the question for internal use')
|
200
|
+
|
201
|
+
export const pageHeadingAndGuidanceSchema = Joi.string()
|
202
|
+
.trim()
|
203
|
+
.optional()
|
204
|
+
.description('Combined heading and guidance for the page')
|
205
|
+
|
206
|
+
export const pageHeadingSchema = Joi.string()
|
207
|
+
.trim()
|
208
|
+
.required()
|
209
|
+
.description('Main heading displayed at the top of the page')
|
210
|
+
|
211
|
+
export const guidanceTextSchema = Joi.string()
|
212
|
+
.trim()
|
213
|
+
.description('Guidance text to assist users in completing the page')
|
214
|
+
|
215
|
+
export const needDeclarationSchema = Joi.string()
|
216
|
+
.trim()
|
217
|
+
.required()
|
218
|
+
.description('Whether a declaration is needed')
|
219
|
+
|
220
|
+
export const declarationTextSchema = Joi.string()
|
221
|
+
.trim()
|
222
|
+
.required()
|
223
|
+
.description('Text of the declaration that users must agree to')
|
224
|
+
|
225
|
+
export const minSchema = Joi.number()
|
226
|
+
.empty('')
|
227
|
+
.integer()
|
228
|
+
.description('Minimum value for numeric inputs')
|
229
|
+
|
230
|
+
export const maxSchema = Joi.number()
|
231
|
+
.empty('')
|
232
|
+
.integer()
|
233
|
+
.description('Maximum value for numeric inputs')
|
234
|
+
|
235
|
+
export const minLengthSchema = Joi.number()
|
236
|
+
.empty('')
|
237
|
+
.integer()
|
238
|
+
.min(1)
|
239
|
+
.description('Minimum character length for text inputs')
|
240
|
+
|
241
|
+
export const maxLengthSchema = Joi.number()
|
242
|
+
.empty('')
|
243
|
+
.integer()
|
244
|
+
.min(1)
|
245
|
+
.description('Maximum character length for text inputs')
|
246
|
+
|
247
|
+
export const maxFutureSchema = Joi.number()
|
248
|
+
.empty('')
|
249
|
+
.integer()
|
250
|
+
.min(1)
|
251
|
+
.description('Maximum days in the future allowed for date inputs')
|
252
|
+
|
253
|
+
export const maxPastSchema = Joi.number()
|
254
|
+
.empty('')
|
255
|
+
.integer()
|
256
|
+
.min(1)
|
257
|
+
.description('Maximum days in the past allowed for date inputs')
|
258
|
+
|
259
|
+
export const precisionSchema = Joi.number()
|
260
|
+
.empty('')
|
261
|
+
.integer()
|
262
|
+
.min(1)
|
263
|
+
.description('Decimal precision for numeric inputs')
|
264
|
+
|
265
|
+
export const prefixSchema = Joi.string()
|
266
|
+
.trim()
|
267
|
+
.optional()
|
268
|
+
.allow('')
|
269
|
+
.description('Text to display before the input (e.g., £)')
|
270
|
+
|
271
|
+
export const regexSchema = Joi.string()
|
272
|
+
.optional()
|
273
|
+
.allow('')
|
274
|
+
.description('Regular expression pattern for validation')
|
275
|
+
|
276
|
+
export const rowsSchema = Joi.number()
|
277
|
+
.empty('')
|
278
|
+
.integer()
|
279
|
+
.min(1)
|
280
|
+
.description('Number of rows for multiline text fields')
|
281
|
+
|
282
|
+
export const suffixSchema = Joi.string()
|
283
|
+
.trim()
|
284
|
+
.optional()
|
285
|
+
.allow('')
|
286
|
+
.description('Text to display after the input (e.g., kg)')
|
287
|
+
|
288
|
+
export const classesSchema = Joi.string()
|
289
|
+
.trim()
|
290
|
+
.optional()
|
291
|
+
.allow('')
|
292
|
+
.description('Custom CSS classes to apply to the component')
|
121
293
|
|
122
294
|
export const questionDetailsFullSchema = {
|
123
295
|
classesSchema,
|
124
296
|
documentTypesSchema,
|
297
|
+
enhancedActionSchema,
|
125
298
|
exactFilesSchema,
|
126
299
|
fileTypesSchema,
|
127
300
|
hintTextSchema,
|
@@ -140,6 +313,10 @@ export const questionDetailsFullSchema = {
|
|
140
313
|
questionOptionalSchema,
|
141
314
|
questionSchema,
|
142
315
|
questionTypeFullSchema,
|
316
|
+
radioHintSchema,
|
317
|
+
radioIdSchema,
|
318
|
+
radioLabelSchema,
|
319
|
+
radioValueSchema,
|
143
320
|
regexSchema,
|
144
321
|
rowsSchema,
|
145
322
|
shortDescriptionSchema,
|
@@ -159,6 +336,7 @@ export const formEditorInputPageKeys = {
|
|
159
336
|
export const formEditorInputPageSchema = Joi.object<FormEditorInputPage>()
|
160
337
|
.keys(formEditorInputPageKeys)
|
161
338
|
.required()
|
339
|
+
.description('Input schema for creating a new page in the form editor')
|
162
340
|
|
163
341
|
export const formEditorInputheckAnswersSettingsKeys = {
|
164
342
|
declarationText: shortDescriptionSchema
|
@@ -172,6 +350,7 @@ export const formEditorInputCheckAnswersSettingSchema =
|
|
172
350
|
Joi.object<FormEditorInputCheckAnswersSettings>()
|
173
351
|
.keys(formEditorInputheckAnswersSettingsKeys)
|
174
352
|
.required()
|
353
|
+
.description('Configuration for the check-answers page')
|
175
354
|
|
176
355
|
export const formEditorInputQuestionKeys = {
|
177
356
|
question: questionSchema,
|
@@ -188,6 +367,9 @@ export const formEditorInputQuestionSchema =
|
|
188
367
|
Joi.object<FormEditorInputQuestion>()
|
189
368
|
.keys(formEditorInputQuestionKeys)
|
190
369
|
.required()
|
370
|
+
.description(
|
371
|
+
'Input schema for creating or updating a question in the form editor'
|
372
|
+
)
|
191
373
|
|
192
374
|
export const formEditorInputPageSettingsKeys = {
|
193
375
|
pageHeadingAndGuidance: pageHeadingAndGuidanceSchema,
|
@@ -203,3 +385,4 @@ export const formEditorInputPageSettingsSchema =
|
|
203
385
|
Joi.object<FormEditorInputPageSettings>()
|
204
386
|
.keys(formEditorInputPageSettingsKeys)
|
205
387
|
.required()
|
388
|
+
.description('Settings for page content and display in the form editor')
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import { type ComponentDef } from '~/src/components/types.js'
|
2
|
+
|
1
3
|
/**
|
2
4
|
* Interface for `FormEditor` Joi schema
|
3
5
|
*/
|
@@ -171,6 +173,36 @@ export interface FormEditor {
|
|
171
173
|
* The types of tabular data files for upload
|
172
174
|
*/
|
173
175
|
tabularDataTypes: string[]
|
176
|
+
|
177
|
+
/**
|
178
|
+
* The action required from within a sub-section
|
179
|
+
*/
|
180
|
+
enhancedAction: string
|
181
|
+
|
182
|
+
/**
|
183
|
+
* Placeholder for inserted section to handle adding/editing radios or checkboxes
|
184
|
+
*/
|
185
|
+
radiosOrCheckboxes: string
|
186
|
+
|
187
|
+
/**
|
188
|
+
* The unique id of the radio item
|
189
|
+
*/
|
190
|
+
radioId: string
|
191
|
+
|
192
|
+
/**
|
193
|
+
* The display text of the radio item
|
194
|
+
*/
|
195
|
+
radioLabel: string
|
196
|
+
|
197
|
+
/**
|
198
|
+
* The hint of the radio item
|
199
|
+
*/
|
200
|
+
radioHint: string
|
201
|
+
|
202
|
+
/**
|
203
|
+
* The value of the radio item
|
204
|
+
*/
|
205
|
+
radioValue: string
|
174
206
|
}
|
175
207
|
|
176
208
|
export type FormEditorInputPage = Pick<
|
@@ -210,6 +242,11 @@ export type FormEditorInputQuestion = Pick<
|
|
210
242
|
| 'documentTypes'
|
211
243
|
| 'imageTypes'
|
212
244
|
| 'tabularDataTypes'
|
245
|
+
| 'enhancedAction'
|
246
|
+
| 'radioId'
|
247
|
+
| 'radioLabel'
|
248
|
+
| 'radioHint'
|
249
|
+
| 'radioValue'
|
213
250
|
>
|
214
251
|
|
215
252
|
export type FormEditorInputPageSettings = Pick<
|
@@ -222,6 +259,36 @@ export type FormEditorInputGuidancePage = Pick<
|
|
222
259
|
'pageHeading' | 'guidanceText'
|
223
260
|
>
|
224
261
|
|
262
|
+
export type FormEditorInputQuestionDetails = Pick<
|
263
|
+
FormEditorInputQuestion,
|
264
|
+
| 'question'
|
265
|
+
| 'hintText'
|
266
|
+
| 'shortDescription'
|
267
|
+
| 'questionOptional'
|
268
|
+
| 'questionType'
|
269
|
+
| 'fileTypes'
|
270
|
+
| 'documentTypes'
|
271
|
+
| 'imageTypes'
|
272
|
+
| 'tabularDataTypes'
|
273
|
+
| 'enhancedAction'
|
274
|
+
| 'radioId'
|
275
|
+
| 'radioLabel'
|
276
|
+
| 'radioHint'
|
277
|
+
| 'radioValue'
|
278
|
+
>
|
279
|
+
|
280
|
+
export interface EnhancedActionState {
|
281
|
+
questionDetails: Partial<ComponentDef>
|
282
|
+
state: {
|
283
|
+
radioId?: string
|
284
|
+
radioLabel?: string
|
285
|
+
radioHint?: string
|
286
|
+
radioValue?: string
|
287
|
+
expanded?: boolean
|
288
|
+
}
|
289
|
+
listItems: { label?: string; hint?: string; value?: string; id?: string }[]
|
290
|
+
}
|
291
|
+
|
225
292
|
export interface GovukField {
|
226
293
|
id?: string
|
227
294
|
name?: string
|
@@ -236,6 +303,7 @@ export interface GovukField {
|
|
236
303
|
items?: { text?: string; value?: string; checked?: boolean }[]
|
237
304
|
rows?: number
|
238
305
|
type?: string
|
306
|
+
customTemplate?: string
|
239
307
|
}
|
240
308
|
|
241
309
|
export interface FormEditorGovukField {
|
@@ -247,6 +315,7 @@ export interface FormEditorGovukField {
|
|
247
315
|
documentTypes?: GovukField
|
248
316
|
imageTypes?: GovukField
|
249
317
|
tabularDataTypes?: GovukField
|
318
|
+
radiosOrCheckboxes?: GovukField
|
250
319
|
errorMessage?: { text: string }
|
251
320
|
}
|
252
321
|
|
@@ -5,8 +5,17 @@ import { pageSchema } from '~/src/index.js'
|
|
5
5
|
|
6
6
|
export const patchPageSchema = Joi.object<PatchPageFields>()
|
7
7
|
.keys({
|
8
|
-
title: pageSchema
|
9
|
-
|
8
|
+
title: pageSchema
|
9
|
+
.extract('title')
|
10
|
+
.optional()
|
11
|
+
.description('New title to set for the page'),
|
12
|
+
path: pageSchema
|
13
|
+
.extract('path')
|
14
|
+
.optional()
|
15
|
+
.description('New URL path to set for the page')
|
10
16
|
})
|
11
17
|
.required()
|
12
18
|
.min(1)
|
19
|
+
.description(
|
20
|
+
'Schema for partially updating a page, requiring at least one field to be provided'
|
21
|
+
)
|
@@ -22,30 +22,63 @@ export const organisations = [
|
|
22
22
|
'Veterinary Medicines Directorate – VMD'
|
23
23
|
]
|
24
24
|
|
25
|
-
export const idSchema = Joi.string()
|
26
|
-
|
25
|
+
export const idSchema = Joi.string()
|
26
|
+
.hex()
|
27
|
+
.length(24)
|
28
|
+
.required()
|
29
|
+
.description(
|
30
|
+
'Unique identifier for the form, 24-character hexadecimal string'
|
31
|
+
)
|
32
|
+
|
33
|
+
export const titleSchema = Joi.string()
|
34
|
+
.max(250)
|
35
|
+
.trim()
|
36
|
+
.required()
|
37
|
+
.description('Title of the form, displayed to users')
|
38
|
+
|
27
39
|
export const slugSchema = Joi.string()
|
28
40
|
.pattern(/^[a-z0-9-]+$/, { name: 'letters, numbers and hyphens only' })
|
29
41
|
.required()
|
42
|
+
.description('URL-friendly identifier used in form paths')
|
30
43
|
|
31
44
|
export const organisationSchema = Joi.string()
|
32
45
|
.valid(...organisations)
|
33
46
|
.required()
|
47
|
+
.description('Defra organisation responsible for the form')
|
48
|
+
|
49
|
+
export const teamNameSchema = Joi.string()
|
50
|
+
.max(100)
|
51
|
+
.trim()
|
52
|
+
.required()
|
53
|
+
.description('Name of the team responsible for the form')
|
34
54
|
|
35
|
-
export const teamNameSchema = Joi.string().max(100).trim().required()
|
36
55
|
export const teamEmailSchema = Joi.string()
|
37
56
|
.email({ tlds: { allow: ['uk'] } })
|
38
57
|
.trim()
|
39
58
|
.required()
|
59
|
+
.description('Contact email for the team responsible for the form')
|
60
|
+
|
61
|
+
export const phoneSchema = Joi.string()
|
62
|
+
.trim()
|
63
|
+
.description('Phone number for form-related inquiries')
|
64
|
+
|
65
|
+
export const emailAddressSchema = Joi.string()
|
66
|
+
.email()
|
67
|
+
.trim()
|
68
|
+
.required()
|
69
|
+
.description('Email address for form-related inquiries')
|
40
70
|
|
41
|
-
export const
|
71
|
+
export const emailResponseTimeSchema = Joi.string()
|
72
|
+
.trim()
|
73
|
+
.required()
|
74
|
+
.description('Expected response time for email inquiries')
|
42
75
|
|
43
|
-
export const
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
76
|
+
export const emailSchema = Joi.object<FormMetadataContactEmail>()
|
77
|
+
.keys({
|
78
|
+
address: emailAddressSchema,
|
79
|
+
responseTime: emailResponseTimeSchema
|
80
|
+
})
|
81
|
+
.description('Email contact details including response expectations')
|
49
82
|
|
50
83
|
export const onlineUrlSchema = Joi.string()
|
51
84
|
.uri({
|
@@ -53,34 +86,61 @@ export const onlineUrlSchema = Joi.string()
|
|
53
86
|
})
|
54
87
|
.trim()
|
55
88
|
.required()
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
89
|
+
.description('URL for online contact method')
|
90
|
+
|
91
|
+
export const onlineTextSchema = Joi.string()
|
92
|
+
.trim()
|
93
|
+
.required()
|
94
|
+
.description('Descriptive text for the online contact link')
|
61
95
|
|
62
|
-
export const
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
})
|
96
|
+
export const onlineSchema = Joi.object<FormMetadataContactOnline>()
|
97
|
+
.keys({
|
98
|
+
url: onlineUrlSchema,
|
99
|
+
text: onlineTextSchema
|
100
|
+
})
|
101
|
+
.description('Online contact details with URL and descriptive text')
|
67
102
|
|
68
|
-
export const
|
103
|
+
export const contactSchema = Joi.object<FormMetadataContact>()
|
104
|
+
.keys({
|
105
|
+
phone: phoneSchema,
|
106
|
+
email: emailSchema,
|
107
|
+
online: onlineSchema
|
108
|
+
})
|
109
|
+
.description('Complete contact information for form-related inquiries')
|
110
|
+
|
111
|
+
export const submissionGuidanceSchema = Joi.string()
|
112
|
+
.trim()
|
113
|
+
.description('Guidance text shown to users when submitting the form')
|
69
114
|
|
70
115
|
export const privacyNoticeUrlSchema = Joi.string()
|
71
116
|
.uri({
|
72
117
|
scheme: ['http', 'https']
|
73
118
|
})
|
74
119
|
.trim()
|
120
|
+
.description('URL to the privacy notice for this form')
|
75
121
|
|
76
122
|
export const notificationEmailAddressSchema = Joi.string()
|
77
123
|
.email({ tlds: { allow: ['uk'] } })
|
78
124
|
.trim()
|
79
125
|
.pattern(/\.gov\.uk$|\.org\.uk$/)
|
126
|
+
.description(
|
127
|
+
'Email address to receive form submission notifications, must be a .gov.uk or .org.uk address'
|
128
|
+
)
|
129
|
+
|
130
|
+
export const authoredAtSchema = Joi.date()
|
131
|
+
.iso()
|
132
|
+
.required()
|
133
|
+
.description('ISO format timestamp of when an action occurred')
|
80
134
|
|
81
|
-
export const
|
82
|
-
|
83
|
-
|
135
|
+
export const authorIdSchema = Joi.string()
|
136
|
+
.trim()
|
137
|
+
.required()
|
138
|
+
.description('Unique identifier for the author')
|
139
|
+
|
140
|
+
export const authorDisplayNameSchema = Joi.string()
|
141
|
+
.trim()
|
142
|
+
.required()
|
143
|
+
.description('Human-readable name of the author')
|
84
144
|
|
85
145
|
export const formMetadataInputKeys = {
|
86
146
|
title: titleSchema,
|
@@ -100,6 +160,7 @@ export const formMetadataInputKeys = {
|
|
100
160
|
export const formMetadataInputSchema = Joi.object<FormMetadataInput>()
|
101
161
|
.keys(formMetadataInputKeys)
|
102
162
|
.required()
|
163
|
+
.description('Input data for creating or updating form metadata')
|
103
164
|
|
104
165
|
/**
|
105
166
|
* Joi schema for `FormMetadataAuthor` interface
|
@@ -111,29 +172,46 @@ export const formMetadataAuthorSchema = Joi.object<FormMetadataAuthor>()
|
|
111
172
|
displayName: authorDisplayNameSchema
|
112
173
|
})
|
113
174
|
.required()
|
175
|
+
.description('Information about the author of a form or form change')
|
114
176
|
|
115
177
|
/**
|
116
178
|
* Joi schema for `FormMetadataState` interface
|
117
179
|
* @see {@link FormMetadataState}
|
118
180
|
*/
|
119
|
-
export const formMetadataStateSchema = Joi.object<FormMetadataState>()
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
181
|
+
export const formMetadataStateSchema = Joi.object<FormMetadataState>()
|
182
|
+
.keys({
|
183
|
+
createdAt: authoredAtSchema.description(
|
184
|
+
'When this version was first created'
|
185
|
+
),
|
186
|
+
createdBy: formMetadataAuthorSchema.description('Who created this version'),
|
187
|
+
updatedAt: authoredAtSchema.description(
|
188
|
+
'When this version was last updated'
|
189
|
+
),
|
190
|
+
updatedBy: formMetadataAuthorSchema.description(
|
191
|
+
'Who last updated this version'
|
192
|
+
)
|
193
|
+
})
|
194
|
+
.description('Metadata about a specific version state (draft or live)')
|
125
195
|
|
126
196
|
/**
|
127
197
|
* Joi schema for `FormMetadata` interface
|
128
198
|
* @see {@link FormMetadata}
|
129
199
|
*/
|
130
|
-
export const formMetadataSchema = formMetadataInputSchema
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
200
|
+
export const formMetadataSchema = formMetadataInputSchema
|
201
|
+
.append<FormMetadata>({
|
202
|
+
id: idSchema,
|
203
|
+
slug: slugSchema,
|
204
|
+
draft: formMetadataStateSchema.description(
|
205
|
+
'Metadata for the draft version'
|
206
|
+
),
|
207
|
+
live: formMetadataStateSchema.description(
|
208
|
+
'Metadata for the published version'
|
209
|
+
),
|
210
|
+
createdAt: authoredAtSchema.description('When the form was first created'),
|
211
|
+
createdBy: formMetadataAuthorSchema.description('Who created the form'),
|
212
|
+
updatedAt: authoredAtSchema.description('When the form was last updated'),
|
213
|
+
updatedBy: formMetadataAuthorSchema.description('Who last updated the form')
|
214
|
+
})
|
215
|
+
.description(
|
216
|
+
'Complete metadata for a form, including version information and authoring details'
|
217
|
+
)
|