@defra/forms-engine-plugin 4.5.4 → 4.5.5

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.
@@ -164,11 +164,17 @@ export function addFeatureToMap(feature, drawPlugin, map) {
164
164
  * Returns HTML summary list for the features
165
165
  * @param {FeatureCollection} features - the features
166
166
  * @param {string} mapId - the ID of the map
167
+ * @param {boolean} [disabled] - render the list with disabled links
167
168
  * @param {boolean} [readonly] - render the list in readonly mode
168
169
  */
169
- export function createFeaturesHTML(features, mapId, readonly = false) {
170
+ export function createFeaturesHTML(
171
+ features,
172
+ mapId,
173
+ disabled = false,
174
+ readonly = false
175
+ ) {
170
176
  return `<dl class="govuk-summary-list">
171
- ${features.map((feature, index) => createFeatureHTML(feature, index, mapId, readonly)).join('\n')}
177
+ ${features.map((feature, index) => createFeatureHTML(feature, index, mapId, disabled, readonly)).join('\n')}
172
178
  </dl>`
173
179
  }
174
180
 
@@ -186,9 +192,16 @@ export function focusFeature(feature, mapProvider) {
186
192
  * @param {Feature} feature - the geo feature
187
193
  * @param {number} index - the feature index
188
194
  * @param {string} mapId - the ID of the map
189
- * @param {boolean} readonly - render the list item in readonly mode
195
+ * @param {boolean} [disabled] - render the list with disabled links
196
+ * @param {boolean} [readonly] - render the list item in readonly mode
190
197
  */
191
- function createFeatureHTML(feature, index, mapId, readonly) {
198
+ export function createFeatureHTML(
199
+ feature,
200
+ index,
201
+ mapId,
202
+ disabled = false,
203
+ readonly = false
204
+ ) {
192
205
  const flattened = feature.geometry.coordinates.flat(2)
193
206
 
194
207
  const points = []
@@ -203,13 +216,13 @@ function createFeatureHTML(feature, index, mapId, readonly) {
203
216
 
204
217
  // Change action link
205
218
  const changeAction = () => `<li class="govuk-summary-list__actions-list-item">
206
- <a class="govuk-link govuk-link--no-visited-state" href="#${mapId}" data-action="edit" data-id="${feature.id}"
219
+ <a class="govuk-link govuk-link--no-visited-state ${disabled ? 'govuk-link--disabled' : ''}" href="#${mapId}" data-action="edit" data-id="${feature.id}"
207
220
  data-type="${feature.geometry.type}">Update<span class="govuk-visually-hidden"> location</span></a>
208
221
  </li>`
209
222
 
210
223
  // Delete action link
211
224
  const deleteAction = () => `<li class="govuk-summary-list__actions-list-item">
212
- <a class="govuk-link govuk-link--no-visited-state" href="#" data-action="delete" data-id="${feature.id}"
225
+ <a class="govuk-link govuk-link--no-visited-state ${disabled ? 'govuk-link--disabled' : ''}" href="#" data-action="delete" data-id="${feature.id}"
213
226
  data-type="${feature.geometry.type}">Delete<span class="govuk-visually-hidden"> location</span></a>
214
227
  </li>`
215
228
 
@@ -415,8 +428,8 @@ function getFeaturesManager(geojson) {
415
428
  * @returns {RenderList}
416
429
  */
417
430
  function getListRenderer(geojson, mapId, listEl, renderValue) {
418
- return function renderList() {
419
- const html = createFeaturesHTML(geojson.features, mapId)
431
+ return function renderList(disabled = false) {
432
+ const html = createFeaturesHTML(geojson.features, mapId, disabled)
420
433
 
421
434
  listEl.innerHTML = html
422
435
 
@@ -523,7 +536,7 @@ function createContainers(geospatialInput, index) {
523
536
  function onMapReadyFactory(context) {
524
537
  const { map, activeFeatureManager, uiManager, interactPlugin, drawPlugin } =
525
538
  context
526
- const { toggleActionButtons } = uiManager
539
+ const { toggleActionButtons, renderList } = uiManager
527
540
  const { resetActiveFeature } = activeFeatureManager
528
541
 
529
542
  /**
@@ -542,6 +555,7 @@ function onMapReadyFactory(context) {
542
555
  onClick: () => {
543
556
  resetActiveFeature()
544
557
  toggleActionButtons(true)
558
+ renderList(true)
545
559
  interactPlugin.enable()
546
560
  },
547
561
  mobile: { slot: 'actions' },
@@ -556,6 +570,7 @@ function onMapReadyFactory(context) {
556
570
  onClick: () => {
557
571
  resetActiveFeature()
558
572
  toggleActionButtons(true)
573
+ renderList(true)
559
574
  drawPlugin.newPolygon(generateID(), polygonFeatureProperties)
560
575
  },
561
576
  mobile: { slot: 'actions' },
@@ -570,6 +585,7 @@ function onMapReadyFactory(context) {
570
585
  onClick: () => {
571
586
  resetActiveFeature()
572
587
  toggleActionButtons(true)
588
+ renderList(true)
573
589
  drawPlugin.newLine(generateID(), lineFeatureProperties)
574
590
  },
575
591
  mobile: { slot: 'actions' },
@@ -589,6 +605,7 @@ function onMapReadyFactory(context) {
589
605
  const { listEl } = uiManager
590
606
  listEl.addEventListener('click', onListElClickFactory(context), false)
591
607
  listEl.addEventListener('change', onListElChangeFactory(context), false)
608
+ listEl.addEventListener('keydown', onListElKeydownFactory(), false)
592
609
  }
593
610
  }
594
611
 
@@ -679,7 +696,7 @@ function onDrawEditedFactory(context) {
679
696
  */
680
697
  function onDrawCancelledFactory(context) {
681
698
  const { uiManager, activeFeatureManager } = context
682
- const { toggleActionButtons } = uiManager
699
+ const { toggleActionButtons, renderList } = uiManager
683
700
  const { resetActiveFeature } = activeFeatureManager
684
701
 
685
702
  /**
@@ -688,6 +705,7 @@ function onDrawCancelledFactory(context) {
688
705
  return function onDrawCancelled() {
689
706
  toggleActionButtons(false)
690
707
  resetActiveFeature()
708
+ renderList()
691
709
  }
692
710
  }
693
711
 
@@ -815,6 +833,7 @@ function onListElClickFactory(context) {
815
833
  }
816
834
 
817
835
  toggleActionButtons(true)
836
+ renderList(true)
818
837
  }
819
838
 
820
839
  /**
@@ -859,7 +878,7 @@ function onListElClickFactory(context) {
859
878
  }
860
879
 
861
880
  /**
862
- * Callback factory function that fires a 'change' event is fired on the list container
881
+ * Callback factory function that fires when a 'change' event is fired on the list container
863
882
  * @param {Context} context - the UI context
864
883
  */
865
884
  function onListElChangeFactory(context) {
@@ -891,6 +910,29 @@ function onListElChangeFactory(context) {
891
910
  }
892
911
  }
893
912
 
913
+ /**
914
+ * Callback factory function that fires when a 'keydown' event is fired on the list container
915
+ */
916
+ function onListElKeydownFactory() {
917
+ /**
918
+ * List container delegated 'keydown' events handler
919
+ * Fixes the issue of pressing "Enter" key in the description input triggering the map search
920
+ * @param {KeyboardEvent} e
921
+ */
922
+ return function (e) {
923
+ const target = e.target
924
+
925
+ if (!(target instanceof HTMLInputElement)) {
926
+ return
927
+ }
928
+
929
+ if (e.code === 'Enter' || e.code === 'NumpadEnter') {
930
+ e.preventDefault()
931
+ e.stopPropagation()
932
+ }
933
+ }
934
+ }
935
+
894
936
  /**
895
937
  * @import { MapsEnvironmentConfig, InteractiveMap } from '~/src/client/javascripts/map.js'
896
938
  */
@@ -960,6 +1002,7 @@ function onListElChangeFactory(context) {
960
1002
  /**
961
1003
  * Renders the features into the list
962
1004
  * @callback RenderList
1005
+ * @param {boolean} [disabled] - whether to render the list with disabled links
963
1006
  * @returns {void}
964
1007
  */
965
1008
 
@@ -33,6 +33,11 @@
33
33
  @include govuk-font($size: 19);
34
34
  }
35
35
 
36
+ // Used in geospatial field
37
+ .govuk-link--disabled {
38
+ opacity: 0.5;
39
+ }
40
+
36
41
  // Hide urls for hyperlinks when in print mode
37
42
  @media print {
38
43
  .govuk-link[href]::after {
@@ -110,7 +110,7 @@ describe('GeospatialField', () => {
110
110
 
111
111
  expect(result.errors).toEqual([
112
112
  expect.objectContaining({
113
- text: 'Example geospatial must contain at least 1 items'
113
+ text: 'Select example geospatial'
114
114
  })
115
115
  ])
116
116
  })
@@ -128,7 +128,7 @@ describe('GeospatialField', () => {
128
128
 
129
129
  expect(result.errors).toEqual([
130
130
  expect.objectContaining({
131
- text: 'Example geospatial title must contain at least 1 items'
131
+ text: 'Select example geospatial title'
132
132
  })
133
133
  ])
134
134
  })
@@ -49,14 +49,7 @@ describe('Geospatial validation helpers', () => {
49
49
  test('it should validate an empty string', () => {
50
50
  const result = geospatialSchema.validate('')
51
51
 
52
- expect(result.error).toBeUndefined()
53
- expect(result.value).toEqual([])
54
- })
55
-
56
- test('it should validate an empty string with errors when required', () => {
57
- const result = geospatialSchema.min(1).required().validate('')
58
-
59
52
  expect(result.error).toBeDefined()
60
- expect(result.value).toEqual([])
53
+ expect(result.value).toBeUndefined()
61
54
  })
62
55
  })
@@ -20,7 +20,7 @@ const Joi = JoiBase.extend({
20
20
  if (typeof value === 'string') {
21
21
  if (value.trim() === '') {
22
22
  return {
23
- value: []
23
+ value: undefined
24
24
  }
25
25
  }
26
26