@defra/interactive-map 0.0.15-alpha → 0.0.17-alpha

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 (263) hide show
  1. package/assets/css/docusaurus.css +104 -0
  2. package/assets/images/favicon.svg +1 -0
  3. package/assets/images/hero.png +0 -0
  4. package/assets/images/slot-map.svg +264 -0
  5. package/dist/css/index.css +1 -1
  6. package/dist/esm/im-core.js +1 -1
  7. package/dist/esm/im-shell.js +1 -1
  8. package/dist/umd/im-core.js +1 -1
  9. package/dist/umd/index.js +1 -1
  10. package/docs/api/slots.md +90 -6
  11. package/docs/api.md +4 -4
  12. package/docs/architecture.md +3 -1
  13. package/docs/{demo.mdx → examples.mdx} +1 -1
  14. package/docs/getting-started.md +5 -4
  15. package/docs/index.mdx +42 -0
  16. package/docs/plugins/datasets.md +561 -0
  17. package/docs/plugins/interact.md +176 -55
  18. package/docs/plugins/map-styles.md +64 -7
  19. package/docs/plugins/search.md +207 -63
  20. package/docs/plugins.md +8 -16
  21. package/docusaurus.config.cjs +34 -34
  22. package/jest.setup.js +1 -1
  23. package/package.json +6 -5
  24. package/plugins/beta/datasets/dist/css/index.css +85 -15
  25. package/plugins/beta/datasets/dist/esm/im-datasets-plugin.js +1 -1
  26. package/plugins/beta/datasets/dist/umd/im-datasets-plugin.js +1 -1
  27. package/plugins/beta/datasets/dist/umd/index.js +1 -1
  28. package/plugins/beta/datasets/src/DatasetsInit.jsx +24 -9
  29. package/plugins/beta/datasets/src/adapters/maplibre/index.js +18 -0
  30. package/plugins/beta/datasets/src/adapters/maplibre/layerBuilders.js +113 -0
  31. package/plugins/beta/datasets/src/adapters/maplibre/layerIds.js +69 -0
  32. package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +338 -0
  33. package/plugins/beta/datasets/src/adapters/maplibre/patternRegistry.js +48 -0
  34. package/plugins/beta/datasets/src/api/addDataset.js +3 -9
  35. package/plugins/beta/datasets/src/api/getOpacity.js +17 -0
  36. package/plugins/beta/datasets/src/api/getStyle.js +13 -0
  37. package/plugins/beta/datasets/src/api/removeDataset.js +3 -45
  38. package/plugins/beta/datasets/src/api/setData.js +8 -0
  39. package/plugins/beta/datasets/src/api/setDatasetVisibility.js +37 -0
  40. package/plugins/beta/datasets/src/api/setFeatureVisibility.js +22 -0
  41. package/plugins/beta/datasets/src/api/setOpacity.js +29 -0
  42. package/plugins/beta/datasets/src/api/setStyle.js +22 -0
  43. package/plugins/beta/datasets/src/datasets.js +33 -59
  44. package/plugins/beta/datasets/src/defaults.js +43 -9
  45. package/plugins/beta/datasets/src/fetch/createDynamicSource.js +39 -30
  46. package/plugins/beta/datasets/src/fetch/fetchGeoJSON.js +2 -2
  47. package/plugins/beta/datasets/src/manifest.js +27 -19
  48. package/plugins/beta/datasets/src/panels/Key.jsx +129 -49
  49. package/plugins/beta/datasets/src/panels/Key.module.scss +48 -9
  50. package/plugins/beta/datasets/src/panels/Layers.jsx +131 -29
  51. package/plugins/beta/datasets/src/panels/Layers.module.scss +50 -8
  52. package/plugins/beta/datasets/src/reducer.js +128 -9
  53. package/plugins/beta/datasets/src/styles/patterns.js +157 -0
  54. package/plugins/beta/datasets/src/utils/bbox.js +8 -6
  55. package/plugins/beta/datasets/src/utils/filters.js +5 -2
  56. package/plugins/beta/datasets/src/utils/mergeSublayer.js +78 -0
  57. package/plugins/beta/draw-es/dist/esm/im-draw-es-plugin.js +1 -1
  58. package/plugins/beta/draw-es/src/DrawInit.jsx +16 -16
  59. package/plugins/beta/draw-es/src/api/addFeature.js +3 -3
  60. package/plugins/beta/draw-es/src/api/deleteFeature.js +3 -3
  61. package/plugins/beta/draw-es/src/api/editFeature.js +3 -3
  62. package/plugins/beta/draw-es/src/api/newPolygon.js +3 -3
  63. package/plugins/beta/draw-es/src/events.js +52 -20
  64. package/plugins/beta/draw-es/src/events.test.js +301 -0
  65. package/plugins/beta/draw-es/src/graphic.js +1 -1
  66. package/plugins/beta/draw-es/src/manifest.js +4 -4
  67. package/plugins/beta/draw-es/src/reducer.js +1 -1
  68. package/plugins/beta/draw-es/src/sketchViewModel.js +1 -1
  69. package/plugins/beta/draw-ml/dist/css/index.css +1 -1
  70. package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -1
  71. package/plugins/beta/draw-ml/dist/umd/im-draw-ml-plugin.js +1 -1
  72. package/plugins/beta/draw-ml/src/DrawInit.jsx +49 -52
  73. package/plugins/beta/draw-ml/src/api/deleteFeature.js +1 -1
  74. package/plugins/beta/draw-ml/src/api/editFeature.js +8 -5
  75. package/plugins/beta/draw-ml/src/api/newLine.js +0 -1
  76. package/plugins/beta/draw-ml/src/api/newPolygon.js +0 -1
  77. package/plugins/beta/draw-ml/src/api/split.js +4 -4
  78. package/plugins/beta/draw-ml/src/defaults.js +1 -1
  79. package/plugins/beta/draw-ml/src/draw.scss +0 -7
  80. package/plugins/beta/draw-ml/src/events.js +8 -6
  81. package/plugins/beta/draw-ml/src/manifest.js +29 -29
  82. package/plugins/beta/draw-ml/src/mapboxDraw.js +1 -1
  83. package/plugins/beta/draw-ml/src/mapboxSnap.js +17 -18
  84. package/plugins/beta/draw-ml/src/modes/createDrawMode.js +31 -31
  85. package/plugins/beta/draw-ml/src/modes/disabledMode.js +1 -1
  86. package/plugins/beta/draw-ml/src/modes/editVertex/touchHandlers.js +11 -11
  87. package/plugins/beta/draw-ml/src/modes/editVertex/undoHandlers.js +7 -7
  88. package/plugins/beta/draw-ml/src/modes/editVertex/vertexOperations.js +8 -8
  89. package/plugins/beta/draw-ml/src/modes/editVertex/vertexQueries.js +7 -7
  90. package/plugins/beta/draw-ml/src/modes/editVertexMode.js +32 -24
  91. package/plugins/beta/draw-ml/src/reducer.js +1 -1
  92. package/plugins/beta/draw-ml/src/undoStack.js +4 -4
  93. package/plugins/beta/draw-ml/src/utils/snapHelpers.js +12 -12
  94. package/plugins/beta/draw-ml/src/utils/spatial.js +11 -11
  95. package/plugins/beta/frame/dist/esm/im-frame-plugin.js +1 -1
  96. package/plugins/beta/frame/dist/umd/im-frame-plugin.js +1 -1
  97. package/plugins/beta/frame/src/Frame.jsx +9 -9
  98. package/plugins/beta/frame/src/FrameInit.jsx +4 -4
  99. package/plugins/beta/frame/src/api/addFrame.js +1 -1
  100. package/plugins/beta/frame/src/api/editFeature.js +1 -1
  101. package/plugins/beta/frame/src/config.js +1 -1
  102. package/plugins/beta/frame/src/manifest.js +3 -3
  103. package/plugins/beta/frame/src/reducer.js +1 -1
  104. package/plugins/beta/frame/src/utils.js +1 -1
  105. package/plugins/beta/map-styles/dist/esm/im-map-styles-plugin.js +1 -1
  106. package/plugins/beta/map-styles/dist/umd/im-map-styles-plugin.js +1 -1
  107. package/plugins/beta/map-styles/src/MapStyles.jsx +18 -18
  108. package/plugins/beta/map-styles/src/manifest.js +1 -1
  109. package/plugins/beta/scale-bar/dist/css/index.css +1 -1
  110. package/plugins/beta/scale-bar/dist/esm/im-scale-bar-plugin.js +1 -1
  111. package/plugins/beta/scale-bar/dist/umd/im-scale-bar-plugin.js +1 -1
  112. package/plugins/beta/scale-bar/src/ScaleBar.jsx +5 -5
  113. package/plugins/beta/scale-bar/src/index.test.js +3 -3
  114. package/plugins/beta/scale-bar/src/manifest.js +3 -3
  115. package/plugins/beta/scale-bar/src/scaleBar.scss +2 -1
  116. package/plugins/beta/use-location/src/UseLocation.jsx +1 -1
  117. package/plugins/beta/use-location/src/defaults.js +1 -1
  118. package/plugins/beta/use-location/src/events.js +3 -3
  119. package/plugins/interact/dist/css/index.css +1 -1
  120. package/plugins/interact/dist/esm/im-interact-plugin.js +1 -1
  121. package/plugins/interact/dist/umd/im-interact-plugin.js +1 -1
  122. package/plugins/interact/src/InteractInit.jsx +1 -2
  123. package/plugins/interact/src/api/enable.js +8 -5
  124. package/plugins/interact/src/api/enable.test.js +2 -2
  125. package/plugins/interact/src/api/selectFeature.js +4 -4
  126. package/plugins/interact/src/api/unselectFeature.js +5 -5
  127. package/plugins/interact/src/defaults.js +0 -1
  128. package/plugins/interact/src/events.test.js +15 -15
  129. package/plugins/interact/src/hooks/useHighlightSync.js +1 -1
  130. package/plugins/interact/src/hooks/useInteractionHandlers.js +2 -2
  131. package/plugins/interact/src/hooks/useInteractionHandlers.test.js +5 -5
  132. package/plugins/interact/src/interact.scss +0 -7
  133. package/plugins/interact/src/manifest.js +15 -19
  134. package/plugins/interact/src/manifest.test.js +6 -5
  135. package/plugins/interact/src/reducer.js +3 -3
  136. package/plugins/interact/src/reducer.test.js +0 -1
  137. package/plugins/interact/src/utils/spatial.js +10 -10
  138. package/plugins/interact/src/utils/spatial.test.js +14 -14
  139. package/plugins/search/dist/css/index.css +1 -1
  140. package/plugins/search/dist/esm/im-search-plugin.js +1 -1
  141. package/plugins/search/dist/esm/index.js +1 -1
  142. package/plugins/search/dist/umd/im-search-plugin.js +1 -1
  143. package/plugins/search/dist/umd/index.js +1 -1
  144. package/plugins/search/src/Search.jsx +7 -6
  145. package/plugins/search/src/Search.test.jsx +23 -23
  146. package/plugins/search/src/components/CloseButton/CloseButton.jsx +15 -15
  147. package/plugins/search/src/components/CloseButton/CloseButton.test.jsx +2 -2
  148. package/plugins/search/src/components/Form/Form.jsx +14 -14
  149. package/plugins/search/src/components/Form/Form.module.scss +2 -1
  150. package/plugins/search/src/components/Form/Form.test.jsx +11 -11
  151. package/plugins/search/src/components/OpenButton/OpenButton.jsx +16 -15
  152. package/plugins/search/src/components/OpenButton/OpenButton.test.jsx +6 -2
  153. package/plugins/search/src/components/SubmitButton/SubmitButton.jsx +15 -15
  154. package/plugins/search/src/components/Suggestions/Suggestions.jsx +6 -6
  155. package/plugins/search/src/components/Suggestions/Suggestions.test.jsx +4 -4
  156. package/plugins/search/src/datasets.js +12 -13
  157. package/plugins/search/src/datasets.test.js +1 -1
  158. package/plugins/search/src/defaults.js +1 -1
  159. package/plugins/search/src/events/fetchSuggestions.js +3 -3
  160. package/plugins/search/src/events/fetchSuggestions.test.js +1 -1
  161. package/plugins/search/src/events/formHandlers.js +3 -3
  162. package/plugins/search/src/events/formHandlers.test.js +1 -1
  163. package/plugins/search/src/events/index.js +2 -2
  164. package/plugins/search/src/events/index.test.js +2 -2
  165. package/plugins/search/src/events/inputHandlers.js +4 -4
  166. package/plugins/search/src/events/inputHandlers.test.js +1 -1
  167. package/plugins/search/src/events/suggestionHandlers.js +2 -2
  168. package/plugins/search/src/events/suggestionHandlers.test.js +1 -1
  169. package/plugins/search/src/index.js +2 -1
  170. package/plugins/search/src/index.test.js +3 -3
  171. package/plugins/search/src/manifest.js +6 -4
  172. package/plugins/search/src/reducer.js +1 -2
  173. package/plugins/search/src/reducer.test.js +2 -2
  174. package/plugins/search/src/search.scss +10 -3
  175. package/plugins/search/src/utils/parseOsNamesResults.js +1 -2
  176. package/plugins/search/src/utils/parseOsNamesResults.test.js +2 -2
  177. package/plugins/search/src/utils/updateMap.js +1 -1
  178. package/plugins/search/src/utils/updateMap.test.js +5 -5
  179. package/providers/beta/esri/dist/esm/im-esri-provider.js +1 -1
  180. package/providers/beta/esri/src/esriProvider.js +5 -5
  181. package/providers/beta/esri/src/utils/coords.js +1 -1
  182. package/providers/beta/esri/src/utils/esriFixes.js +1 -1
  183. package/providers/beta/esri/src/utils/query.js +4 -4
  184. package/providers/beta/esri/src/utils/spatial.js +1 -2
  185. package/providers/beta/esri/src/utils/spatial.test.js +4 -1
  186. package/providers/beta/open-names/src/utils/mapToLocationModel.test.js +1 -1
  187. package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -1
  188. package/providers/maplibre/dist/umd/im-maplibre-framework.js +1 -1
  189. package/providers/maplibre/dist/umd/im-maplibre-framework.js.LICENSE.txt +1 -1
  190. package/providers/maplibre/dist/umd/im-maplibre-provider.js +1 -1
  191. package/providers/maplibre/src/appEvents.test.js +1 -1
  192. package/providers/maplibre/src/index.js +1 -1
  193. package/providers/maplibre/src/index.test.js +3 -5
  194. package/providers/maplibre/src/mapEvents.test.js +15 -5
  195. package/providers/maplibre/src/maplibreProvider.test.js +6 -2
  196. package/providers/maplibre/src/utils/calculateLinearTextSize.js +4 -4
  197. package/providers/maplibre/src/utils/calculateLinearTextSize.test.js +3 -3
  198. package/providers/maplibre/src/utils/detectWebgl.test.js +1 -1
  199. package/providers/maplibre/src/utils/highlightFeatures.js +3 -2
  200. package/providers/maplibre/src/utils/highlightFeatures.test.js +13 -6
  201. package/providers/maplibre/src/utils/labels.js +19 -20
  202. package/providers/maplibre/src/utils/labels.test.js +15 -13
  203. package/providers/maplibre/src/utils/maplibreFixes.test.js +1 -1
  204. package/providers/maplibre/src/utils/queryFeatures.js +6 -6
  205. package/providers/maplibre/src/utils/queryFeatures.test.js +13 -13
  206. package/providers/maplibre/src/utils/spatial.js +0 -1
  207. package/providers/maplibre/src/utils/spatial.test.js +26 -27
  208. package/src/App/components/Actions/Actions.jsx +2 -2
  209. package/src/App/components/Actions/Actions.module.scss +0 -7
  210. package/src/App/components/Actions/Actions.test.jsx +1 -1
  211. package/src/App/components/Icon/Icon.jsx +3 -2
  212. package/src/App/components/Icon/Icon.module.scss +4 -0
  213. package/src/App/components/Icon/Icon.test.jsx +43 -4
  214. package/src/App/components/MapButton/MapButton.jsx +42 -17
  215. package/src/App/components/MapButton/MapButton.module.scss +4 -13
  216. package/src/App/components/MapButton/MapButton.test.jsx +27 -3
  217. package/src/App/components/PopupMenu/PopupMenu.jsx +51 -274
  218. package/src/App/components/PopupMenu/PopupMenu.module.scss +14 -7
  219. package/src/App/components/PopupMenu/PopupMenu.test.jsx +70 -1
  220. package/src/App/components/PopupMenu/usePopupMenu.js +258 -0
  221. package/src/App/hooks/useButtonStateEvaluator.js +12 -2
  222. package/src/App/hooks/useButtonStateEvaluator.test.js +38 -4
  223. package/src/App/hooks/useInterfaceAPI.js +6 -0
  224. package/src/App/hooks/useLayoutMeasurements.js +84 -18
  225. package/src/App/hooks/useLayoutMeasurements.test.js +124 -17
  226. package/src/App/layout/Layout.jsx +12 -7
  227. package/src/App/layout/Layout.test.jsx +2 -2
  228. package/src/App/layout/layout.module.scss +67 -29
  229. package/src/App/registry/pluginRegistry.js +17 -0
  230. package/src/App/registry/pluginRegistry.test.js +33 -0
  231. package/src/App/renderer/HtmlElementHost.jsx +2 -1
  232. package/src/App/renderer/HtmlElementHost.test.jsx +7 -7
  233. package/src/App/renderer/mapButtons.js +3 -2
  234. package/src/App/renderer/mapPanels.test.js +2 -2
  235. package/src/App/renderer/slotHelpers.js +2 -2
  236. package/src/App/renderer/slotHelpers.test.js +5 -5
  237. package/src/App/renderer/slots.js +9 -5
  238. package/src/App/store/AppProvider.jsx +3 -1
  239. package/src/App/store/AppProvider.test.jsx +1 -1
  240. package/src/App/store/ServiceProvider.jsx +3 -1
  241. package/src/App/store/appActionsMap.js +16 -0
  242. package/src/App/store/appActionsMap.test.js +27 -0
  243. package/src/App/store/appDispatchMiddleware.js +33 -1
  244. package/src/App/store/appDispatchMiddleware.test.js +250 -222
  245. package/src/App/store/appReducer.js +2 -0
  246. package/src/InteractiveMap/InteractiveMap.js +4 -0
  247. package/src/config/appConfig.js +7 -4
  248. package/src/config/events.js +28 -0
  249. package/src/scss/main.scss +1 -0
  250. package/src/scss/settings/_dimensions.scss +0 -1
  251. package/src/services/logger.js +6 -0
  252. package/src/services/logger.test.js +32 -0
  253. package/src/utils/getSafeZoneInset.js +9 -7
  254. package/src/utils/getSafeZoneInset.test.js +10 -10
  255. package/webpack.dev.mjs +23 -19
  256. package/docs/govuk-prototype.md +0 -23
  257. package/docs/index.md +0 -19
  258. package/plugins/beta/datasets/src/api/hideDataset.js +0 -14
  259. package/plugins/beta/datasets/src/api/hideFeatures.js +0 -41
  260. package/plugins/beta/datasets/src/api/showDataset.js +0 -14
  261. package/plugins/beta/datasets/src/api/showFeatures.js +0 -44
  262. package/plugins/beta/datasets/src/handleSetMapStyle.js +0 -54
  263. package/plugins/beta/datasets/src/mapLayers.js +0 -165
