@defra/interactive-map 0.0.29-alpha → 0.0.31-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.
- package/dist/css/index.css +1 -1
- package/dist/esm/im-core.js +1 -1
- package/dist/esm/im-shell.js +1 -1
- package/dist/umd/im-core.js +1 -1
- package/dist/umd/index.js +1 -1
- package/docs/api/context.md +4 -4
- package/docs/api.md +111 -37
- package/docs/assets/css/docusaurus.scss +20 -4
- package/docs/assets/images/basic-map.jpg +0 -0
- package/docs/assets/images/button-first.jpg +0 -0
- package/docs/assets/images/deuteranopia-ozs-map-thumb.jpg +0 -0
- package/docs/assets/images/draw.jpg +0 -0
- package/docs/assets/images/marker-panel.jpg +0 -0
- package/docs/assets/images/night-ozs-map-thumb.jpg +0 -0
- package/docs/assets/images/outdoor-ozs-map-thumb.jpg +0 -0
- package/docs/assets/images/search.jpg +0 -0
- package/docs/assets/images/select-feature.jpg +0 -0
- package/docs/assets/images/style-switcher.jpg +0 -0
- package/docs/assets/images/toggle-marker-label.jpg +0 -0
- package/docs/assets/images/tritanopia-ozs-map-thumb.jpg +0 -0
- package/docs/examples/add-marker-with-panel.mdx +2 -2
- package/docs/examples/basic-map.mdx +2 -2
- package/docs/examples/draw.mdx +271 -0
- package/docs/examples/index.mdx +58 -10
- package/docs/examples/search-control.mdx +71 -0
- package/docs/examples/select-feature.mdx +146 -0
- package/docs/examples/style-switcher.mdx +135 -0
- package/docs/examples/toggle-marker-label.mdx +3 -3
- package/docs/plugins/datasets.md +15 -28
- package/docusaurus.config.cjs +5 -1
- package/package.json +1 -1
- package/plugins/beta/datasets/dist/css/index.css +4 -0
- package/plugins/beta/datasets/dist/esm/im-datasets-ml-adapter.js +1 -0
- package/plugins/beta/datasets/dist/esm/im-datasets-plugin.js +1 -1
- package/plugins/beta/datasets/dist/esm/index.js +1 -1
- package/plugins/beta/datasets/dist/umd/im-datasets-ml-adapter.js +2 -0
- package/plugins/beta/datasets/dist/umd/im-datasets-plugin.js +2 -0
- package/plugins/beta/datasets/dist/umd/index.js +2 -0
- package/plugins/beta/datasets/src/adapters/loadLayerAdapter.js +33 -0
- package/plugins/beta/datasets/src/adapters/maplibre/layerBuilders.js +44 -120
- package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +145 -245
- package/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.test.js +516 -0
- package/plugins/beta/datasets/src/adapters/maplibre/registry/mapLibreDataset.js +191 -0
- package/plugins/beta/datasets/src/adapters/maplibre/registry/mapLibreDataset.test.js +441 -0
- package/plugins/beta/datasets/src/api/addDataset.js +2 -5
- package/plugins/beta/datasets/src/api/addDataset.test.js +16 -0
- package/plugins/beta/datasets/src/api/getOpacity.js +14 -14
- package/plugins/beta/datasets/src/api/getOpacity.test.js +72 -0
- package/plugins/beta/datasets/src/api/getStyle.js +8 -9
- package/plugins/beta/datasets/src/api/getStyle.test.js +42 -0
- package/plugins/beta/datasets/src/api/removeDataset.js +7 -7
- package/plugins/beta/datasets/src/api/removeDataset.test.js +45 -0
- package/plugins/beta/datasets/src/api/setData.js +9 -3
- package/plugins/beta/datasets/src/api/setData.test.js +62 -0
- package/plugins/beta/datasets/src/api/setDatasetVisibility.js +5 -30
- package/plugins/beta/datasets/src/api/setDatasetVisibility.test.js +31 -0
- package/plugins/beta/datasets/src/api/setFeatureVisibility.js +3 -21
- package/plugins/beta/datasets/src/api/setFeatureVisibility.test.js +32 -0
- package/plugins/beta/datasets/src/api/setGlobals.js +20 -0
- package/plugins/beta/datasets/src/api/setGlobals.test.js +63 -0
- package/plugins/beta/datasets/src/api/setOpacity.js +8 -27
- package/plugins/beta/datasets/src/api/setOpacity.test.js +31 -0
- package/plugins/beta/datasets/src/api/setStyle.js +5 -21
- package/plugins/beta/datasets/src/api/setStyle.test.js +53 -0
- package/plugins/beta/datasets/src/components/Key/Key.jsx +51 -0
- package/plugins/beta/datasets/src/components/Key/KeyGroupItem.jsx +18 -0
- package/plugins/beta/datasets/src/components/Key/KeyItem.jsx +20 -0
- package/plugins/beta/datasets/src/components/Key/KeySvg.jsx +22 -0
- package/plugins/beta/datasets/src/components/Key/KeySvg.test.jsx +87 -0
- package/plugins/beta/datasets/src/components/Key/KeySvgLine.jsx +19 -0
- package/plugins/beta/datasets/src/components/Key/KeySvgLine.test.jsx +71 -0
- package/plugins/beta/datasets/src/components/{KeySvgPattern.jsx → Key/KeySvgPattern.jsx} +3 -4
- package/plugins/beta/datasets/src/components/Key/KeySvgPattern.test.jsx +55 -0
- package/plugins/beta/datasets/src/components/Key/KeySvgRect.jsx +22 -0
- package/plugins/beta/datasets/src/components/Key/KeySvgRect.test.jsx +85 -0
- package/plugins/beta/datasets/src/components/{KeySvgSymbol.jsx → Key/KeySvgSymbol.jsx} +5 -5
- package/plugins/beta/datasets/src/components/Key/KeySvgSymbol.test.jsx +80 -0
- package/plugins/beta/datasets/src/components/Key/svgProperties.test.js +61 -0
- package/plugins/beta/datasets/src/{panels → components/LayersMenu}/Layers.module.scss +4 -0
- package/plugins/beta/datasets/src/components/LayersMenu/LayersMenu.jsx +33 -0
- package/plugins/beta/datasets/src/components/LayersMenu/LayersMenuCheckbox.jsx +31 -0
- package/plugins/beta/datasets/src/components/LayersMenu/LayersMenuGroupWrapper.jsx +19 -0
- package/plugins/beta/datasets/src/datasets.scss +2 -2
- package/plugins/beta/datasets/src/fetch/createDynamicSource.js +8 -8
- package/plugins/beta/datasets/src/{DatasetsInit.jsx → initialise/DatasetsInit.jsx} +19 -21
- package/plugins/beta/datasets/src/{defaults.js → initialise/defaults.js} +17 -2
- package/plugins/beta/datasets/src/initialise/defaults.test.js +127 -0
- package/plugins/beta/datasets/src/{datasets.js → initialise/initialiseDatasets.js} +30 -26
- package/plugins/beta/datasets/src/initialise/initialiseDatasets.test.js +273 -0
- package/plugins/beta/datasets/src/manifest.js +8 -6
- package/plugins/beta/datasets/src/reducers/__data__/demoDatasets.js +253 -0
- package/plugins/beta/datasets/src/reducers/datasetsToMenu.js +78 -0
- package/plugins/beta/datasets/src/reducers/datasetsToMenu.test.js +35 -0
- package/plugins/beta/datasets/src/reducers/mappedDatasetsReducer.js +34 -0
- package/plugins/beta/datasets/src/reducers/mappedDatasetsReducer.test.js +117 -0
- package/plugins/beta/datasets/src/reducers/pluginState.js +206 -0
- package/plugins/beta/datasets/src/reducers/pluginState.test.js +386 -0
- package/plugins/beta/datasets/src/registry/__mocks__/datasetRegistry.js +29 -0
- package/plugins/beta/datasets/src/registry/createDataset.js +5 -0
- package/plugins/beta/datasets/src/registry/dataset.js +172 -0
- package/plugins/beta/datasets/src/registry/dataset.test.js +483 -0
- package/plugins/beta/datasets/src/registry/datasetDefinitionCache.js +35 -0
- package/plugins/beta/datasets/src/registry/datasetRegistry.js +116 -0
- package/plugins/beta/datasets/src/registry/datasetRegistry.test.js +335 -0
- package/plugins/beta/datasets/src/registry/dynamicGeoJson.js +17 -0
- package/plugins/beta/datasets/src/registry/globalDataset.js +36 -0
- package/plugins/beta/draw-ml/dist/esm/im-draw-ml-plugin.js +1 -1
- package/plugins/beta/draw-ml/dist/umd/im-draw-ml-plugin.js +1 -1
- package/plugins/beta/draw-ml/src/events.js +13 -1
- package/plugins/beta/draw-ml/src/index.js +1 -1
- package/plugins/beta/draw-ml/src/manifest.js +3 -0
- package/plugins/interact/dist/esm/im-interact-plugin.js +1 -1
- package/plugins/interact/dist/umd/im-interact-plugin.js +1 -1
- package/plugins/interact/src/InteractInit.jsx +2 -2
- package/plugins/interact/src/InteractInit.test.js +1 -1
- package/plugins/interact/src/events.js +2 -29
- package/plugins/interact/src/events.test.js +4 -102
- package/plugins/interact/src/hooks/useAttachEvents.js +3 -4
- package/plugins/interact/src/hooks/useAttachEvents.test.js +1 -3
- package/plugins/interact/src/hooks/useInteractionHandlers.js +10 -1
- package/plugins/interact/src/hooks/useInteractionHandlers.test.js +23 -4
- package/plugins/interact/src/manifest.js +0 -35
- package/plugins/interact/src/manifest.test.js +3 -43
- package/providers/beta/esri/dist/esm/im-esri-provider.js +1 -1
- package/providers/beta/esri/src/esriProvider.js +4 -0
- package/providers/beta/openlayers/dist/esm/im-openlayers-provider.js +1 -1
- package/providers/beta/openlayers/dist/umd/im-openlayers-provider.js +1 -1
- package/providers/beta/openlayers/src/openlayersProvider.js +4 -0
- package/providers/beta/openlayers/src/openlayersProvider.test.js +5 -0
- package/providers/maplibre/dist/esm/im-maplibre-provider.js +1 -1
- package/providers/maplibre/dist/umd/im-maplibre-provider.js +1 -1
- package/providers/maplibre/src/maplibreProvider.js +6 -4
- package/providers/maplibre/src/maplibreProvider.test.js +5 -0
- package/providers/maplibre/src/utils/highlightFeatures.js +74 -25
- package/providers/maplibre/src/utils/highlightFeatures.test.js +132 -0
- package/providers/maplibre/src/utils/patternImages.js +2 -4
- package/providers/maplibre/src/utils/symbolImages.js +1 -4
- package/rollup.esm.mjs +2 -8
- package/src/App/components/MapButton/MapButton.jsx +16 -1
- package/src/App/components/MapButton/MapButton.module.scss +12 -1
- package/src/App/components/MapButton/MapButton.test.jsx +40 -1
- package/src/App/components/Tooltip/getTooltipPosition.js +2 -2
- package/src/App/hooks/useContinueEnabledEvaluator.js +31 -0
- package/src/App/hooks/useContinueEnabledEvaluator.test.js +118 -0
- package/src/App/hooks/useEvaluateProp.js +15 -15
- package/src/App/hooks/useEvaluateProp.test.js +80 -76
- package/src/App/hooks/useLayoutMeasurements.js +1 -3
- package/src/App/hooks/useResizeObserver.js +12 -1
- package/src/App/hooks/useResizeObserver.test.js +1 -0
- package/src/App/renderer/PluginInits.jsx +2 -0
- package/src/App/renderer/mapButtons.js +21 -1
- package/src/App/renderer/mapButtons.test.js +46 -1
- package/src/App/store/appReducer.js +1 -1
- package/src/App/store/appReducer.test.js +37 -0
- package/src/InteractiveMap/InteractiveMap.js +10 -0
- package/src/InteractiveMap/InteractiveMap.test.js +8 -0
- package/src/InteractiveMap/polyfills.js +37 -6
- package/src/InteractiveMap/polyfills.test.js +132 -101
- package/src/config/appConfig.js +25 -0
- package/src/config/appConfig.test.js +50 -0
- package/src/config/defaults.js +1 -0
- package/src/scss/settings/_dimensions.scss +1 -0
- package/src/services/patternRegistry.js +8 -4
- package/src/types.js +7 -0
- package/src/utils/patternUtils.js +1 -2
- package/src/utils/patternUtils.test.js +9 -0
- package/webpack.dev.mjs +10 -0
- package/webpack.umd.mjs +1 -1
- package/plugins/beta/datasets/dist/adapters/maplibre/esm/im-datasets-ml-adapter.js +0 -1
- package/plugins/beta/datasets/dist/adapters/maplibre/esm/index.js +0 -1
- package/plugins/beta/datasets/dist/umd/maplibre/im-datasets-maplibre-adapter.js +0 -2
- package/plugins/beta/datasets/dist/umd/maplibre/im-datasets-plugin.js +0 -2
- package/plugins/beta/datasets/dist/umd/maplibre/index.js +0 -2
- package/plugins/beta/datasets/src/adapters/maplibre/index.js +0 -18
- package/plugins/beta/datasets/src/adapters/maplibre/layerIds.js +0 -75
- package/plugins/beta/datasets/src/adapters/maplibre/patternImages.js +0 -27
- package/plugins/beta/datasets/src/adapters/maplibre/symbolImages.js +0 -31
- package/plugins/beta/datasets/src/components/KeySvg.jsx +0 -24
- package/plugins/beta/datasets/src/components/KeySvgLine.jsx +0 -19
- package/plugins/beta/datasets/src/components/KeySvgRect.jsx +0 -22
- package/plugins/beta/datasets/src/index.maplibre.umd.js +0 -23
- package/plugins/beta/datasets/src/panels/Key.jsx +0 -62
- package/plugins/beta/datasets/src/panels/Layers.jsx +0 -141
- package/plugins/beta/datasets/src/reducer.js +0 -219
- package/plugins/beta/datasets/src/reducers/keyReducer.js +0 -34
- package/plugins/beta/datasets/src/utils/filters.js +0 -34
- package/plugins/beta/datasets/src/utils/mergeSublayer.js +0 -86
- package/plugins/beta/draw-ml/dist/css/index.css +0 -21
- /package/plugins/beta/datasets/dist/umd/{maplibre/im-datasets-maplibre-adapter.js.LICENSE.txt → im-datasets-ml-adapter.js.LICENSE.txt} +0 -0
- /package/plugins/beta/datasets/dist/umd/{maplibre/im-datasets-plugin.js.LICENSE.txt → im-datasets-plugin.js.LICENSE.txt} +0 -0
- /package/plugins/beta/datasets/dist/umd/{maplibre/index.js.LICENSE.txt → index.js.LICENSE.txt} +0 -0
- /package/plugins/beta/datasets/src/components/{EmptyKey.jsx → Key/EmptyKey.jsx} +0 -0
- /package/plugins/beta/datasets/src/components/{EmptyKey.test.jsx → Key/EmptyKey.test.jsx} +0 -0
- /package/plugins/beta/datasets/src/{panels → components/Key}/Key.module.scss +0 -0
- /package/plugins/beta/datasets/src/components/{svgProperties.js → Key/svgProperties.js} +0 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { initialState, actions } from './pluginState.js'
|
|
2
|
+
import { logger } from '../../../../../src/services/logger.js'
|
|
3
|
+
|
|
4
|
+
jest.mock('../../../../../src/services/logger.js', () => ({
|
|
5
|
+
logger: { error: jest.fn() }
|
|
6
|
+
}))
|
|
7
|
+
|
|
8
|
+
// Helper: build a minimal plugin state with some mapped datasets
|
|
9
|
+
const makeState = (overrides = {}) => ({
|
|
10
|
+
...initialState,
|
|
11
|
+
mappedDatasets: {},
|
|
12
|
+
orderedDatasets: [],
|
|
13
|
+
menu: [],
|
|
14
|
+
...overrides
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// Helper: build a state that already contains a dataset
|
|
18
|
+
const makeStateWithDataset = (id = 'roads', extraDatasetProps = {}) => ({
|
|
19
|
+
...makeState(),
|
|
20
|
+
mappedDatasets: {
|
|
21
|
+
[id]: { id, label: 'Roads', visible: true, style: {}, ...extraDatasetProps }
|
|
22
|
+
},
|
|
23
|
+
orderedDatasets: [id],
|
|
24
|
+
menu: [{ label: 'Default', items: [{ id, label: 'Roads', type: 'item' }] }]
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
jest.clearAllMocks()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// ─── initialState ────────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
describe('initialState', () => {
|
|
34
|
+
it('has default globals', () => {
|
|
35
|
+
expect(initialState.globals).toEqual({
|
|
36
|
+
visible: true,
|
|
37
|
+
opacity: 1,
|
|
38
|
+
opacityMode: 'dataset'
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('has an empty key', () => {
|
|
43
|
+
expect(initialState.key).toEqual({ items: [], hasGroups: false })
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('has an empty actionsArray', () => {
|
|
47
|
+
expect(initialState.actionsArray).toEqual([])
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// ─── SET_DATASETS ─────────────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
describe('SET_DATASETS', () => {
|
|
54
|
+
it('sets mappedDatasets, orderedDatasets and menu from payload', () => {
|
|
55
|
+
const state = makeState()
|
|
56
|
+
const payload = {
|
|
57
|
+
datasets: [{ id: 'parks', label: 'Parks', showInMenu: true }],
|
|
58
|
+
mappedDatasets: { parks: { id: 'parks', label: 'Parks' } },
|
|
59
|
+
orderedDatasets: ['parks'],
|
|
60
|
+
menu: [{ id: 'parks', label: 'Parks', type: 'item' }]
|
|
61
|
+
}
|
|
62
|
+
const result = actions.SET_DATASETS(state, payload)
|
|
63
|
+
expect(result.mappedDatasets).toEqual(payload.mappedDatasets)
|
|
64
|
+
expect(result.orderedDatasets).toEqual(payload.orderedDatasets)
|
|
65
|
+
expect(result.menu).toEqual(payload.menu)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('derives menu from datasets when menu is not in payload', () => {
|
|
69
|
+
const state = makeState()
|
|
70
|
+
const payload = {
|
|
71
|
+
datasets: [{ id: 'parks', label: 'Parks', showInMenu: true }],
|
|
72
|
+
mappedDatasets: { parks: { id: 'parks', label: 'Parks' } },
|
|
73
|
+
orderedDatasets: ['parks']
|
|
74
|
+
}
|
|
75
|
+
const result = actions.SET_DATASETS(state, payload)
|
|
76
|
+
// Menu is derived; it should be an array
|
|
77
|
+
expect(Array.isArray(result.menu)).toBe(true)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('does not add to actionsArray', () => {
|
|
81
|
+
const state = makeState()
|
|
82
|
+
const payload = {
|
|
83
|
+
datasets: [],
|
|
84
|
+
mappedDatasets: {},
|
|
85
|
+
orderedDatasets: []
|
|
86
|
+
}
|
|
87
|
+
const result = actions.SET_DATASETS(state, payload)
|
|
88
|
+
expect(result.actionsArray).toEqual([])
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
// ─── ADD_DATASET ──────────────────────────────────────────────────────────────
|
|
93
|
+
|
|
94
|
+
describe('ADD_DATASET', () => {
|
|
95
|
+
it('adds a new dataset and queues an addDataset action', () => {
|
|
96
|
+
const state = makeState()
|
|
97
|
+
const dataset = { id: 'rivers', label: 'Rivers', showInMenu: true }
|
|
98
|
+
const mapStyle = { layers: [] }
|
|
99
|
+
|
|
100
|
+
const result = actions.ADD_DATASET(state, { dataset, mapStyle })
|
|
101
|
+
|
|
102
|
+
expect(result.mappedDatasets).toHaveProperty('rivers')
|
|
103
|
+
expect(result.orderedDatasets).toContain('rivers')
|
|
104
|
+
expect(result.actionsArray).toHaveLength(1)
|
|
105
|
+
expect(result.actionsArray[0]).toMatchObject({
|
|
106
|
+
method: 'addDataset',
|
|
107
|
+
parameters: ['rivers', mapStyle]
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it('logs error and returns unchanged state when dataset already exists', () => {
|
|
112
|
+
const state = makeStateWithDataset('roads')
|
|
113
|
+
const result = actions.ADD_DATASET(state, { dataset: { id: 'roads', label: 'Roads' }, mapStyle: {} })
|
|
114
|
+
|
|
115
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("'roads'"))
|
|
116
|
+
expect(result).toBe(state)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
// ─── REMOVE_DATASET ───────────────────────────────────────────────────────────
|
|
121
|
+
|
|
122
|
+
describe('REMOVE_DATASET', () => {
|
|
123
|
+
it('removes the dataset from mappedDatasets, orderedDatasets and menu', () => {
|
|
124
|
+
const state = makeStateWithDataset('roads')
|
|
125
|
+
const result = actions.REMOVE_DATASET(state, { id: 'roads' })
|
|
126
|
+
|
|
127
|
+
expect(result.mappedDatasets).not.toHaveProperty('roads')
|
|
128
|
+
expect(result.orderedDatasets).not.toContain('roads')
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('removes sublayers when parent is removed', () => {
|
|
132
|
+
const state = makeState({
|
|
133
|
+
mappedDatasets: {
|
|
134
|
+
parks: { id: 'parks', label: 'Parks', sublayerIds: ['parks-zone-a'] },
|
|
135
|
+
'parks-zone-a': { id: 'parks-zone-a', parentId: 'parks' }
|
|
136
|
+
},
|
|
137
|
+
orderedDatasets: ['parks', 'parks-zone-a'],
|
|
138
|
+
menu: []
|
|
139
|
+
})
|
|
140
|
+
const result = actions.REMOVE_DATASET(state, { id: 'parks' })
|
|
141
|
+
|
|
142
|
+
expect(result.mappedDatasets).not.toHaveProperty('parks')
|
|
143
|
+
expect(result.mappedDatasets).not.toHaveProperty('parks-zone-a')
|
|
144
|
+
expect(result.orderedDatasets).toEqual([])
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('logs error and returns unchanged state when dataset does not exist', () => {
|
|
148
|
+
const state = makeState()
|
|
149
|
+
const result = actions.REMOVE_DATASET(state, { id: 'unknown' })
|
|
150
|
+
|
|
151
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("'unknown'"))
|
|
152
|
+
expect(result).toBe(state)
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
// ─── SET_DATASET_VISIBILITY ───────────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
describe('SET_DATASET_VISIBILITY', () => {
|
|
159
|
+
it('updates dataset visibility and queues applyDatasetVisibility action', () => {
|
|
160
|
+
const state = makeStateWithDataset('roads')
|
|
161
|
+
const result = actions.SET_DATASET_VISIBILITY(state, { datasetId: 'roads', visible: false })
|
|
162
|
+
|
|
163
|
+
expect(result.mappedDatasets.roads.visible).toBe(false)
|
|
164
|
+
expect(result.actionsArray).toHaveLength(1)
|
|
165
|
+
expect(result.actionsArray[0]).toMatchObject({
|
|
166
|
+
method: 'applyDatasetVisibility',
|
|
167
|
+
parameters: ['roads', false]
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
it('logs error and returns unchanged state when dataset does not exist', () => {
|
|
172
|
+
const state = makeState()
|
|
173
|
+
const result = actions.SET_DATASET_VISIBILITY(state, { datasetId: 'unknown', visible: false })
|
|
174
|
+
|
|
175
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("'unknown'"))
|
|
176
|
+
expect(result).toBe(state)
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
// ─── SET_GLOBAL_VISIBILITY ────────────────────────────────────────────────────
|
|
181
|
+
|
|
182
|
+
describe('SET_GLOBAL_VISIBILITY', () => {
|
|
183
|
+
it('updates globals.visible and queues applyGlobalVisibility action', () => {
|
|
184
|
+
const state = makeState()
|
|
185
|
+
const result = actions.SET_GLOBAL_VISIBILITY(state, { visible: false })
|
|
186
|
+
|
|
187
|
+
expect(result.globals.visible).toBe(false)
|
|
188
|
+
expect(result.actionsArray).toHaveLength(1)
|
|
189
|
+
expect(result.actionsArray[0]).toMatchObject({
|
|
190
|
+
method: 'applyGlobalVisibility',
|
|
191
|
+
parameters: [false]
|
|
192
|
+
})
|
|
193
|
+
})
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
// ─── SET_DATASET_STYLE ────────────────────────────────────────────────────────
|
|
197
|
+
|
|
198
|
+
describe('SET_DATASET_STYLE', () => {
|
|
199
|
+
it('merges style changes and queues applyStyle action', () => {
|
|
200
|
+
const state = makeStateWithDataset('roads', { style: { stroke: 'red' } })
|
|
201
|
+
const mapStyle = { layers: [] }
|
|
202
|
+
const result = actions.SET_DATASET_STYLE(state, {
|
|
203
|
+
datasetId: 'roads',
|
|
204
|
+
styleChanges: { fill: 'blue' },
|
|
205
|
+
mapStyle
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
expect(result.mappedDatasets.roads.style).toMatchObject({ stroke: 'red', fill: 'blue' })
|
|
209
|
+
expect(result.actionsArray).toHaveLength(1)
|
|
210
|
+
expect(result.actionsArray[0]).toMatchObject({
|
|
211
|
+
method: 'applyStyle',
|
|
212
|
+
parameters: ['roads', mapStyle]
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
it('logs error and returns unchanged state when dataset does not exist', () => {
|
|
217
|
+
const state = makeState()
|
|
218
|
+
const result = actions.SET_DATASET_STYLE(state, { datasetId: 'unknown', styleChanges: {}, mapStyle: {} })
|
|
219
|
+
|
|
220
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("'unknown'"))
|
|
221
|
+
expect(result).toBe(state)
|
|
222
|
+
})
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
// ─── SET_OPACITY ──────────────────────────────────────────────────────────────
|
|
226
|
+
|
|
227
|
+
describe('SET_OPACITY', () => {
|
|
228
|
+
it('sets opacity in dataset style and queues applyDatasetOpacity action', () => {
|
|
229
|
+
const state = makeStateWithDataset('roads', { style: {} })
|
|
230
|
+
const result = actions.SET_OPACITY(state, { datasetId: 'roads', opacity: 0.5 })
|
|
231
|
+
|
|
232
|
+
expect(result.mappedDatasets.roads.style.opacity).toBe(0.5)
|
|
233
|
+
expect(result.actionsArray).toHaveLength(1)
|
|
234
|
+
expect(result.actionsArray[0]).toMatchObject({
|
|
235
|
+
method: 'applyDatasetOpacity',
|
|
236
|
+
parameters: ['roads']
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
it('logs error and returns unchanged state when dataset does not exist', () => {
|
|
241
|
+
const state = makeState()
|
|
242
|
+
const result = actions.SET_OPACITY(state, { datasetId: 'unknown', opacity: 0.5 })
|
|
243
|
+
|
|
244
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("'unknown'"))
|
|
245
|
+
expect(result).toBe(state)
|
|
246
|
+
})
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
// ─── SET_GLOBAL_OPACITY ───────────────────────────────────────────────────────
|
|
250
|
+
|
|
251
|
+
describe('SET_GLOBAL_OPACITY', () => {
|
|
252
|
+
it('updates globals.opacity and queues applyGlobalOpacity action', () => {
|
|
253
|
+
const state = makeState()
|
|
254
|
+
const result = actions.SET_GLOBAL_OPACITY(state, { opacity: 0.7 })
|
|
255
|
+
|
|
256
|
+
expect(result.globals.opacity).toBe(0.7)
|
|
257
|
+
expect(result.actionsArray).toHaveLength(1)
|
|
258
|
+
expect(result.actionsArray[0]).toMatchObject({
|
|
259
|
+
method: 'applyGlobalOpacity',
|
|
260
|
+
parameters: []
|
|
261
|
+
})
|
|
262
|
+
})
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
// ─── SET_GLOBAL_STATE ─────────────────────────────────────────────────────────
|
|
266
|
+
|
|
267
|
+
describe('SET_GLOBAL_STATE', () => {
|
|
268
|
+
it('merges payload into globals and queues applyGlobalOpacity action', () => {
|
|
269
|
+
const state = makeState()
|
|
270
|
+
const result = actions.SET_GLOBAL_STATE(state, { opacityMode: 'global' })
|
|
271
|
+
|
|
272
|
+
expect(result.globals.opacityMode).toBe('global')
|
|
273
|
+
expect(result.actionsArray).toHaveLength(1)
|
|
274
|
+
expect(result.actionsArray[0]).toMatchObject({ method: 'applyGlobalOpacity' })
|
|
275
|
+
})
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
// ─── HIDE_FEATURES ────────────────────────────────────────────────────────────
|
|
279
|
+
|
|
280
|
+
describe('HIDE_FEATURES', () => {
|
|
281
|
+
it('starts from empty hiddenFeatures when none are set', () => {
|
|
282
|
+
const state = makeStateWithDataset('roads')
|
|
283
|
+
const result = actions.HIDE_FEATURES(state, { datasetId: 'roads', featureIds: [5] })
|
|
284
|
+
expect(result.mappedDatasets.roads.hiddenFeatures).toEqual([5])
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
it('adds feature ids to hiddenFeatures and queues applyFeatureFilter', () => {
|
|
288
|
+
const state = makeStateWithDataset('roads', { hiddenFeatures: [1] })
|
|
289
|
+
const result = actions.HIDE_FEATURES(state, { datasetId: 'roads', featureIds: [2, 3] })
|
|
290
|
+
|
|
291
|
+
expect(result.mappedDatasets.roads.hiddenFeatures).toEqual([1, 2, 3])
|
|
292
|
+
expect(result.actionsArray[0]).toMatchObject({ method: 'applyFeatureFilter', parameters: ['roads'] })
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('deduplicates feature ids', () => {
|
|
296
|
+
const state = makeStateWithDataset('roads', { hiddenFeatures: [1, 2] })
|
|
297
|
+
const result = actions.HIDE_FEATURES(state, { datasetId: 'roads', featureIds: [2, 3] })
|
|
298
|
+
|
|
299
|
+
expect(result.mappedDatasets.roads.hiddenFeatures).toEqual([1, 2, 3])
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
it('logs error and returns unchanged state when dataset does not exist', () => {
|
|
303
|
+
const state = makeState()
|
|
304
|
+
const result = actions.HIDE_FEATURES(state, { datasetId: 'unknown', featureIds: [1] })
|
|
305
|
+
|
|
306
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("'unknown'"))
|
|
307
|
+
expect(result).toBe(state)
|
|
308
|
+
})
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
// ─── SHOW_FEATURES ────────────────────────────────────────────────────────────
|
|
312
|
+
|
|
313
|
+
describe('SHOW_FEATURES', () => {
|
|
314
|
+
it('handles dataset with no existing hiddenFeatures', () => {
|
|
315
|
+
const state = makeStateWithDataset('roads')
|
|
316
|
+
const result = actions.SHOW_FEATURES(state, { datasetId: 'roads', featureIds: [99] })
|
|
317
|
+
expect(result.mappedDatasets.roads.hiddenFeatures).toEqual([-1])
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
it('removes feature ids from hiddenFeatures and queues applyFeatureFilter', () => {
|
|
321
|
+
const state = makeStateWithDataset('roads', { hiddenFeatures: [1, 2, 3] })
|
|
322
|
+
const result = actions.SHOW_FEATURES(state, { datasetId: 'roads', featureIds: [2] })
|
|
323
|
+
|
|
324
|
+
expect(result.mappedDatasets.roads.hiddenFeatures).toEqual([1, 3])
|
|
325
|
+
expect(result.actionsArray[0]).toMatchObject({ method: 'applyFeatureFilter', parameters: ['roads'] })
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
it('sets hiddenFeatures to [-1] when all features are shown', () => {
|
|
329
|
+
const state = makeStateWithDataset('roads', { hiddenFeatures: [1] })
|
|
330
|
+
const result = actions.SHOW_FEATURES(state, { datasetId: 'roads', featureIds: [1] })
|
|
331
|
+
|
|
332
|
+
expect(result.mappedDatasets.roads.hiddenFeatures).toEqual([-1])
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
it('logs error and returns unchanged state when dataset does not exist', () => {
|
|
336
|
+
const state = makeState()
|
|
337
|
+
const result = actions.SHOW_FEATURES(state, { datasetId: 'unknown', featureIds: [1] })
|
|
338
|
+
|
|
339
|
+
expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("'unknown'"))
|
|
340
|
+
expect(result).toBe(state)
|
|
341
|
+
})
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
// ─── REMOVE_ADAPTER_ACTIONS ───────────────────────────────────────────────────
|
|
345
|
+
|
|
346
|
+
describe('REMOVE_ADAPTER_ACTIONS', () => {
|
|
347
|
+
it('removes completed actions from actionsArray', () => {
|
|
348
|
+
const action1 = { method: 'addDataset', parameters: ['roads'], actionId: 0 }
|
|
349
|
+
const action2 = { method: 'applyStyle', parameters: ['roads', {}], actionId: 1 }
|
|
350
|
+
const state = { ...makeState(), actionsArray: [action1, action2] }
|
|
351
|
+
|
|
352
|
+
const result = actions.REMOVE_ADAPTER_ACTIONS(state, [action1])
|
|
353
|
+
|
|
354
|
+
expect(result.actionsArray).toEqual([action2])
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
it('returns unchanged state when completedActions is empty', () => {
|
|
358
|
+
const state = makeState()
|
|
359
|
+
const result = actions.REMOVE_ADAPTER_ACTIONS(state, [])
|
|
360
|
+
expect(result).toBe(state)
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
it('returns unchanged state when completedActions is undefined', () => {
|
|
364
|
+
const state = makeState()
|
|
365
|
+
const result = actions.REMOVE_ADAPTER_ACTIONS(state, undefined)
|
|
366
|
+
expect(result).toBe(state)
|
|
367
|
+
})
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
// ─── actionId counter behaviour ───────────────────────────────────────────────
|
|
371
|
+
|
|
372
|
+
describe('actionId counter', () => {
|
|
373
|
+
it('resets actionId to 0 when actionsArray is empty', () => {
|
|
374
|
+
const state = makeStateWithDataset('roads')
|
|
375
|
+
const result = actions.SET_DATASET_VISIBILITY(state, { datasetId: 'roads', visible: false })
|
|
376
|
+
expect(result.actionsArray[0].actionId).toBe(0)
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
it('increments actionId for each successive queued action', () => {
|
|
380
|
+
const state = makeStateWithDataset('roads')
|
|
381
|
+
const state1 = actions.SET_DATASET_VISIBILITY(state, { datasetId: 'roads', visible: false })
|
|
382
|
+
const state2 = actions.SET_DATASET_VISIBILITY(state1, { datasetId: 'roads', visible: true })
|
|
383
|
+
|
|
384
|
+
expect(state2.actionsArray[1].actionId).toBe(1)
|
|
385
|
+
})
|
|
386
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { mappedDatasetsReducer } from '../../reducers/mappedDatasetsReducer.js'
|
|
2
|
+
import { datasets as datasetDefinitions } from '../../reducers/__data__/demoDatasets.js'
|
|
3
|
+
import { attachGlobalState } from '../globalDataset.js'
|
|
4
|
+
const { datasetRegistry } = jest.requireActual('../datasetRegistry.js')
|
|
5
|
+
const { mappedDatasets, orderedDatasets } = mappedDatasetsReducer({ datasets: datasetDefinitions })
|
|
6
|
+
|
|
7
|
+
const globalState = {
|
|
8
|
+
opacityMode: 'dataset',
|
|
9
|
+
opacity: 1,
|
|
10
|
+
visible: true
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// By adding jest.mock('<path-to>/datasetRegistry.js')
|
|
14
|
+
// to a test file, any import of datasetRegistry from that file will get this
|
|
15
|
+
// version with the demo datasets attached for testing.
|
|
16
|
+
// If we need to test against a different set of datasets
|
|
17
|
+
// we can import that config from demoDatasets.js (or roll our own)
|
|
18
|
+
// and attach it in the specific test
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
datasetRegistry.attach(mappedDatasets, orderedDatasets)
|
|
21
|
+
attachGlobalState(globalState)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
datasetRegistry.mockExtend = (extraDatasets) => datasetRegistry.attach(
|
|
25
|
+
{ ...mappedDatasets, ...extraDatasets },
|
|
26
|
+
[...orderedDatasets, ...Object.keys(extraDatasets)]
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
export { datasetRegistry }
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { datasetRegistry } from './datasetRegistry.js'
|
|
2
|
+
import { hasCustomVisualStyle } from '../initialise/defaults.js'
|
|
3
|
+
import { hasPattern } from '../../../../../src/utils/patternUtils.js'
|
|
4
|
+
import { DynamicGeoJson } from './dynamicGeoJson.js'
|
|
5
|
+
import { calculateOpacity, getGlobalVisibility } from './globalDataset.js'
|
|
6
|
+
|
|
7
|
+
export class Dataset {
|
|
8
|
+
constructor (dataset) {
|
|
9
|
+
this._datasetDefinition = dataset
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get id () { return this._datasetDefinition.id }
|
|
13
|
+
get label () { return this._datasetDefinition.label }
|
|
14
|
+
get hasSymbol () { return !this.hasSublayers && Boolean(this.style?.symbol) }
|
|
15
|
+
get hasPattern () { return !this.hasSublayers && !this.hasSymbol && hasPattern(this.style) }
|
|
16
|
+
get hasFill () { return !this.hasSublayers && !this.hasSymbol && (this.hasPattern || (this.style?.fill && this.style?.fill !== 'transparent')) }
|
|
17
|
+
get hasStroke () { return !this.hasSublayers && !this.hasSymbol && Boolean(this.style?.stroke) }
|
|
18
|
+
get tiles () { return this._datasetDefinition.tiles }
|
|
19
|
+
get geojson () { return this._datasetDefinition.geojson }
|
|
20
|
+
get idProperty () { return this._datasetDefinition.idProperty }
|
|
21
|
+
// TODO - handle transformRequest for non-dynamicGeoJSON as well (e.g. to add auth headers) --- IGNORE ---
|
|
22
|
+
// get transformRequest () { return this._datasetDefinition.transformRequest }
|
|
23
|
+
get parentId () { return this._datasetDefinition.parentId }
|
|
24
|
+
get minZoom () { return this._datasetDefinition.minZoom || this.parent?.minZoom }
|
|
25
|
+
get maxZoom () { return this._datasetDefinition.maxZoom || this.parent?.maxZoom }
|
|
26
|
+
get showInKey () { return this._datasetDefinition.showInKey || this.parent?.showInKey || false }
|
|
27
|
+
get groupLabel () { return this._datasetDefinition.groupLabel }
|
|
28
|
+
|
|
29
|
+
get opacity () {
|
|
30
|
+
const myOpacity = this.style?.opacity
|
|
31
|
+
const parentOpacity = this.parent?.style?.opacity
|
|
32
|
+
return calculateOpacity(myOpacity, parentOpacity)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get hasDynamicGeoJSON () {
|
|
36
|
+
return Boolean(this._datasetDefinition.dynamicGeoJSON)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get dynamicGeoJSON () {
|
|
40
|
+
return new DynamicGeoJson({
|
|
41
|
+
...this._datasetDefinition.dynamicGeoJSON,
|
|
42
|
+
id: this.id,
|
|
43
|
+
minZoom: this.minZoom
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get hiddenFeatures () { return this._datasetDefinition.hiddenFeatures }
|
|
48
|
+
get hasHiddenFeatures () { return Boolean(this.hiddenFeatures?.length > 0 || this.parent?.hasHiddenFeatures) }
|
|
49
|
+
|
|
50
|
+
get filter () {
|
|
51
|
+
return null // TODO - implement filter construction for esri and openLayers adapters
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Returns true if either the parent (if it has one) or global visibility is hidden , otherwise returns true.
|
|
55
|
+
// This is used to determine whether to show a tooltip
|
|
56
|
+
// TODO: also work out how to convey datasets hidden by zoom filter.
|
|
57
|
+
get isHiddenByInheritance () {
|
|
58
|
+
if (this.isSublayer) {
|
|
59
|
+
return !this.parent?.visible
|
|
60
|
+
}
|
|
61
|
+
return !getGlobalVisibility()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Returns true if this dataset is visible based on its own visibility setting,
|
|
65
|
+
// even if globalVisibility is false or its parent is not visible.
|
|
66
|
+
// This is used to determine whether the dataset is rendered as checked when
|
|
67
|
+
// disabled in the layers menu.
|
|
68
|
+
get isLocallyVisible () {
|
|
69
|
+
if (this.isVisible) {
|
|
70
|
+
return true
|
|
71
|
+
}
|
|
72
|
+
return this._datasetDefinition.visible
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get visible () {
|
|
76
|
+
if (this.isSublayer) {
|
|
77
|
+
return this._datasetDefinition.visible && (this.parent?.visible)
|
|
78
|
+
}
|
|
79
|
+
return this._datasetDefinition.visible && getGlobalVisibility()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
get symbolAnchor () {
|
|
83
|
+
if (this.style?.symbolAnchor) {
|
|
84
|
+
return this.style.symbolAnchor
|
|
85
|
+
}
|
|
86
|
+
return this.parent?.symbolAnchor
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get sourceLayer () {
|
|
90
|
+
if (this.isSublayer) {
|
|
91
|
+
return this.parent.sourceLayer
|
|
92
|
+
}
|
|
93
|
+
if (this.tiles) {
|
|
94
|
+
return this._datasetDefinition.sourceLayer
|
|
95
|
+
}
|
|
96
|
+
return undefined
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get isSublayer () {
|
|
100
|
+
return Boolean(this._datasetDefinition.parentId)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
get hasSublayers () {
|
|
104
|
+
return this._datasetDefinition.sublayerIds?.length > 0
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
get sublayerIds () {
|
|
108
|
+
return this._datasetDefinition.sublayerIds
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get sublayers () {
|
|
112
|
+
const { sublayerIds } = this
|
|
113
|
+
if (sublayerIds) {
|
|
114
|
+
return sublayerIds.map(id => datasetRegistry.getDataset(id))
|
|
115
|
+
}
|
|
116
|
+
return undefined
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
get parent () {
|
|
120
|
+
if (this._datasetDefinition.parentId) {
|
|
121
|
+
return datasetRegistry.getDataset(this._datasetDefinition.parentId)
|
|
122
|
+
}
|
|
123
|
+
return undefined
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
get style () {
|
|
127
|
+
const parentStyle = this.parent?.style
|
|
128
|
+
if (parentStyle) {
|
|
129
|
+
// Here - we must set the merge styles opacity to undefined before the specific child opacity
|
|
130
|
+
// so that we can correctly calculate opacity in the Dataset.opacity getter
|
|
131
|
+
// - otherwise if opacity mode multiply is set,
|
|
132
|
+
// any child with a parent opacity only would be multiplied by itself
|
|
133
|
+
return {
|
|
134
|
+
...parentStyle,
|
|
135
|
+
opacity: undefined,
|
|
136
|
+
...this._datasetDefinition.style,
|
|
137
|
+
symbolDescription: this.symbolDescription
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return this._datasetDefinition.style || {}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
get hasCustomVisualStyle () {
|
|
144
|
+
return hasCustomVisualStyle(this._datasetDefinition.style || {})
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
get symbolDescription () {
|
|
148
|
+
if (this._datasetDefinition.style?.symbolDescription) {
|
|
149
|
+
return this._datasetDefinition.style.symbolDescription
|
|
150
|
+
}
|
|
151
|
+
if (this.hasCustomVisualStyle) {
|
|
152
|
+
return undefined
|
|
153
|
+
}
|
|
154
|
+
return this.parent?.symbolDescription
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
get patternConfigs () {
|
|
158
|
+
const stylePatterns = this.hasPattern ? [this.style] : []
|
|
159
|
+
if (this.hasSublayers) {
|
|
160
|
+
return [...stylePatterns, ...this.sublayers.flatMap(sublayer => sublayer.patternConfigs)]
|
|
161
|
+
}
|
|
162
|
+
return stylePatterns
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
get symbolConfigs () {
|
|
166
|
+
const styleSymbols = this.hasSymbol ? [this.style] : []
|
|
167
|
+
if (this.hasSublayers) {
|
|
168
|
+
return [...styleSymbols, ...this.sublayers.flatMap(sublayer => sublayer.symbolConfigs)]
|
|
169
|
+
}
|
|
170
|
+
return styleSymbols
|
|
171
|
+
}
|
|
172
|
+
}
|