@defra/forms-engine-plugin 4.3.0 → 4.4.0
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/.public/javascripts/application.min.js.map +1 -1
- package/.public/javascripts/shared.min.js +1 -1
- package/.public/javascripts/shared.min.js.map +1 -1
- package/.public/javascripts/vendor/accessible-autocomplete.min.js.map +1 -1
- package/.public/stylesheets/application.min.css +1 -1
- package/.public/stylesheets/application.min.css.map +1 -1
- package/.server/client/javascripts/geospatial-map.d.ts +189 -0
- package/.server/client/javascripts/geospatial-map.js +1068 -0
- package/.server/client/javascripts/geospatial-map.js.map +1 -0
- package/.server/client/javascripts/location-map.d.ts +6 -91
- package/.server/client/javascripts/location-map.js +78 -385
- package/.server/client/javascripts/location-map.js.map +1 -1
- package/.server/client/javascripts/map.d.ts +199 -0
- package/.server/client/javascripts/map.js +384 -0
- package/.server/client/javascripts/map.js.map +1 -0
- package/.server/client/javascripts/shared.d.ts +3 -1
- package/.server/client/javascripts/shared.js +3 -1
- package/.server/client/javascripts/shared.js.map +1 -1
- package/.server/client/stylesheets/shared.scss +7 -0
- package/.server/server/plugins/engine/components/ComponentBase.d.ts +1 -0
- package/.server/server/plugins/engine/components/ComponentBase.js +2 -0
- package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
- package/.server/server/plugins/engine/components/FormComponent.d.ts +9 -1
- package/.server/server/plugins/engine/components/FormComponent.js +22 -0
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/GeospatialField.d.ts +77 -0
- package/.server/server/plugins/engine/components/GeospatialField.js +102 -0
- package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -0
- package/.server/server/plugins/engine/components/helpers/__stubs__/geospatial.d.ts +3 -0
- package/.server/server/plugins/engine/components/helpers/__stubs__/geospatial.js +63 -0
- package/.server/server/plugins/engine/components/helpers/__stubs__/geospatial.js.map +1 -0
- package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
- package/.server/server/plugins/engine/components/helpers/components.js +7 -0
- package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +6 -0
- package/.server/server/plugins/engine/components/helpers/geospatial.js +71 -0
- package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -0
- package/.server/server/plugins/engine/components/helpers/geospatial.test.js +42 -0
- package/.server/server/plugins/engine/components/helpers/geospatial.test.js.map +1 -0
- package/.server/server/plugins/engine/components/index.d.ts +1 -0
- package/.server/server/plugins/engine/components/index.js +1 -0
- package/.server/server/plugins/engine/components/index.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/PageController.d.ts +1 -0
- package/.server/server/plugins/engine/pageControllers/PageController.js +2 -0
- package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js +13 -1
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.js +2 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +63 -2
- package/.server/server/plugins/engine/types.js +33 -0
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/plugins/engine/views/components/geospatialfield.html +7 -0
- package/.server/server/plugins/nunjucks/context.test.js.map +1 -1
- package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
- package/.server/server/routes/types.js.map +1 -1
- package/.server/server/services/cacheService.js +3 -0
- package/.server/server/services/cacheService.js.map +1 -1
- package/package.json +9 -5
- package/src/client/javascripts/geospatial-map.js +1023 -0
- package/src/client/javascripts/location-map.js +94 -390
- package/src/client/javascripts/map.js +389 -0
- package/src/client/javascripts/shared.js +3 -1
- package/src/client/stylesheets/shared.scss +7 -0
- package/src/server/plugins/engine/components/ComponentBase.ts +2 -0
- package/src/server/plugins/engine/components/FormComponent.ts +29 -0
- package/src/server/plugins/engine/components/GeospatialField.test.ts +380 -0
- package/src/server/plugins/engine/components/GeospatialField.ts +145 -0
- package/src/server/plugins/engine/components/helpers/__stubs__/geospatial.ts +85 -0
- package/src/server/plugins/engine/components/helpers/components.test.ts +44 -0
- package/src/server/plugins/engine/components/helpers/components.ts +10 -0
- package/src/server/plugins/engine/components/helpers/geospatial.test.js +55 -0
- package/src/server/plugins/engine/components/helpers/geospatial.ts +93 -0
- package/src/server/plugins/engine/components/index.ts +1 -0
- package/src/server/plugins/engine/pageControllers/PageController.ts +2 -0
- package/src/server/plugins/engine/pageControllers/helpers/submission.test.ts +74 -0
- package/src/server/plugins/engine/pageControllers/helpers/submission.ts +17 -1
- package/src/server/plugins/engine/pageControllers/validationOptions.ts +3 -1
- package/src/server/plugins/engine/types.ts +77 -4
- package/src/server/plugins/engine/views/components/geospatialfield.html +7 -0
- package/src/server/plugins/nunjucks/context.test.js +2 -3
- package/src/server/routes/types.ts +4 -2
- package/src/server/services/cacheService.ts +2 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { validState } from '~/src/server/plugins/engine/components/helpers/__stubs__/geospatial.js'
|
|
2
|
+
import { geospatialSchema } from '~/src/server/plugins/engine/components/helpers/geospatial.js'
|
|
3
|
+
|
|
4
|
+
describe('Geospatial validation helpers', () => {
|
|
5
|
+
test('it should not have errors for valid geojson object', () => {
|
|
6
|
+
const result = geospatialSchema.validate(validState)
|
|
7
|
+
|
|
8
|
+
expect(result.error).toBeUndefined()
|
|
9
|
+
expect(result.value).toBeDefined()
|
|
10
|
+
expect(result.value).toHaveLength(4)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test('it should not have errors for valid geojson string', () => {
|
|
14
|
+
const result = geospatialSchema.validate(JSON.stringify(validState))
|
|
15
|
+
|
|
16
|
+
expect(result.error).toBeUndefined()
|
|
17
|
+
expect(result.value).toBeDefined()
|
|
18
|
+
expect(result.value).toHaveLength(4)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('it should have errors for invalid json string', () => {
|
|
22
|
+
const result = geospatialSchema.validate('{')
|
|
23
|
+
|
|
24
|
+
expect(result.error).toBeDefined()
|
|
25
|
+
expect(result.value).toBe('{')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('it should have errors for invalid geojson string', () => {
|
|
29
|
+
const result = geospatialSchema.validate('[')
|
|
30
|
+
|
|
31
|
+
expect(result.error).toBeDefined()
|
|
32
|
+
expect(result.value).toBe('[')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('it should validate an empty array', () => {
|
|
36
|
+
const result = geospatialSchema.validate('[]')
|
|
37
|
+
|
|
38
|
+
expect(result.error).toBeUndefined()
|
|
39
|
+
expect(result.value).toEqual([])
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('it should not validate an empty object', () => {
|
|
43
|
+
const result = geospatialSchema.validate('{}')
|
|
44
|
+
|
|
45
|
+
expect(result.error).toBeDefined()
|
|
46
|
+
expect(result.value).toBeUndefined()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('it should validate an empty string', () => {
|
|
50
|
+
const result = geospatialSchema.validate('')
|
|
51
|
+
|
|
52
|
+
expect(result.error).toBeDefined()
|
|
53
|
+
expect(result.value).toBeUndefined()
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import Bourne from '@hapi/bourne'
|
|
2
|
+
import JoiBase from 'joi'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type Coordinates,
|
|
6
|
+
type Feature,
|
|
7
|
+
type FeatureProperties,
|
|
8
|
+
type Geometry
|
|
9
|
+
} from '~/src/server/plugins/engine/types.js'
|
|
10
|
+
|
|
11
|
+
const Joi = JoiBase.extend({
|
|
12
|
+
type: 'array',
|
|
13
|
+
base: JoiBase.array(),
|
|
14
|
+
messages: {
|
|
15
|
+
'object.invalidjson': '{{#label}} must be a valid json array string'
|
|
16
|
+
},
|
|
17
|
+
coerce: {
|
|
18
|
+
from: 'string',
|
|
19
|
+
method(value, helpers) {
|
|
20
|
+
if (typeof value === 'string') {
|
|
21
|
+
if (value.trim() === '') {
|
|
22
|
+
return {
|
|
23
|
+
value: undefined
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
29
|
+
return { value: Bourne.parse(value) }
|
|
30
|
+
} catch {
|
|
31
|
+
const result = {
|
|
32
|
+
value,
|
|
33
|
+
errors: [helpers.error('object.invalidjson')]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
return {
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
41
|
+
value
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}) as JoiBase.Root
|
|
47
|
+
|
|
48
|
+
const coordinatesSchema = Joi.array<Coordinates[]>()
|
|
49
|
+
.items(Joi.number().required(), Joi.number().required())
|
|
50
|
+
.required()
|
|
51
|
+
|
|
52
|
+
const featurePropertiesSchema = Joi.object<FeatureProperties>()
|
|
53
|
+
.keys({
|
|
54
|
+
description: Joi.string().required(),
|
|
55
|
+
coordinateGridReference: Joi.string().required(),
|
|
56
|
+
centroidGridReference: Joi.string().required()
|
|
57
|
+
})
|
|
58
|
+
.required()
|
|
59
|
+
|
|
60
|
+
const featureGeometrySchema = Joi.object<Geometry>().keys({
|
|
61
|
+
type: Joi.string().valid('Point', 'LineString', 'Polygon').required(),
|
|
62
|
+
coordinates: Joi.array()
|
|
63
|
+
.when('type', {
|
|
64
|
+
switch: [
|
|
65
|
+
{ is: 'Point', then: coordinatesSchema },
|
|
66
|
+
{
|
|
67
|
+
is: 'LineString',
|
|
68
|
+
then: Joi.array().items(coordinatesSchema).min(2)
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
is: 'Polygon',
|
|
72
|
+
then: Joi.array().items(Joi.array().items(coordinatesSchema).min(3))
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
})
|
|
76
|
+
.required()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
const featureSchema = Joi.object<Feature>().keys({
|
|
80
|
+
id: Joi.string().required(),
|
|
81
|
+
type: Joi.string().valid('Feature').required(),
|
|
82
|
+
properties: featurePropertiesSchema,
|
|
83
|
+
geometry: featureGeometrySchema
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
export const geospatialSchema = Joi.array<Feature[]>()
|
|
87
|
+
.items(featureSchema)
|
|
88
|
+
.unique('id')
|
|
89
|
+
.required()
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @import { CustomHelpers } from 'joi'
|
|
93
|
+
*/
|
|
@@ -30,3 +30,4 @@ export { NationalGridFieldNumberField } from '~/src/server/plugins/engine/compon
|
|
|
30
30
|
export { LatLongField } from '~/src/server/plugins/engine/components/LatLongField.js'
|
|
31
31
|
export { HiddenField } from '~/src/server/plugins/engine/components/HiddenField.js'
|
|
32
32
|
export { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'
|
|
33
|
+
export { GeospatialField } from '~/src/server/plugins/engine/components/GeospatialField.js'
|
|
@@ -37,6 +37,7 @@ export class PageController {
|
|
|
37
37
|
name?: string
|
|
38
38
|
model: FormModel
|
|
39
39
|
pageDef: Page
|
|
40
|
+
id?: string
|
|
40
41
|
title: string
|
|
41
42
|
section?: Section
|
|
42
43
|
condition?: ExecutableCondition
|
|
@@ -52,6 +53,7 @@ export class PageController {
|
|
|
52
53
|
this.name = def.name
|
|
53
54
|
this.model = model
|
|
54
55
|
this.pageDef = pageDef
|
|
56
|
+
this.id = pageDef.id
|
|
55
57
|
this.title = pageDef.title
|
|
56
58
|
this.events = pageDef.events
|
|
57
59
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { GeospatialField } from '~/src/server/plugins/engine/components/GeospatialField.js'
|
|
1
2
|
import { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'
|
|
2
3
|
import { TextField } from '~/src/server/plugins/engine/components/TextField.js'
|
|
4
|
+
import { validSingleState } from '~/src/server/plugins/engine/components/helpers/__stubs__/geospatial.js'
|
|
3
5
|
import { type DetailItemField } from '~/src/server/plugins/engine/models/types.js'
|
|
4
6
|
import {
|
|
5
7
|
buildMainRecords,
|
|
@@ -242,6 +244,34 @@ describe('Submission helpers', () => {
|
|
|
242
244
|
|
|
243
245
|
expect(result).toEqual([])
|
|
244
246
|
})
|
|
247
|
+
|
|
248
|
+
it('should JSON stringify GeospatialField', () => {
|
|
249
|
+
const mockGeospatialField = Object.create(GeospatialField.prototype)
|
|
250
|
+
mockGeospatialField.name = 'geospatial'
|
|
251
|
+
|
|
252
|
+
const items = [
|
|
253
|
+
{
|
|
254
|
+
name: 'geospatial',
|
|
255
|
+
label: 'Site features',
|
|
256
|
+
field: mockGeospatialField,
|
|
257
|
+
state: {
|
|
258
|
+
geospatial: validSingleState
|
|
259
|
+
} as FormSubmissionState
|
|
260
|
+
}
|
|
261
|
+
] as unknown as DetailItemField[]
|
|
262
|
+
|
|
263
|
+
const result = buildMainRecords(items)
|
|
264
|
+
|
|
265
|
+
expect(result).toHaveLength(1)
|
|
266
|
+
expect(result).toEqual([
|
|
267
|
+
{
|
|
268
|
+
name: 'geospatial',
|
|
269
|
+
title: 'Site features',
|
|
270
|
+
value:
|
|
271
|
+
'[{"type":"Feature","properties":{"description":"My farm house","coordinateGridReference":"ST 00001","centroidGridReference":"ST 00001"},"geometry":{"coordinates":[-2.5723699109417737,53.2380485215034],"type":"Point"},"id":"a"}]'
|
|
272
|
+
}
|
|
273
|
+
])
|
|
274
|
+
})
|
|
245
275
|
})
|
|
246
276
|
|
|
247
277
|
describe('buildRepeaterRecords', () => {
|
|
@@ -295,5 +325,49 @@ describe('Submission helpers', () => {
|
|
|
295
325
|
expect(result[0].title).toBe('Addresses')
|
|
296
326
|
expect(result[0].value).toHaveLength(1)
|
|
297
327
|
})
|
|
328
|
+
|
|
329
|
+
it('should JSON stringify GeospatialField', () => {
|
|
330
|
+
const mockGeospatialField = Object.create(GeospatialField.prototype)
|
|
331
|
+
mockGeospatialField.name = 'geospatial'
|
|
332
|
+
|
|
333
|
+
const items = [
|
|
334
|
+
{
|
|
335
|
+
name: 'features',
|
|
336
|
+
label: 'Site features repeater',
|
|
337
|
+
subItems: [
|
|
338
|
+
[
|
|
339
|
+
{
|
|
340
|
+
name: 'geospatial',
|
|
341
|
+
label: 'Site features',
|
|
342
|
+
field: mockGeospatialField,
|
|
343
|
+
state: {
|
|
344
|
+
geospatial: validSingleState
|
|
345
|
+
} as FormSubmissionState
|
|
346
|
+
} as unknown as DetailItemField[]
|
|
347
|
+
]
|
|
348
|
+
]
|
|
349
|
+
}
|
|
350
|
+
] as unknown as DetailItemField[]
|
|
351
|
+
|
|
352
|
+
const result = buildRepeaterRecords(items)
|
|
353
|
+
|
|
354
|
+
expect(result).toHaveLength(1)
|
|
355
|
+
expect(result).toEqual([
|
|
356
|
+
{
|
|
357
|
+
name: 'features',
|
|
358
|
+
title: 'Site features repeater',
|
|
359
|
+
value: [
|
|
360
|
+
[
|
|
361
|
+
{
|
|
362
|
+
name: 'geospatial',
|
|
363
|
+
title: 'Site features',
|
|
364
|
+
value:
|
|
365
|
+
'[{"type":"Feature","properties":{"description":"My farm house","coordinateGridReference":"ST 00001","centroidGridReference":"ST 00001"},"geometry":{"coordinates":[-2.5723699109417737,53.2380485215034],"type":"Point"},"id":"a"}]'
|
|
366
|
+
}
|
|
367
|
+
]
|
|
368
|
+
]
|
|
369
|
+
}
|
|
370
|
+
])
|
|
371
|
+
})
|
|
298
372
|
})
|
|
299
373
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type SubmitPayload } from '@defra/forms-model'
|
|
2
2
|
|
|
3
|
+
import { GeospatialField } from '~/src/server/plugins/engine/components/GeospatialField.js'
|
|
3
4
|
import { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'
|
|
4
5
|
import { getAnswer } from '~/src/server/plugins/engine/components/helpers/components.js'
|
|
5
6
|
import {
|
|
@@ -32,6 +33,14 @@ export function buildMainRecords(items: DetailItem[]): SubmitRecord[] {
|
|
|
32
33
|
for (const item of fieldItems) {
|
|
33
34
|
if (item.field instanceof PaymentField) {
|
|
34
35
|
records.push(...buildPaymentRecords(item))
|
|
36
|
+
} else if (item.field instanceof GeospatialField) {
|
|
37
|
+
// Stringify of GeoJSON is done here rather than inside `getContextValueFromState`
|
|
38
|
+
// so we don't incur the overhead of JSON.stringify on every request when building context
|
|
39
|
+
records.push({
|
|
40
|
+
name: item.name,
|
|
41
|
+
title: item.label,
|
|
42
|
+
value: JSON.stringify(item.field.getFormValueFromState(item.state))
|
|
43
|
+
})
|
|
35
44
|
} else {
|
|
36
45
|
records.push({
|
|
37
46
|
name: item.name,
|
|
@@ -103,7 +112,14 @@ export function buildRepeaterRecords(
|
|
|
103
112
|
detailItems.map((subItem) => ({
|
|
104
113
|
name: subItem.name,
|
|
105
114
|
title: subItem.label,
|
|
106
|
-
value:
|
|
115
|
+
value:
|
|
116
|
+
// Stringify of GeoJSON is done here rather than inside `getContextValueFromState`
|
|
117
|
+
// so we don't incur the overhead of JSON.stringify on every request when building context
|
|
118
|
+
subItem.field instanceof GeospatialField
|
|
119
|
+
? JSON.stringify(
|
|
120
|
+
subItem.field.getFormValueFromState(subItem.state)
|
|
121
|
+
)
|
|
122
|
+
: getAnswer(subItem.field, subItem.state, { format: 'data' })
|
|
107
123
|
}))
|
|
108
124
|
)
|
|
109
125
|
}))
|
|
@@ -89,7 +89,9 @@ export const messages: LanguageMessagesExt = {
|
|
|
89
89
|
'date.base': messageTemplate.dateFormat,
|
|
90
90
|
'date.format': messageTemplate.dateFormat,
|
|
91
91
|
'date.min': messageTemplate.dateMin,
|
|
92
|
-
'date.max': messageTemplate.dateMax
|
|
92
|
+
'date.max': messageTemplate.dateMax,
|
|
93
|
+
|
|
94
|
+
'object.invalidjson': messageTemplate.format
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
export const messagesPre: LanguageMessages =
|
|
@@ -94,8 +94,10 @@ export type FormSubmissionState = {
|
|
|
94
94
|
upload?: Record<string, TempFileState>
|
|
95
95
|
} & FormState
|
|
96
96
|
|
|
97
|
-
export interface FormSubmissionError
|
|
98
|
-
|
|
97
|
+
export interface FormSubmissionError extends Pick<
|
|
98
|
+
ValidationErrorItem,
|
|
99
|
+
'context' | 'path'
|
|
100
|
+
> {
|
|
99
101
|
href: string // e.g: '#dateField__day'
|
|
100
102
|
name: string // e.g: 'dateField__day'
|
|
101
103
|
text: string // e.g: 'Date field must be a real date'
|
|
@@ -125,6 +127,7 @@ export type FormValue =
|
|
|
125
127
|
| Item['value'][]
|
|
126
128
|
| UploadState
|
|
127
129
|
| RepeatListState
|
|
130
|
+
| GeospatialState
|
|
128
131
|
| undefined
|
|
129
132
|
|
|
130
133
|
export type FormState = Partial<Record<string, FormStateValue>>
|
|
@@ -285,6 +288,76 @@ export interface RepeatItemState extends FormPayload {
|
|
|
285
288
|
|
|
286
289
|
export type RepeatListState = RepeatItemState[]
|
|
287
290
|
|
|
291
|
+
/**
|
|
292
|
+
* A longitude/latitude coordinate pair in WGS84 format
|
|
293
|
+
* Format: [longitude, latitude]
|
|
294
|
+
*/
|
|
295
|
+
export type Coordinates = [longitude: number, latitude: number]
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* GeoJSON Point geometry
|
|
299
|
+
*/
|
|
300
|
+
export interface PointGeometry {
|
|
301
|
+
type: 'Point'
|
|
302
|
+
coordinates: Coordinates
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* GeoJSON LineString geometry
|
|
307
|
+
*/
|
|
308
|
+
export interface LineStringGeometry {
|
|
309
|
+
type: 'LineString'
|
|
310
|
+
coordinates: Coordinates[]
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* GeoJSON Polygon geometry
|
|
315
|
+
*/
|
|
316
|
+
export interface PolygonGeometry {
|
|
317
|
+
type: 'Polygon'
|
|
318
|
+
coordinates: Coordinates[][]
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Supported geometry types
|
|
323
|
+
*/
|
|
324
|
+
export type Geometry = PointGeometry | LineStringGeometry | PolygonGeometry
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Feature metadata
|
|
328
|
+
*/
|
|
329
|
+
export interface FeatureProperties {
|
|
330
|
+
/**
|
|
331
|
+
* Human-readable description of the feature
|
|
332
|
+
*/
|
|
333
|
+
description: string
|
|
334
|
+
/**
|
|
335
|
+
* The OS grid reference of the first coordinate of the feature
|
|
336
|
+
*/
|
|
337
|
+
coordinateGridReference?: string
|
|
338
|
+
/**
|
|
339
|
+
* The OS grid reference of the centroid of the feature
|
|
340
|
+
*/
|
|
341
|
+
centroidGridReference?: string
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* A single GeoJSON Feature
|
|
346
|
+
*/
|
|
347
|
+
export interface Feature {
|
|
348
|
+
id: string
|
|
349
|
+
type: 'Feature'
|
|
350
|
+
properties: FeatureProperties
|
|
351
|
+
geometry: Geometry
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* A GeoJSON FeatureCollection
|
|
356
|
+
*/
|
|
357
|
+
export type FeatureCollection = Feature[]
|
|
358
|
+
|
|
359
|
+
export type GeospatialState = FeatureCollection
|
|
360
|
+
|
|
288
361
|
export interface CheckAnswers {
|
|
289
362
|
title?: ComponentText
|
|
290
363
|
summaryList: SummaryList
|
|
@@ -502,6 +575,7 @@ export type RichFormValue =
|
|
|
502
575
|
| UkAddressState
|
|
503
576
|
| EastingNorthingState
|
|
504
577
|
| LatLongState
|
|
578
|
+
| GeospatialState
|
|
505
579
|
|
|
506
580
|
export interface FormAdapterSubmissionMessageData {
|
|
507
581
|
main: Record<string, RichFormValue | null>
|
|
@@ -516,8 +590,7 @@ export interface FormAdapterSubmissionMessagePayload {
|
|
|
516
590
|
result: FormAdapterSubmissionMessageResult
|
|
517
591
|
}
|
|
518
592
|
|
|
519
|
-
export interface FormAdapterSubmissionMessage
|
|
520
|
-
extends FormAdapterSubmissionMessagePayload {
|
|
593
|
+
export interface FormAdapterSubmissionMessage extends FormAdapterSubmissionMessagePayload {
|
|
521
594
|
messageId: string
|
|
522
595
|
recordCreatedAt: Date
|
|
523
596
|
}
|
|
@@ -33,9 +33,8 @@ describe('Nunjucks context', () => {
|
|
|
33
33
|
const { config } = await import('~/src/config/index.js')
|
|
34
34
|
|
|
35
35
|
// Import when isolated to avoid cache
|
|
36
|
-
const { devtoolContext } =
|
|
37
|
-
'~/src/server/plugins/nunjucks/context.js'
|
|
38
|
-
)
|
|
36
|
+
const { devtoolContext } =
|
|
37
|
+
await import('~/src/server/plugins/nunjucks/context.js')
|
|
39
38
|
|
|
40
39
|
// Update config for missing manifest
|
|
41
40
|
config.set('publicDir', tmpdir())
|
|
@@ -24,8 +24,10 @@ export interface FormParams extends Partial<Record<string, string>> {
|
|
|
24
24
|
state?: FormStatus
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export interface FormRequestRefs
|
|
28
|
-
|
|
27
|
+
export interface FormRequestRefs extends Omit<
|
|
28
|
+
ReqRefDefaults,
|
|
29
|
+
'Params' | 'Payload' | 'Query'
|
|
30
|
+
> {
|
|
29
31
|
Params: FormParams
|
|
30
32
|
Payload: object | undefined
|
|
31
33
|
Query: FormQuery
|
|
@@ -147,7 +147,9 @@ export class CacheService {
|
|
|
147
147
|
throw new Error('No session ID found')
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
// eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
|
|
150
151
|
const state = (request.params.state as string) || ''
|
|
152
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
151
153
|
const slug = (request.params.slug as string) || ''
|
|
152
154
|
const key = `${request.yar.id}:${state}:${slug}:`
|
|
153
155
|
|