@@ -0,0 +1,301 @@
1
+ import { attachEvents } from './events.js'
2
+ import { EVENTS as events } from '../../../../src/config/events.js'
3
+
4
+ import * as graphicJs from './graphic.js'
5
+ jest.mock('./graphic.js')
6
+ const createGraphic = jest.spyOn(graphicJs, 'createGraphic')
7
+ const createSymbol = jest.spyOn(graphicJs, 'createSymbol')
8
+ // const graphicToGeoJSON = jest.spyOn(graphicJs, 'graphicToGeoJSON')
9
+
10
+ const dispatch = jest.fn()
11
+
12
+ const createMockEventHandler = (type) => {
13
+ const callbackSpies = {}
14
+ const removeSpy = jest.fn()
15
+ const onSpy = jest.fn((eventType, callback) => {
16
+ callbackSpies[eventType] = callback
17
+ return { remove: () => removeSpy(eventType) }
18
+ })
19
+
20
+ // returns an async function that runs asserts
21
+ const assertOnCalls = (methodArray) => async () => {
22
+ expect(onSpy.mock.calls, `${type}.on should be called ${methodArray.length} times`)
23
+ .toHaveLength(methodArray.length)
24
+ methodArray.forEach((method) =>
25
+ expect(onSpy, `${type}.on should be called with ${method} and a callback`)
26
+ .toHaveBeenCalledWith(method, callbackSpies[method]))
27
+ }
28
+
29
+ const assertRemoveCalls = (methodArray) => async () => {
30
+ expect(removeSpy.mock.calls, `${type}.remove/off should be called ${methodArray.length} times`)
31
+ .toHaveLength(methodArray.length)
32
+ methodArray.forEach((method) => {
33
+ const removeParams = type === 'eventBus' ? [method, callbackSpies[[method]]] : [method]
34
+ expect(removeSpy, `${type}.remove/off should be called with ${removeParams} `).toHaveBeenCalledWith(...removeParams)
35
+ })
36
+ }
37
+
38
+ return {
39
+ removeSpy,
40
+ callbackSpies,
41
+ emit: jest.fn(),
42
+ off: removeSpy,
43
+ on: onSpy,
44
+ assertOnCalls,
45
+ assertRemoveCalls,
46
+ triggerEvent: (eventType, event) => callbackSpies[eventType](event)
47
+ }
48
+ }
49
+ const coordinates = [[[337560, 504846], [337580, 504855], [337587, 504838], [337565, 504833], [337560, 504846]]]
50
+ const feature = {
51
+ type: 'Feature',
52
+ geometry: {
53
+ type: 'Polygon',
54
+ coordinates
55
+ },
56
+ properties: { id: 'boundary' }
57
+ }
58
+
59
+ const mockSymbol = { color: 'blue' }
60
+ const newGraphicMock = { symbol: { color: 'red' } }
61
+
62
+ const mockGraphic = {
63
+ attributes: { id: 'boundary' },
64
+ geometry: { rings: coordinates },
65
+ symbol: null
66
+ }
67
+
68
+ const sketchLayer = {
69
+ removeAll: jest.fn(),
70
+ add: jest.fn(),
71
+ graphics: { items: [mockGraphic] }
72
+ }
73
+
74
+ class ButtonConfigMock {
75
+ constructor (name) {
76
+ this.name = name
77
+ this._onClick = 'Initial Value'
78
+ this._initialOnClick = this._onClick
79
+ this.assignOnClickSpy = jest.spyOn(this, 'onClick', 'set')
80
+ }
81
+
82
+ set onClick (onClick) {
83
+ this._onClick = onClick
84
+ }
85
+
86
+ get onClick () {
87
+ return this._onClick
88
+ }
89
+
90
+ assertOnClickAssignment () {
91
+ return async () => {
92
+ expect(this.assignOnClickSpy.mock.calls, `${this.name}.onClick should have been reassigned once`)
93
+ .toHaveLength(1)
94
+ expect(this._onClick, `${this.name}.onClick should have changed`)
95
+ .not.toEqual(this._initialOnClick)
96
+ }
97
+ }
98
+
99
+ assertOnClickReset () {
100
+ return async () => {
101
+ expect(this.assignOnClickSpy.mock.calls, `${this.name}.onClick should have been assigned twice`)
102
+ .toHaveLength(2)
103
+ expect(this._onClick, `${this.name}.onClick should been set back to its initial value`)
104
+ .toEqual(this._initialOnClick)
105
+ }
106
+ }
107
+ }
108
+ const emptySketchLayer = {}
109
+
110
+ const buildParams = (overrides = {}) => {
111
+ return {
112
+ pluginState: {
113
+ dispatch,
114
+ mode: 'new-polygon', // or: edit-feature
115
+ feature,
116
+ ...overrides.pluginState
117
+ },
118
+ mapProvider: {
119
+ view: createMockEventHandler('view'),
120
+ sketchViewModel: {
121
+ ...createMockEventHandler('sketchViewModel'),
122
+ layer: sketchLayer,
123
+ cancel: jest.fn(),
124
+ state: 'idle',
125
+ polygonSymbol: null,
126
+ update: jest.fn().mockResolvedValue(undefined)
127
+ },
128
+ // sketchViewModel: { ...sketchViewModel, ...overrides.sketchViewModel },
129
+ sketchLayer,
130
+ emptySketchLayer,
131
+ ...overrides.mapProvider
132
+ },
133
+ events,
134
+ eventBus: createMockEventHandler('eventBus'),
135
+ buttonConfig: {
136
+ drawDone: new ButtonConfigMock('Done'),
137
+ drawCancel: new ButtonConfigMock('Cancel')
138
+ },
139
+ mapColorScheme: 'MOCK_COLOUR_SCHEME'
140
+ }
141
+ }
142
+
143
+ describe('attachEvents - draw-es', () => {
144
+ beforeEach(() => {
145
+ jest.useFakeTimers()
146
+ })
147
+
148
+ afterEach(() => {
149
+ jest.useRealTimers()
150
+ })
151
+
152
+ describe('listeners', () => {
153
+ const params = buildParams()
154
+ const { drawDone, drawCancel } = params.buttonConfig
155
+ const { eventBus } = params
156
+ const { sketchViewModel, view } = params.mapProvider
157
+ const teardown = attachEvents(params)
158
+ describe('attach', () => {
159
+ it('should add view listeners', view.assertOnCalls(['click']))
160
+ it('should add sketchViewModel listeners', sketchViewModel.assertOnCalls(['update', 'create', 'undo']))
161
+ it('should add eventBus listeners', eventBus.assertOnCalls([events.MAP_STYLE_CHANGE]))
162
+ it('should assign a Done click handler', drawDone.assertOnClickAssignment())
163
+ it('should assign a Cancel click handler', drawCancel.assertOnClickAssignment())
164
+ })
165
+
166
+ describe('teardown', () => {
167
+ beforeAll(teardown)
168
+ it('should teardown the view listeners', view.assertRemoveCalls(['click']))
169
+ it('should teardown the sketchViewModel listeners', sketchViewModel.assertRemoveCalls(['update', 'create', 'undo']))
170
+ it('should teardown the eventBus listeners', eventBus.assertRemoveCalls([events.MAP_STYLE_CHANGE]))
171
+ it('should reset the Done click handler', drawDone.assertOnClickReset())
172
+ it('should reset the Cancel click handler', drawCancel.assertOnClickReset())
173
+ })
174
+ })
175
+
176
+ describe('internal methods', () => {
177
+ beforeEach(jest.clearAllMocks)
178
+
179
+ it('should return null if sketchViewModel is not set', async () => {
180
+ const response = attachEvents(buildParams({
181
+ mapProvider: { sketchViewModel: null }
182
+ }))
183
+ expect(response).toBeNull()
184
+ })
185
+
186
+ it('should call handleDone when Done is clicked', async () => {
187
+ const params = buildParams()
188
+ params.pluginState.tempFeature = 'Test Feature'
189
+ attachEvents(params)
190
+ params.buttonConfig.drawDone.onClick()
191
+ expect(params.mapProvider.sketchViewModel.cancel).toHaveBeenCalled()
192
+ expect(params.mapProvider.sketchViewModel.layer).toEqual(emptySketchLayer)
193
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_MODE', payload: null })
194
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_FEATURE', payload: { feature: null, tempFeature: null } })
195
+ expect(params.eventBus.emit).toHaveBeenCalledWith('draw:done', { newFeature: 'Test Feature' })
196
+ })
197
+
198
+ it('should call handleCancel when Cancel is clicked', async () => {
199
+ const params = buildParams()
200
+ params.pluginState.tempFeature = 'Test Feature'
201
+ // params.pluginState.feature = { properties: { id: 'boundary' } }
202
+ const { drawCancel } = params.buttonConfig
203
+ const { sketchViewModel, sketchLayer } = params.mapProvider
204
+ const { eventBus } = params
205
+ attachEvents(params)
206
+ drawCancel.onClick()
207
+ expect(sketchViewModel.cancel).toHaveBeenCalled()
208
+ expect(sketchLayer.removeAll).toHaveBeenCalled()
209
+ expect(createGraphic).toHaveBeenCalled()
210
+ expect(sketchLayer.add).toHaveBeenCalled()
211
+ expect(sketchViewModel.layer).toEqual(emptySketchLayer)
212
+ expect(dispatch).toHaveBeenCalledWith({ type: 'SET_MODE', payload: null })
213
+ expect(eventBus.emit).toHaveBeenCalledWith('draw:cancelled')
214
+ })
215
+
216
+ describe('reColour', () => {
217
+ beforeEach(() => {
218
+ createSymbol.mockReturnValue(mockSymbol)
219
+ createGraphic.mockReturnValue(newGraphicMock)
220
+ mockGraphic.symbol = null
221
+ })
222
+
223
+ it('should update polygonSymbol and graphic symbols when state is not active', async () => {
224
+ const params = buildParams()
225
+ attachEvents(params)
226
+ params.eventBus.triggerEvent(events.MAP_STYLE_CHANGE)
227
+ await Promise.resolve()
228
+ expect(params.mapProvider.sketchViewModel.polygonSymbol).toEqual(mockSymbol)
229
+ expect(createGraphic).toHaveBeenCalledWith('boundary', mockGraphic.geometry.rings, params.mapColorScheme)
230
+ expect(mockGraphic.symbol).toEqual(newGraphicMock.symbol)
231
+ expect(params.mapProvider.sketchViewModel.cancel).not.toHaveBeenCalled()
232
+ })
233
+
234
+ it('should cancel and re-enter update mode when state is active and activeGraphicId is set (edit mode)', async () => {
235
+ const params = buildParams()
236
+ params.mapProvider.sketchViewModel.state = 'active'
237
+ attachEvents(params)
238
+ params.eventBus.triggerEvent(events.MAP_STYLE_CHANGE)
239
+ expect(params.mapProvider.sketchViewModel.cancel).toHaveBeenCalled()
240
+ jest.advanceTimersByTime(50)
241
+ await Promise.resolve()
242
+ await Promise.resolve()
243
+ expect(params.mapProvider.sketchViewModel.update).toHaveBeenCalledWith(mockGraphic, {
244
+ tool: 'reshape',
245
+ toggleToolOnClick: false
246
+ })
247
+ })
248
+
249
+ it('should not cancel or re-enter update mode when isCreating (active state, no activeGraphicId)', async () => {
250
+ const params = buildParams({
251
+ pluginState: { feature: null }
252
+ })
253
+ attachEvents(params)
254
+ params.eventBus.triggerEvent(events.MAP_STYLE_CHANGE)
255
+ await Promise.resolve()
256
+ expect(params.mapProvider.sketchViewModel.cancel).not.toHaveBeenCalled()
257
+ expect(params.mapProvider.sketchViewModel.update).not.toHaveBeenCalled()
258
+ })
259
+
260
+ it('should not call sketchViewModel.update if layer is not sketchLayer', async () => {
261
+ const params = buildParams()
262
+ params.mapProvider.sketchViewModel.layer = emptySketchLayer
263
+ attachEvents(params)
264
+ params.eventBus.triggerEvent(events.MAP_STYLE_CHANGE)
265
+ await Promise.resolve()
266
+ expect(params.mapProvider.sketchViewModel.update).not.toHaveBeenCalled()
267
+ })
268
+
269
+ it('should swallow AbortError thrown by sketchViewModel.update', async () => {
270
+ const abortError = Object.assign(new Error('Aborted'), { name: 'AbortError' })
271
+ const params = buildParams()
272
+ params.mapProvider.sketchViewModel.update.mockRejectedValue(abortError)
273
+ const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
274
+ attachEvents(params)
275
+ params.eventBus.triggerEvent(events.MAP_STYLE_CHANGE)
276
+ jest.advanceTimersByTime(50)
277
+ await Promise.resolve()
278
+ await Promise.resolve()
279
+ await Promise.resolve()
280
+ expect(consoleSpy).not.toHaveBeenCalled()
281
+ consoleSpy.mockRestore()
282
+ })
283
+
284
+ it('should log non-AbortError thrown by sketchViewModel.update', async () => {
285
+ const genericError = new Error('Something went wrong')
286
+ const params = buildParams()
287
+ params.mapProvider.sketchViewModel.state = 'active'
288
+ params.mapProvider.sketchViewModel.update.mockRejectedValue(genericError)
289
+ const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
290
+ attachEvents(params)
291
+ params.eventBus.triggerEvent(events.MAP_STYLE_CHANGE)
292
+ jest.advanceTimersByTime(50)
293
+ await Promise.resolve()
294
+ await Promise.resolve()
295
+ await Promise.resolve()
296
+ expect(consoleSpy).toHaveBeenCalledWith('Error updating sketch:', genericError)
297
+ consoleSpy.mockRestore()
298
+ })
299
+ })
300
+ })
301
+ })
@@ -25,7 +25,7 @@ function createGraphic (id, coordinates, mapColorScheme) {
25
25
  })
