@defra/interactive-map 0.0.30-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/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/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,483 @@
|
|
|
1
|
+
import { Dataset } from './dataset.js'
|
|
2
|
+
import { datasetRegistry } from './datasetRegistry.js'
|
|
3
|
+
import { attachGlobalState } from './globalDataset.js'
|
|
4
|
+
// Use the mock datasetRegistry with the demo datasets attached before each test
|
|
5
|
+
// so we can test Dataset methods that depend on parent/sublayer relationships and styles
|
|
6
|
+
jest.mock('./datasetRegistry.js')
|
|
7
|
+
|
|
8
|
+
const globalState = {
|
|
9
|
+
opacityMode: 'dataset',
|
|
10
|
+
opacity: 1,
|
|
11
|
+
visible: true
|
|
12
|
+
}
|
|
13
|
+
describe('Dataset class', () => {
|
|
14
|
+
describe('isSublayer', () => {
|
|
15
|
+
it('returns false for a top-level dataset', () => {
|
|
16
|
+
const dataset = datasetRegistry.getDataset('land-covers')
|
|
17
|
+
expect(dataset.isSublayer).toBe(false)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('returns true for a sublayer', () => {
|
|
21
|
+
const dataset = datasetRegistry.getDataset('land-covers-130-131')
|
|
22
|
+
expect(dataset.isSublayer).toBe(true)
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
describe('hasSublayers', () => {
|
|
27
|
+
it('returns true for a dataset that has sublayers', () => {
|
|
28
|
+
const dataset = datasetRegistry.getDataset('land-covers')
|
|
29
|
+
expect(dataset.hasSublayers).toBe(true)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('returns false for a dataset with no sublayers', () => {
|
|
33
|
+
const dataset = datasetRegistry.getDataset('hedge-control')
|
|
34
|
+
expect(dataset.hasSublayers).toBe(false)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('returns false for a dataset with an empty sublayerIds array', () => {
|
|
38
|
+
const dataset = new Dataset({ sublayerIds: [] })
|
|
39
|
+
expect(dataset.hasSublayers).toBe(false)
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('sublayers', () => {
|
|
44
|
+
it('returns undefined for a dataset with no sublayerIds', () => {
|
|
45
|
+
const dataset = datasetRegistry.getDataset('hedge-control')
|
|
46
|
+
expect(dataset.sublayers).toBeUndefined()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('returns a Dataset instance for each sublayer', () => {
|
|
50
|
+
const dataset = datasetRegistry.getDataset('land-covers')
|
|
51
|
+
expect(dataset.sublayers).toHaveLength(5)
|
|
52
|
+
dataset.sublayers.forEach(s => expect(s).toBeInstanceOf(Dataset))
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('returns sublayers for historic-monuments', () => {
|
|
56
|
+
const dataset = datasetRegistry.getDataset('historic-monuments')
|
|
57
|
+
expect(dataset.sublayers).toHaveLength(3)
|
|
58
|
+
dataset.sublayers.forEach(s => expect(s).toBeInstanceOf(Dataset))
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
describe('parent', () => {
|
|
63
|
+
it('returns undefined for a top-level dataset', () => {
|
|
64
|
+
const dataset = datasetRegistry.getDataset('land-covers')
|
|
65
|
+
expect(dataset.parent).toBeUndefined()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('returns a Dataset instance representing the parent for a sublayer', () => {
|
|
69
|
+
const dataset = datasetRegistry.getDataset('land-covers-130-131')
|
|
70
|
+
expect(dataset.parent).toBeInstanceOf(Dataset)
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
describe('style', () => {
|
|
75
|
+
it('returns the dataset style directly when there is no parent', () => {
|
|
76
|
+
const dataset = new Dataset({ style: { stroke: '#ff0000', fill: 'transparent' } })
|
|
77
|
+
expect(dataset.style).toEqual({ stroke: '#ff0000', fill: 'transparent' })
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('merges parent style with the sublayer style', () => {
|
|
81
|
+
const parentDef = { id: 'parent', style: { stroke: '#ff0000', strokeWidth: 2 } }
|
|
82
|
+
const childDef = { id: 'child', parentId: 'parent', style: { fill: 'blue' } }
|
|
83
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
84
|
+
|
|
85
|
+
const dataset = new Dataset(childDef)
|
|
86
|
+
expect(dataset.style).toMatchObject({ stroke: '#ff0000', strokeWidth: 2, fill: 'blue' })
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('overrides parent style properties with the sublayer own style', () => {
|
|
90
|
+
const parentDef = { id: 'parent', style: { stroke: '#ff0000' } }
|
|
91
|
+
const childDef = { id: 'child', parentId: 'parent', style: { stroke: '#00ff00' } }
|
|
92
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
93
|
+
|
|
94
|
+
const dataset = new Dataset(childDef)
|
|
95
|
+
expect(dataset.style.stroke).toBe('#00ff00')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('includes symbolDescription in the merged sublayer style', () => {
|
|
99
|
+
const parentDef = { id: 'parent', style: { stroke: '#ff0000' } }
|
|
100
|
+
const childDef = { id: 'child', parentId: 'parent', style: { symbolDescription: 'custom' } }
|
|
101
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
102
|
+
|
|
103
|
+
const dataset = new Dataset(childDef)
|
|
104
|
+
expect(dataset.style.symbolDescription).toBe('custom')
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
describe('hasCustomVisualStyle', () => {
|
|
109
|
+
it.each([
|
|
110
|
+
['stroke', { stroke: '#ff0000' }],
|
|
111
|
+
['fill', { fill: 'transparent' }],
|
|
112
|
+
['fillPattern', { fillPattern: 'dots' }],
|
|
113
|
+
['fillPatternSvgContent', { fillPatternSvgContent: '<svg/>' }],
|
|
114
|
+
['symbol', { symbol: 'square' }],
|
|
115
|
+
['symbolSvgContent', { symbolSvgContent: '<svg/>' }]
|
|
116
|
+
])('returns true when style contains %s', (_, style) => {
|
|
117
|
+
expect(new Dataset({ style }).hasCustomVisualStyle).toBe(true)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
it('returns false when style contains no visual style properties', () => {
|
|
121
|
+
const dataset = new Dataset({ style: { symbolBackgroundColor: '#ff0000', strokeWidth: 3 } })
|
|
122
|
+
expect(dataset.hasCustomVisualStyle).toBe(false)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('returns false when there is no style', () => {
|
|
126
|
+
const dataset = new Dataset({})
|
|
127
|
+
expect(dataset.hasCustomVisualStyle).toBe(false)
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
describe('symbolDescription', () => {
|
|
132
|
+
it("returns the dataset's own symbolDescription", () => {
|
|
133
|
+
const dataset = new Dataset({ style: { symbolDescription: 'a circle' } })
|
|
134
|
+
expect(dataset.symbolDescription).toBe('a circle')
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('returns undefined when the dataset has a custom visual style but no symbolDescription', () => {
|
|
138
|
+
const dataset = new Dataset({ style: { stroke: '#ff0000' } })
|
|
139
|
+
expect(dataset.symbolDescription).toBeUndefined()
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('returns undefined when the dataset has no style', () => {
|
|
143
|
+
const dataset = new Dataset({})
|
|
144
|
+
expect(dataset.symbolDescription).toBeUndefined()
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it("inherits the parent's symbolDescription when the sublayer has no custom visual style", () => {
|
|
148
|
+
const parentDef = { id: 'parent', style: { symbolDescription: 'parent symbol' } }
|
|
149
|
+
const childDef = { id: 'child', parentId: 'parent', style: {} }
|
|
150
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
151
|
+
|
|
152
|
+
const dataset = new Dataset(childDef)
|
|
153
|
+
expect(dataset.symbolDescription).toBe('parent symbol')
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('returns undefined when neither the sublayer nor the parent has a symbolDescription', () => {
|
|
157
|
+
const parentDef = { id: 'parent', style: { stroke: '#ff0000' } }
|
|
158
|
+
const childDef = { id: 'child', parentId: 'parent', style: {} }
|
|
159
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
160
|
+
|
|
161
|
+
// parent has a custom visual style (stroke) → parent.symbolDescription = undefined
|
|
162
|
+
// child has no visual style → inherits undefined from parent
|
|
163
|
+
const dataset = new Dataset(childDef)
|
|
164
|
+
expect(dataset.symbolDescription).toBeUndefined()
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
describe('label', () => {
|
|
169
|
+
it('returns the dataset label', () => {
|
|
170
|
+
const dataset = new Dataset({ label: 'My dataset' })
|
|
171
|
+
expect(dataset.label).toBe('My dataset')
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('returns undefined when no label is set', () => {
|
|
175
|
+
const dataset = new Dataset({})
|
|
176
|
+
expect(dataset.label).toBeUndefined()
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
describe('showInKey', () => {
|
|
181
|
+
it('returns true when showInKey is set on the dataset', () => {
|
|
182
|
+
const dataset = new Dataset({ showInKey: true })
|
|
183
|
+
expect(dataset.showInKey).toBe(true)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('returns false when showInKey is not set and there is no parent', () => {
|
|
187
|
+
const dataset = new Dataset({})
|
|
188
|
+
expect(dataset.showInKey).toBe(false)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
it('inherits showInKey from the parent when not set on the sublayer', () => {
|
|
192
|
+
const parentDef = { id: 'parent', showInKey: true, style: {} }
|
|
193
|
+
const childDef = { id: 'child', parentId: 'parent', style: {} }
|
|
194
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
195
|
+
expect(new Dataset(childDef).showInKey).toBe(true)
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('returns false when neither the sublayer nor the parent has showInKey set', () => {
|
|
199
|
+
const parentDef = { id: 'parent', style: {} }
|
|
200
|
+
const childDef = { id: 'child', parentId: 'parent', style: {} }
|
|
201
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
202
|
+
expect(new Dataset(childDef).showInKey).toBe(false)
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
describe('tiles, geojson, idProperty, parentId', () => {
|
|
207
|
+
it('returns tiles from the definition', () => {
|
|
208
|
+
const tiles = ['https://example.com/{z}/{x}/{y}']
|
|
209
|
+
const dataset = new Dataset({ tiles })
|
|
210
|
+
expect(dataset.tiles).toBe(tiles)
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('returns geojson from the definition', () => {
|
|
214
|
+
const geojson = { type: 'FeatureCollection', features: [] }
|
|
215
|
+
const dataset = new Dataset({ geojson })
|
|
216
|
+
expect(dataset.geojson).toBe(geojson)
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
it('returns idProperty from the definition', () => {
|
|
220
|
+
const dataset = new Dataset({ idProperty: 'gid' })
|
|
221
|
+
expect(dataset.idProperty).toBe('gid')
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
it('returns parentId from the definition', () => {
|
|
225
|
+
const dataset = new Dataset({ parentId: 'parent' })
|
|
226
|
+
expect(dataset.parentId).toBe('parent')
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
describe('minZoom / maxZoom', () => {
|
|
231
|
+
it('returns minZoom from the definition', () => {
|
|
232
|
+
const dataset = new Dataset({ minZoom: 8 })
|
|
233
|
+
expect(dataset.minZoom).toBe(8)
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
it('falls back to the parent minZoom when not set on the sublayer', () => {
|
|
237
|
+
const parentDef = { id: 'parent', minZoom: 10, style: {} }
|
|
238
|
+
const childDef = { id: 'child', parentId: 'parent', style: {} }
|
|
239
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
240
|
+
expect(new Dataset(childDef).minZoom).toBe(10)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it('returns maxZoom from the definition', () => {
|
|
244
|
+
const dataset = new Dataset({ maxZoom: 20 })
|
|
245
|
+
expect(dataset.maxZoom).toBe(20)
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
it('falls back to the parent maxZoom when not set on the sublayer', () => {
|
|
249
|
+
const parentDef = { id: 'parent', maxZoom: 22, style: {} }
|
|
250
|
+
const childDef = { id: 'child', parentId: 'parent', style: {} }
|
|
251
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
252
|
+
expect(new Dataset(childDef).maxZoom).toBe(22)
|
|
253
|
+
})
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
describe('opacity', () => {
|
|
257
|
+
const noOpacity = {
|
|
258
|
+
id: 'noOpacity'
|
|
259
|
+
}
|
|
260
|
+
const noOpacityChild = {
|
|
261
|
+
id: 'noOpacityChild',
|
|
262
|
+
parentId: 'noOpacity'
|
|
263
|
+
}
|
|
264
|
+
const opacityChild4 = {
|
|
265
|
+
id: 'opacityChild4',
|
|
266
|
+
parentId: 'noOpacity',
|
|
267
|
+
style: { opacity: 0.4 }
|
|
268
|
+
}
|
|
269
|
+
const zeroOpacity = {
|
|
270
|
+
id: 'zeroOpacity',
|
|
271
|
+
style: { opacity: 0 }
|
|
272
|
+
}
|
|
273
|
+
const opacity8 = {
|
|
274
|
+
id: 'opacity8',
|
|
275
|
+
style: { opacity: 0.8 }
|
|
276
|
+
}
|
|
277
|
+
const opacity8Child = {
|
|
278
|
+
id: 'opacity8Child',
|
|
279
|
+
parentId: 'opacity8',
|
|
280
|
+
style: { opacity: 0.4 }
|
|
281
|
+
}
|
|
282
|
+
const opacity8ChildNoOpacity = {
|
|
283
|
+
id: 'opacity8ChildNoOpacity',
|
|
284
|
+
parentId: 'opacity8'
|
|
285
|
+
}
|
|
286
|
+
beforeEach(() => {
|
|
287
|
+
datasetRegistry.attach({
|
|
288
|
+
zeroOpacity,
|
|
289
|
+
noOpacity,
|
|
290
|
+
noOpacityChild,
|
|
291
|
+
opacity8,
|
|
292
|
+
opacity8Child,
|
|
293
|
+
opacity8ChildNoOpacity,
|
|
294
|
+
opacityChild4
|
|
295
|
+
})
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
describe('with opacityMode set to "dataset"', () => {
|
|
299
|
+
it('returns global opacity when no opacity', () => {
|
|
300
|
+
expect(datasetRegistry.getDataset('noOpacity').opacity).toBe(1)
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
it('returns global opacity when no opacity is set in child or parent', () => {
|
|
304
|
+
expect(datasetRegistry.getDataset('noOpacityChild').opacity).toBe(1)
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
it('returns the specified opacity when opacity is set in child only', () => {
|
|
308
|
+
expect(datasetRegistry.getDataset('opacityChild4').opacity).toBe(0.4)
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
it('returns the specified opacity for a topLevel Dataset', () => {
|
|
312
|
+
expect(datasetRegistry.getDataset('opacity8').opacity).toBe(0.8)
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
it('returns the specified opacity when opacity is set in parent only', () => {
|
|
316
|
+
expect(datasetRegistry.getDataset('opacity8ChildNoOpacity').opacity).toBe(0.8)
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
it('returns the specified opacity for a child Dataset', () => {
|
|
320
|
+
expect(datasetRegistry.getDataset('opacity8Child').opacity).toBe(0.4)
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
it('returns 0 when opacity is explicitly set to 0', () => {
|
|
324
|
+
expect(datasetRegistry.getDataset('zeroOpacity').opacity).toBe(0)
|
|
325
|
+
})
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
describe('with opacityMode set to "multiply"', () => {
|
|
329
|
+
beforeEach(() => {
|
|
330
|
+
attachGlobalState({
|
|
331
|
+
...globalState,
|
|
332
|
+
opacityMode: 'multiply',
|
|
333
|
+
opacity: 0.75
|
|
334
|
+
})
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
it('returns global opacity when no opacity', () => {
|
|
338
|
+
expect(datasetRegistry.getDataset('noOpacity').opacity).toBe(0.75)
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
it('returns global opacity when no opacity is set in child or parent', () => {
|
|
342
|
+
expect(datasetRegistry.getDataset('noOpacityChild').opacity).toBe(0.75)
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
it('returns the multiplied opacity when opacity is set in child only', () => {
|
|
346
|
+
expect(datasetRegistry.getDataset('opacityChild4').opacity).toBe(0.3)
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
it('returns the multiplied opacity for a topLevel Dataset', () => {
|
|
350
|
+
// 0.8 (dataset opacity) * 0.75 (global opacity)
|
|
351
|
+
expect(datasetRegistry.getDataset('opacity8').opacity).toBe(0.6)
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
it('returns the multiplied opacity for a child Dataset', () => {
|
|
355
|
+
// 0.4 (dataset opacity) * 0.75 (global opacity) * 0.8 (parent dataset opacity)
|
|
356
|
+
expect(datasetRegistry.getDataset('opacity8Child').opacity).toBe(0.24)
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
it('returns 0 when opacity is explicitly set to 0', () => {
|
|
360
|
+
expect(datasetRegistry.getDataset('zeroOpacity').opacity).toBe(0)
|
|
361
|
+
})
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
describe('with opacityMode set to "global"', () => {
|
|
365
|
+
beforeEach(() => {
|
|
366
|
+
attachGlobalState({
|
|
367
|
+
...globalState,
|
|
368
|
+
opacityMode: 'global',
|
|
369
|
+
opacity: 0.6
|
|
370
|
+
})
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
it('returns the global opacity when no opacity', () => {
|
|
374
|
+
expect(datasetRegistry.getDataset('noOpacity').opacity).toBe(0.6)
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
it('returns the global opacity when no opacity is set in child or parent', () => {
|
|
378
|
+
expect(datasetRegistry.getDataset('noOpacityChild').opacity).toBe(0.6)
|
|
379
|
+
})
|
|
380
|
+
|
|
381
|
+
it('returns the global opacity for a topLevel Dataset', () => {
|
|
382
|
+
expect(datasetRegistry.getDataset('opacity8').opacity).toBe(0.6)
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
it('returns the global opacity for a child Dataset', () => {
|
|
386
|
+
expect(datasetRegistry.getDataset('opacity8Child').opacity).toBe(0.6)
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
it('returns global opacity when opacity is explicitly set to 0', () => {
|
|
390
|
+
expect(datasetRegistry.getDataset('zeroOpacity').opacity).toBe(0.6)
|
|
391
|
+
})
|
|
392
|
+
})
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
describe('hasDynamicGeoJSON', () => {
|
|
396
|
+
it('returns true when definition has a dynamicGeoJSON object', () => {
|
|
397
|
+
expect(datasetRegistry.getDataset('land-covers').hasDynamicGeoJSON).toBe(true)
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
it('returns false when definition does not have a dynamicGeoJSON object', () => {
|
|
401
|
+
expect(datasetRegistry.getDataset('historic-monuments').hasDynamicGeoJSON).toBe(false)
|
|
402
|
+
})
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
describe('hiddenFeatures / hasHiddenFeatures', () => {
|
|
406
|
+
it('returns hiddenFeatures from the definition', () => {
|
|
407
|
+
const dataset = new Dataset({ hiddenFeatures: [1, 2] })
|
|
408
|
+
expect(dataset.hiddenFeatures).toEqual([1, 2])
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
it('returns undefined when hiddenFeatures is not set', () => {
|
|
412
|
+
const dataset = new Dataset({})
|
|
413
|
+
expect(dataset.hiddenFeatures).toBeUndefined()
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
it('returns true from hasHiddenFeatures when hiddenFeatures is a non-empty array', () => {
|
|
417
|
+
const dataset = new Dataset({ hiddenFeatures: [42] })
|
|
418
|
+
expect(dataset.hasHiddenFeatures).toBe(true)
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
it('returns false from hasHiddenFeatures when hiddenFeatures is empty', () => {
|
|
422
|
+
const dataset = new Dataset({ hiddenFeatures: [] })
|
|
423
|
+
expect(dataset.hasHiddenFeatures).toBe(false)
|
|
424
|
+
})
|
|
425
|
+
|
|
426
|
+
it('returns false from hasHiddenFeatures when hiddenFeatures is not set', () => {
|
|
427
|
+
const dataset = new Dataset({})
|
|
428
|
+
expect(dataset.hasHiddenFeatures).toBe(false)
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
it('returns true from hasHiddenFeatures when the parent has hidden features', () => {
|
|
432
|
+
const parentDef = { id: 'parent', hiddenFeatures: [7], style: {} }
|
|
433
|
+
const childDef = { id: 'child', parentId: 'parent', style: {} }
|
|
434
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
435
|
+
expect(new Dataset(childDef).hasHiddenFeatures).toBe(true)
|
|
436
|
+
})
|
|
437
|
+
})
|
|
438
|
+
|
|
439
|
+
describe('filter', () => {
|
|
440
|
+
it('returns null', () => {
|
|
441
|
+
const dataset = new Dataset({ filter: ['==', ['get', 'type'], 'foo'] })
|
|
442
|
+
expect(dataset.filter).toBeNull()
|
|
443
|
+
})
|
|
444
|
+
})
|
|
445
|
+
|
|
446
|
+
describe('symbolAnchor', () => {
|
|
447
|
+
it('returns symbolAnchor from its own style', () => {
|
|
448
|
+
const dataset = new Dataset({ style: { symbolAnchor: [0.5, 1] } })
|
|
449
|
+
expect(dataset.symbolAnchor).toEqual([0.5, 1])
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
it('returns undefined when no symbolAnchor is set and there is no parent', () => {
|
|
453
|
+
const dataset = new Dataset({ style: {} })
|
|
454
|
+
expect(dataset.symbolAnchor).toBeUndefined()
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
it('inherits symbolAnchor from the parent when not set on the sublayer', () => {
|
|
458
|
+
const parentDef = { id: 'parent', style: { symbolAnchor: [0.1, 0.9] } }
|
|
459
|
+
const childDef = { id: 'child', parentId: 'parent', style: {} }
|
|
460
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
461
|
+
expect(new Dataset(childDef).symbolAnchor).toEqual([0.1, 0.9])
|
|
462
|
+
})
|
|
463
|
+
})
|
|
464
|
+
|
|
465
|
+
describe('sourceLayer', () => {
|
|
466
|
+
it('returns the sourceLayer from a tile-based top-level dataset', () => {
|
|
467
|
+
const dataset = new Dataset({ tiles: ['https://example.com/{z}/{x}/{y}'], sourceLayer: 'my_layer' })
|
|
468
|
+
expect(dataset.sourceLayer).toBe('my_layer')
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
it('returns undefined for a geojson dataset with no tiles', () => {
|
|
472
|
+
const dataset = new Dataset({ geojson: { type: 'FeatureCollection', features: [] } })
|
|
473
|
+
expect(dataset.sourceLayer).toBeUndefined()
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
it("returns the parent's sourceLayer for a sublayer", () => {
|
|
477
|
+
const parentDef = { id: 'parent', tiles: ['https://example.com/{z}/{x}/{y}'], sourceLayer: 'parent_layer', style: {} }
|
|
478
|
+
const childDef = { id: 'child', parentId: 'parent', style: {} }
|
|
479
|
+
datasetRegistry.attach({ parent: parentDef, child: childDef })
|
|
480
|
+
expect(new Dataset(childDef).sourceLayer).toBe('parent_layer')
|
|
481
|
+
})
|
|
482
|
+
})
|
|
483
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export class DatasetDefinitionCache {
|
|
2
|
+
constructor () {
|
|
3
|
+
this.idToDefinitionMap = new Map()
|
|
4
|
+
this.definitionToInstanceMap = new Map()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
add (registryDataset) {
|
|
8
|
+
this.idToDefinitionMap.set(registryDataset.id, registryDataset._datasetDefinition)
|
|
9
|
+
this.definitionToInstanceMap.set(registryDataset._datasetDefinition, registryDataset)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
invalidateDataset (registryDataset) {
|
|
13
|
+
const existingDefinition = this.idToDefinitionMap.get(registryDataset.id)
|
|
14
|
+
const allIds = [existingDefinition.id, ...(existingDefinition?.sublayerIds || [])]
|
|
15
|
+
allIds.forEach(id => {
|
|
16
|
+
const existingDefinition = this.idToDefinitionMap.get(id)
|
|
17
|
+
this.definitionToInstanceMap.delete(existingDefinition)
|
|
18
|
+
this.idToDefinitionMap.delete(id)
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
invalidateChangedDatasets (newDatasets) {
|
|
23
|
+
newDatasets.forEach((datasetDefinition) => {
|
|
24
|
+
const existingDefinition = this.idToDefinitionMap.get(datasetDefinition.id)
|
|
25
|
+
if (existingDefinition && existingDefinition !== datasetDefinition) {
|
|
26
|
+
const instance = this.definitionToInstanceMap.get(existingDefinition)
|
|
27
|
+
this.invalidateDataset(instance.isSublayer && instance.parent ? instance.parent : instance)
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getByDefinition (datasetDefinition) {
|
|
33
|
+
return this.definitionToInstanceMap.get(datasetDefinition)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { createDataset } from './createDataset.js'
|
|
2
|
+
import { DatasetDefinitionCache } from './datasetDefinitionCache.js'
|
|
3
|
+
|
|
4
|
+
const datasetRegistry = {
|
|
5
|
+
attach (datasetsRef, orderedDatasetsRef) {
|
|
6
|
+
this._datasets = datasetsRef
|
|
7
|
+
this._orderedDatasets = orderedDatasetsRef
|
|
8
|
+
this._invalidateChangedDatasets()
|
|
9
|
+
},
|
|
10
|
+
_definitionCache: new DatasetDefinitionCache(),
|
|
11
|
+
_invalidateCache () { // used in tests to clear the cache between runs
|
|
12
|
+
this._definitionCache = new DatasetDefinitionCache()
|
|
13
|
+
},
|
|
14
|
+
_invalidateChangedDatasets () { // used in tests to clear the cache between runs
|
|
15
|
+
if (this._datasets) {
|
|
16
|
+
this._definitionCache.invalidateChangedDatasets(Object.values(this._datasets))
|
|
17
|
+
} else {
|
|
18
|
+
this._invalidateCache()
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
// createDataset defaults to a generic dataset factory function, but can be overridden by calling
|
|
22
|
+
// attachCreateDataset, which allows the layer adapter to provide its own createDataset function,
|
|
23
|
+
attachCreateDataset (createDataset) { this._createDataset = createDataset },
|
|
24
|
+
_createDataset: (datasetDefinition) => createDataset(datasetDefinition),
|
|
25
|
+
|
|
26
|
+
// getDataset retrieves a dataset by id, creating a new Dataset instance that wraps the definition
|
|
27
|
+
getDataset (id) {
|
|
28
|
+
const definition = this.datasets[id]
|
|
29
|
+
if (!definition) {
|
|
30
|
+
return undefined
|
|
31
|
+
}
|
|
32
|
+
const cachedDefinition = this._definitionCache.getByDefinition(definition)
|
|
33
|
+
if (cachedDefinition) {
|
|
34
|
+
return cachedDefinition
|
|
35
|
+
}
|
|
36
|
+
const registryDataset = this._createDataset(definition)
|
|
37
|
+
this._definitionCache.add(registryDataset)
|
|
38
|
+
if (registryDataset.isSublayer) {
|
|
39
|
+
// Ensure the parent dataset is also cached
|
|
40
|
+
this.getDataset(registryDataset.parentId)
|
|
41
|
+
}
|
|
42
|
+
return registryDataset
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
forEach (callback) {
|
|
46
|
+
this._orderedDatasets.forEach((datasetId) => callback(this.getDataset(datasetId)))
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
forEachDataset (callback) {
|
|
50
|
+
Object.values(this.datasets)
|
|
51
|
+
.filter(def => !def.parentId) // Only top-level datasets
|
|
52
|
+
.forEach((dataset) => callback(this.getDataset(dataset.id)))
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
topLevelDatasets () {
|
|
56
|
+
return Object.values(this.datasets)
|
|
57
|
+
.filter(def => !def.parentId)
|
|
58
|
+
.map(def => this.getDataset(def.id))
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
getPatternAndSymbolConfigs () {
|
|
62
|
+
return this.topLevelDatasets().reduce((acc, dataset) => {
|
|
63
|
+
return {
|
|
64
|
+
...acc,
|
|
65
|
+
patternConfigs: [...acc.patternConfigs, ...dataset.patternConfigs],
|
|
66
|
+
symbolConfigs: [...acc.symbolConfigs, ...dataset.symbolConfigs]
|
|
67
|
+
}
|
|
68
|
+
}, { patternConfigs: [], symbolConfigs: [] })
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
_lastKeyItems: {},
|
|
72
|
+
keyItems () {
|
|
73
|
+
if (this.datasets === this._lastKeyItemsDatasets) {
|
|
74
|
+
return this._lastKeyItems
|
|
75
|
+
}
|
|
76
|
+
this._lastKeyItemsDatasets = this.datasets
|
|
77
|
+
const items = []
|
|
78
|
+
const seenGroups = new Set()
|
|
79
|
+
let hasGroups = false
|
|
80
|
+
this.forEachDataset((dataset) => {
|
|
81
|
+
if (!(dataset.showInKey && dataset.visible)) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
if (dataset.hasSublayers) {
|
|
85
|
+
const sublayers = dataset.sublayers.filter(sublayer => sublayer.visible)
|
|
86
|
+
if (sublayers.length) {
|
|
87
|
+
hasGroups = true
|
|
88
|
+
items.push({ type: 'sublayers', dataset, sublayers })
|
|
89
|
+
}
|
|
90
|
+
} else if (dataset.groupLabel) {
|
|
91
|
+
if (seenGroups.has(dataset.groupLabel)) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
seenGroups.add(dataset.groupLabel)
|
|
95
|
+
hasGroups = true
|
|
96
|
+
items.push({
|
|
97
|
+
type: 'group',
|
|
98
|
+
groupLabel: dataset.groupLabel,
|
|
99
|
+
datasets: this.topLevelDatasets()
|
|
100
|
+
.filter(groupDataset => (groupDataset.groupLabel === dataset.groupLabel && !groupDataset.hasSublayers && groupDataset.showInKey))
|
|
101
|
+
})
|
|
102
|
+
} else {
|
|
103
|
+
items.push({ type: 'flat', dataset })
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
this._lastKeyItems = { items, hasGroups }
|
|
107
|
+
return this._lastKeyItems
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
Object.defineProperty(datasetRegistry, 'datasets', { get: () => datasetRegistry._datasets })
|
|
112
|
+
|
|
113
|
+
// TODO remove this global reference once development is finished
|
|
114
|
+
window.datasetRegistry = datasetRegistry
|
|
115
|
+
|
|
116
|
+
export { datasetRegistry }
|