26
26
  }
27
27
 
28
- function graphicToGeoJSON(graphic) {
28
+ function graphicToGeoJSON (graphic) {
29
29
  if (!graphic?.geometry) {
30
30
  throw new Error('Invalid graphic')
31
31
  }
@@ -7,8 +7,8 @@ import { addFeature } from './api/addFeature.js'
7
7
  import { deleteFeature } from './api/deleteFeature.js'
8
8
 
9
9
  const buttonSlots = {
10
- mobile: { slot: 'actions', showLabel: true },
11
- tablet: { slot: 'actions', showLabel: true },
10
+ mobile: { slot: 'actions', showLabel: true },
11
+ tablet: { slot: 'actions', showLabel: true },
12
12
  desktop: { slot: 'actions', showLabel: true }
13
13
  }
14
14
 
@@ -27,7 +27,7 @@ export const manifest = {
27
27
  hiddenWhen: ({ pluginState }) => !pluginState.mode,
28
28
  enableWhen: ({ pluginState }) => !!pluginState.tempFeature,
29
29
  ...buttonSlots
30
- },{
30
+ }, {
31
31
  id: 'drawCancel',
32
32
  label: 'Cancel',
33
33
  variant: 'tertiary',
@@ -48,4 +48,4 @@ export const manifest = {
48
48
  addFeature,
49
49
  deleteFeature
50
50
  }
51
- }
51
+ }
@@ -27,4 +27,4 @@ const actions = {
27
27
  export {
28
28
  initialState,
29
29
  actions
30
- }
30
+ }
@@ -29,4 +29,4 @@ export const createSketchViewModel = ({ mapProvider }) => {
29
29
  emptySketchLayer,
30
30
  sketchLayer
31
31
  }
32
- }
32
+ }
@@ -1 +1 @@
1
- .touch-vertex-target circle{fill:var(--map-overlay-foreground-color)}.touch-vertex-target path{fill:var(--map-overlay-halo-color)}.im-c-actions .im-c-button-wrapper--draw-done,.im-c-actions .im-c-button-wrapper--draw-menu,.im-c-actions .im-c-button-wrapper--draw-cancel{width:33.33%}.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-done,.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-menu,.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-cancel,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-done,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-menu,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-cancel{width:100px}.im-c-button-wrapper--draw-add-point{position:absolute;bottom:calc(100% + var(--primary-gap));z-index:0}
1
+ .touch-vertex-target circle{fill:var(--map-overlay-foreground-color)}.touch-vertex-target path{fill:var(--map-overlay-halo-color)}.im-c-actions .im-c-button-wrapper--draw-done,.im-c-actions .im-c-button-wrapper--draw-menu,.im-c-actions .im-c-button-wrapper--draw-cancel{width:33.33%}.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-done,.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-menu,.im-o-app--tablet .im-c-actions .im-c-button-wrapper--draw-cancel,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-done,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-menu,.im-o-app--desktop .im-c-actions .im-c-button-wrapper--draw-cancel{width:100px}