@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,191 @@
|
|
|
1
|
+
import { Dataset } from '../../../registry/dataset.js'
|
|
2
|
+
import { hashString } from '../../../../../../../src/utils/patternUtils.js'
|
|
3
|
+
import { anchorToMaplibre } from '../../../../../../../providers/maplibre/src/utils/symbolImages.js'
|
|
4
|
+
const MAX_TILE_ZOOM = 22
|
|
5
|
+
|
|
6
|
+
export class MapLibreDataset extends Dataset {
|
|
7
|
+
get visibility () { return this.visible ? 'visible' : 'none' }
|
|
8
|
+
|
|
9
|
+
get fillLayerId () {
|
|
10
|
+
if (this.hasSublayers) {
|
|
11
|
+
return null
|
|
12
|
+
}
|
|
13
|
+
if (this.hasSymbol) {
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
16
|
+
if (this.hasFill) {
|
|
17
|
+
return this.id
|
|
18
|
+
}
|
|
19
|
+
return null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get strokeLayerId () {
|
|
23
|
+
if (this.hasSublayers) {
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
26
|
+
if (this.hasSymbol) {
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
if (this.hasStroke) {
|
|
30
|
+
return this.hasFill ? `${this.id}-stroke` : this.id
|
|
31
|
+
}
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get symbolLayerId () {
|
|
36
|
+
if (this.hasSublayers) {
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
if (this.hasSymbol) {
|
|
40
|
+
return this.id
|
|
41
|
+
}
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get layerIds () {
|
|
46
|
+
if (this.hasSublayers) {
|
|
47
|
+
return this.sublayers.flatMap(sublayer => sublayer.layerIds).filter(Boolean)
|
|
48
|
+
}
|
|
49
|
+
return [this.symbolLayerId, this.fillLayerId, this.strokeLayerId].filter(Boolean)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getLayersWithValue (valueName, condition = false) {
|
|
53
|
+
const response = []
|
|
54
|
+
if (condition === false || this[condition]) {
|
|
55
|
+
const layerIds = [this.symbolLayerId, this.fillLayerId, this.strokeLayerId].filter(Boolean)
|
|
56
|
+
if (layerIds.length) {
|
|
57
|
+
const value = this[valueName]
|
|
58
|
+
response.push({ layerIds, [valueName]: value })
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (this.hasSublayers) {
|
|
63
|
+
this.sublayers.forEach((sublayer) => {
|
|
64
|
+
if (condition === false || sublayer[condition]) {
|
|
65
|
+
response.push(sublayer.getLayersWithValue(valueName)[0])
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
return response
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getLayersWithVisibility () {
|
|
73
|
+
return this.getLayersWithValue('visibility')
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getLayersWithOpacity () {
|
|
77
|
+
return this.getLayersWithValue('opacity')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getLayersWithFilters () {
|
|
81
|
+
return this.getLayersWithValue('filter', 'hasHiddenFeatures')
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get sourceId () {
|
|
85
|
+
if (this.isSublayer) { return this.parent.sourceId }
|
|
86
|
+
if (this.hasDynamicGeoJSON) { return this.dynamicGeoJSON.sourceId }
|
|
87
|
+
if (this.tiles) {
|
|
88
|
+
const tilesKey = Array.isArray(this.tiles) ? this.tiles.join(',') : this.tiles
|
|
89
|
+
return `tiles-${hashString(tilesKey)}`
|
|
90
|
+
}
|
|
91
|
+
if (this.geojson) {
|
|
92
|
+
if (typeof this.geojson === 'string') { return `geojson-${hashString(this.geojson)}` }
|
|
93
|
+
return `geojson-${this.id}`
|
|
94
|
+
}
|
|
95
|
+
return `source-${this.id}`
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
get source () {
|
|
99
|
+
if (this.hasDynamicGeoJSON) {
|
|
100
|
+
return this.dynamicGeoJSON.source
|
|
101
|
+
}
|
|
102
|
+
if (this.tiles) {
|
|
103
|
+
return {
|
|
104
|
+
type: 'vector',
|
|
105
|
+
tiles: this.tiles,
|
|
106
|
+
minzoom: this.minZoom || 0,
|
|
107
|
+
maxzoom: this.maxZoom || MAX_TILE_ZOOM
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (this.geojson) {
|
|
111
|
+
return { type: 'geojson', data: this.geojson, generateId: true }
|
|
112
|
+
}
|
|
113
|
+
return null
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
getSymbolSource (imageId, anchor, symbolDef) {
|
|
117
|
+
return {
|
|
118
|
+
id: this.symbolLayerId,
|
|
119
|
+
type: 'symbol',
|
|
120
|
+
source: this.sourceId,
|
|
121
|
+
'source-layer': this.sourceLayer,
|
|
122
|
+
minzoom: this.minZoom,
|
|
123
|
+
maxzoom: this.maxZoom,
|
|
124
|
+
layout: {
|
|
125
|
+
visibility: this.visibility,
|
|
126
|
+
'icon-image': imageId,
|
|
127
|
+
'icon-anchor': anchorToMaplibre(anchor || symbolDef?.anchor || [0.5, 0.5]),
|
|
128
|
+
'icon-allow-overlap': true
|
|
129
|
+
},
|
|
130
|
+
...(this.filter ? { filter: this.filter } : {})
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
getFillSource (paint) {
|
|
135
|
+
return {
|
|
136
|
+
id: this.fillLayerId,
|
|
137
|
+
type: 'fill',
|
|
138
|
+
source: this.sourceId,
|
|
139
|
+
'source-layer': this.sourceLayer,
|
|
140
|
+
minzoom: this.minZoom,
|
|
141
|
+
maxzoom: this.maxZoom,
|
|
142
|
+
layout: { visibility: this.visibility },
|
|
143
|
+
paint,
|
|
144
|
+
...(this.filter ? { filter: this.filter } : {})
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
getStrokeSource (paint) {
|
|
149
|
+
return {
|
|
150
|
+
id: this.strokeLayerId,
|
|
151
|
+
type: 'line',
|
|
152
|
+
source: this.sourceId,
|
|
153
|
+
'source-layer': this.sourceLayer,
|
|
154
|
+
minzoom: this.minZoom,
|
|
155
|
+
maxzoom: this.maxZoom,
|
|
156
|
+
layout: { visibility: this.visibility },
|
|
157
|
+
paint,
|
|
158
|
+
...(this.filter ? { filter: this.filter } : {})
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
get _hiddenFeaturesIdExpression () {
|
|
163
|
+
return this.hasDynamicGeoJSON ? this.dynamicGeoJSON.hiddenFeaturesIdExpression : ['to-string', ['id']]
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
get _hiddenFeaturesFilter () {
|
|
167
|
+
const hiddenFeatures = this.hiddenFeatures?.filter(id => id !== -1)
|
|
168
|
+
if (hiddenFeatures?.length) {
|
|
169
|
+
return ['!', ['in', this._hiddenFeaturesIdExpression, ['literal', hiddenFeatures.map(String)]]]
|
|
170
|
+
}
|
|
171
|
+
return null
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
get filter () {
|
|
175
|
+
const filter = ['all']
|
|
176
|
+
if (this.parent?.filter) {
|
|
177
|
+
filter.push(this.parent.filter)
|
|
178
|
+
}
|
|
179
|
+
if (this._datasetDefinition.filter) {
|
|
180
|
+
filter.push(this._datasetDefinition.filter)
|
|
181
|
+
}
|
|
182
|
+
const hiddenFeaturesFilter = this._hiddenFeaturesFilter
|
|
183
|
+
if (hiddenFeaturesFilter) {
|
|
184
|
+
filter.push(hiddenFeaturesFilter)
|
|
185
|
+
}
|
|
186
|
+
if (filter.length === 1) {
|
|
187
|
+
return null
|
|
188
|
+
}
|
|
189
|
+
return filter.length > 2 ? filter : filter[1]
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
import { MapLibreDataset } from './mapLibreDataset.js'
|
|
2
|
+
import { datasetRegistry } from '../../../registry/datasetRegistry.js'
|
|
3
|
+
// Use the mock datasetRegistry with the demo datasets attached before each test
|
|
4
|
+
// so we can test Dataset methods that depend on parent/sublayer relationships and styles
|
|
5
|
+
jest.mock('../../../registry/datasetRegistry.js')
|
|
6
|
+
|
|
7
|
+
describe('MapLibreDataset', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
datasetRegistry.attachCreateDataset(def => new MapLibreDataset(def))
|
|
10
|
+
datasetRegistry.mockExtend({
|
|
11
|
+
// layerIds
|
|
12
|
+
'ds-fill-only': { id: 'ds-fill-only', visible: true, minZoom: 10, maxZoom: 24, style: { fill: 'blue' } },
|
|
13
|
+
'ds-pattern-only': { id: 'ds-pattern-only', style: { fillPattern: 'dots' } },
|
|
14
|
+
'ds-transparent-fill': { id: 'ds-transparent-fill', style: { fill: 'transparent' } },
|
|
15
|
+
// shared: no special properties — used by layerIds, sourceId, source, visibility,
|
|
16
|
+
// _hiddenFeaturesIdExpression, _hiddenFeaturesFilter, and filter tests
|
|
17
|
+
'ds-bare': { id: 'ds-bare' },
|
|
18
|
+
'ds-no-id-prop': { id: 'ds-no-id-prop', geojson: 'https://example.com/data', transformRequest: () => {} },
|
|
19
|
+
'ds-no-transform': { id: 'ds-no-transform', geojson: 'https://example.com/data', idProperty: 'id' },
|
|
20
|
+
'ds-static-url': { id: 'ds-static-url', geojson: 'https://example.com/static.geojson' },
|
|
21
|
+
// shared: tiles with no zoom — used by source minzoom and maxzoom fallback tests
|
|
22
|
+
'ds-tiles-no-zoom': { id: 'ds-tiles-no-zoom', tiles: ['https://example.com/{z}/{x}/{y}'] },
|
|
23
|
+
// getSymbolSource/getFillSource/getStrokeSource 'has filter' tests use historic-monuments-prehistoric and existing-fields from demo data
|
|
24
|
+
// _hiddenFeaturesFilter — ds-hf-123 also reused in filter describe
|
|
25
|
+
'ds-hf-123': { id: 'ds-hf-123', hiddenFeatures: [1, 2, 3] },
|
|
26
|
+
'ds-hf-neg1': { id: 'ds-hf-neg1', hiddenFeatures: [-1, 5] },
|
|
27
|
+
'ds-hf-all-neg1': { id: 'ds-hf-all-neg1', hiddenFeatures: [-1] },
|
|
28
|
+
'ds-hf-empty': { id: 'ds-hf-empty', hiddenFeatures: [] },
|
|
29
|
+
// filter
|
|
30
|
+
'ds-combined': { id: 'ds-combined', filter: ['==', ['get', 'type'], 'foo'], hiddenFeatures: [5] }
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
describe('layerIds', () => {
|
|
35
|
+
it('returns [id] when dataset has a symbol (historic-monuments-prehistoric inherits symbol from parent)', () => {
|
|
36
|
+
const dataset = datasetRegistry.getDataset('historic-monuments-prehistoric')
|
|
37
|
+
expect(dataset.layerIds).toEqual(['historic-monuments-prehistoric'])
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('returns [id, id-stroke] when dataset has both fill and stroke (existing-fields)', () => {
|
|
41
|
+
const dataset = datasetRegistry.getDataset('existing-fields')
|
|
42
|
+
expect(dataset.layerIds).toEqual(['existing-fields', 'existing-fields-stroke'])
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('returns [id] when dataset has only fill', () => {
|
|
46
|
+
const dataset = datasetRegistry.getDataset('ds-fill-only')
|
|
47
|
+
expect(dataset.layerIds).toEqual(['ds-fill-only'])
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('returns [id] when dataset has only stroke (hedge-control)', () => {
|
|
51
|
+
const dataset = datasetRegistry.getDataset('hedge-control')
|
|
52
|
+
expect(dataset.layerIds).toEqual(['hedge-control'])
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('returns [id] when dataset has a fillPattern but no stroke', () => {
|
|
56
|
+
const dataset = datasetRegistry.getDataset('ds-pattern-only')
|
|
57
|
+
expect(dataset.layerIds).toEqual(['ds-pattern-only'])
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('returns [id, id-stroke] when dataset has fillPattern and stroke (land-covers-130-131)', () => {
|
|
61
|
+
const dataset = datasetRegistry.getDataset('land-covers-130-131')
|
|
62
|
+
expect(dataset.layerIds).toEqual(['land-covers-130-131', 'land-covers-130-131-stroke'])
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('returns null when fill is transparent and there is no stroke, symbol, or pattern', () => {
|
|
66
|
+
const dataset = datasetRegistry.getDataset('ds-transparent-fill')
|
|
67
|
+
expect(dataset.layerIds).toEqual([])
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('returns null when dataset has no fill, stroke, symbol, or pattern', () => {
|
|
71
|
+
const dataset = datasetRegistry.getDataset('ds-bare')
|
|
72
|
+
expect(dataset.layerIds).toEqual([])
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('returns the combined layerIds from all sublayers (historic-monuments)', () => {
|
|
76
|
+
const dataset = datasetRegistry.getDataset('historic-monuments')
|
|
77
|
+
expect(dataset.layerIds).toEqual([
|
|
78
|
+
'historic-monuments-prehistoric',
|
|
79
|
+
'historic-monuments-roman',
|
|
80
|
+
'historic-monuments-medieval'
|
|
81
|
+
])
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('returns the combined layerIds from all sublayers (land-covers)', () => {
|
|
85
|
+
const dataset = datasetRegistry.getDataset('land-covers')
|
|
86
|
+
expect(dataset.layerIds).toEqual([
|
|
87
|
+
'land-covers-130-131', 'land-covers-130-131-stroke',
|
|
88
|
+
'land-covers-332', 'land-covers-332-stroke',
|
|
89
|
+
'land-covers-110', 'land-covers-110-stroke',
|
|
90
|
+
'land-covers-379', 'land-covers-379-stroke',
|
|
91
|
+
'land-covers-other', 'land-covers-other-stroke'
|
|
92
|
+
])
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
describe('visibility', () => {
|
|
97
|
+
it('returns "visible" when visible is true', () => {
|
|
98
|
+
expect(datasetRegistry.getDataset('existing-fields').visibility).toBe('visible')
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('returns "none" when visible is false', () => {
|
|
102
|
+
expect(datasetRegistry.getDataset('hedge-control').visibility).toBe('none')
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
describe('getLayersWithVisibility', () => {
|
|
107
|
+
it('returns layerIds and visibility for a layer with sublayers', () => {
|
|
108
|
+
const registryDataset = datasetRegistry.getDataset('land-covers')
|
|
109
|
+
const layersWithVisibility = registryDataset.getLayersWithVisibility()
|
|
110
|
+
expect(layersWithVisibility).toEqual([
|
|
111
|
+
{ layerIds: ['land-covers-130-131', 'land-covers-130-131-stroke'], visibility: 'visible' },
|
|
112
|
+
{ layerIds: ['land-covers-332', 'land-covers-332-stroke'], visibility: 'visible' },
|
|
113
|
+
{ layerIds: ['land-covers-110', 'land-covers-110-stroke'], visibility: 'visible' },
|
|
114
|
+
{ layerIds: ['land-covers-379', 'land-covers-379-stroke'], visibility: 'none' },
|
|
115
|
+
{ layerIds: ['land-covers-other', 'land-covers-other-stroke'], visibility: 'visible' }
|
|
116
|
+
])
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
describe('getLayersWithOpacity', () => {
|
|
121
|
+
it('returns layerIds and opacity for a sublayer with no sublayers', () => {
|
|
122
|
+
const dataset = datasetRegistry.getDataset('existing-fields')
|
|
123
|
+
expect(dataset.getLayersWithOpacity()).toEqual([{ layerIds: ['existing-fields', 'existing-fields-stroke'], opacity: 1 }])
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('returns layerIds and opacity for a sublayer', () => {
|
|
127
|
+
const dataset = datasetRegistry.getDataset('land-covers-130-131')
|
|
128
|
+
const result = dataset.getLayersWithOpacity()
|
|
129
|
+
expect(result).toEqual([{ layerIds: ['land-covers-130-131', 'land-covers-130-131-stroke'], opacity: 1 }])
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it('returns layerIds and opacity for a sublayer with sublayers with specific opacity', () => {
|
|
133
|
+
const parentDef = { id: 'parent-ds', sublayerIds: ['parent-ds-sub'] }
|
|
134
|
+
const subDef = { id: 'parent-ds-sub', parentId: 'parent-ds', style: { stroke: '#ff0000', fill: '#00ff00', opacity: 0.75 } }
|
|
135
|
+
datasetRegistry.attach({ 'parent-ds': parentDef, 'parent-ds-sub': subDef })
|
|
136
|
+
const dataset = datasetRegistry.getDataset('parent-ds')
|
|
137
|
+
const result = dataset.getLayersWithOpacity()
|
|
138
|
+
expect(result).toEqual([{ layerIds: ['parent-ds-sub', 'parent-ds-sub-stroke'], opacity: 0.75 }])
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('returns layerIds and opacity for all sublayers', () => {
|
|
142
|
+
const dataset = datasetRegistry.getDataset('historic-monuments')
|
|
143
|
+
expect(dataset.getLayersWithOpacity()).toEqual([
|
|
144
|
+
{ layerIds: ['historic-monuments-prehistoric'], opacity: 1 },
|
|
145
|
+
{ layerIds: ['historic-monuments-roman'], opacity: 1 },
|
|
146
|
+
{ layerIds: ['historic-monuments-medieval'], opacity: 1 }
|
|
147
|
+
])
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
describe('fillLayerId, strokeLayerId, symbolLayerId — hasSublayers returns null', () => {
|
|
152
|
+
it('fillLayerId returns null for a dataset with sublayers', () => {
|
|
153
|
+
const dataset = datasetRegistry.getDataset('land-covers')
|
|
154
|
+
expect(dataset.fillLayerId).toBeNull()
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('strokeLayerId returns null for a dataset with sublayers', () => {
|
|
158
|
+
const dataset = datasetRegistry.getDataset('land-covers')
|
|
159
|
+
expect(dataset.strokeLayerId).toBeNull()
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('symbolLayerId returns null for a dataset with sublayers', () => {
|
|
163
|
+
const dataset = datasetRegistry.getDataset('land-covers')
|
|
164
|
+
expect(dataset.symbolLayerId).toBeNull()
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
describe('getLayersWithFilters', () => {
|
|
169
|
+
it('returns an empty array when there are no hidden features and no sublayers', () => {
|
|
170
|
+
const dataset = datasetRegistry.getDataset('existing-fields')
|
|
171
|
+
expect(dataset.getLayersWithFilters()).toEqual([])
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('returns an entry with layerIds and filter when the dataset has hidden features', () => {
|
|
175
|
+
const dataset = datasetRegistry.getDataset('land-covers-130-131')
|
|
176
|
+
expect(dataset.getLayersWithFilters()).toEqual([{
|
|
177
|
+
layerIds: ['land-covers-130-131', 'land-covers-130-131-stroke'],
|
|
178
|
+
filter: ['all',
|
|
179
|
+
['!', ['in', ['to-string', ['get', 'id']], ['literal', ['42']]]],
|
|
180
|
+
['in', ['get', 'dominant_land_cover'], ['literal', ['130', '131']]]]
|
|
181
|
+
}])
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
it('includes sublayer entries when a sublayer has hidden features', () => {
|
|
185
|
+
const parentDef = { id: 'parent-ds', sublayerIds: ['parent-ds-sub'] }
|
|
186
|
+
const subDef = { id: 'parent-ds-sub', parentId: 'parent-ds', hiddenFeatures: [7], style: { stroke: '#ff0000', fill: '#00ff00' } }
|
|
187
|
+
datasetRegistry.attach({ 'parent-ds': parentDef, 'parent-ds-sub': subDef })
|
|
188
|
+
const dataset = datasetRegistry.getDataset('parent-ds')
|
|
189
|
+
expect(dataset.getLayersWithFilters()).toEqual([{
|
|
190
|
+
layerIds: ['parent-ds-sub', 'parent-ds-sub-stroke'],
|
|
191
|
+
filter: ['!', ['in', ['to-string', ['id']], ['literal', ['7']]]]
|
|
192
|
+
}])
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it('returns an empty array when sublayers exist but none have hidden features', () => {
|
|
196
|
+
const dataset = datasetRegistry.getDataset('historic-monuments')
|
|
197
|
+
expect(dataset.getLayersWithFilters()).toEqual([])
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
describe('sourceId', () => {
|
|
202
|
+
it('returns the parent sourceId for a sublayer', () => {
|
|
203
|
+
const sublayer = datasetRegistry.getDataset('land-covers-130-131')
|
|
204
|
+
expect(sublayer.sourceId).toBe(datasetRegistry.getDataset('land-covers').sourceId)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
it('returns a tiles-based id for a tile dataset (array tiles)', () => {
|
|
208
|
+
const dataset = datasetRegistry.getDataset('existing-fields')
|
|
209
|
+
expect(dataset.sourceId).toBe('tiles-3delfuv')
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it('returns a tiles-based id when tiles is a plain string (line 76 non-array branch)', () => {
|
|
213
|
+
const dataset = datasetRegistry.getDataset('existing-fields')
|
|
214
|
+
expect(dataset.sourceId).toBe('tiles-3delfuv')
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
it('returns geojson-dynamic-{id} for a dynamic geojson source', () => {
|
|
218
|
+
expect(datasetRegistry.getDataset('land-covers').sourceId).toBe('geojson-dynamic-land-covers')
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
it('returns geojson-{hash} for a static string geojson url', () => {
|
|
222
|
+
expect(datasetRegistry.getDataset('ds-static-url').sourceId).toBe('geojson-1u4xay')
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
it('returns geojson-{id} for an object geojson source', () => {
|
|
226
|
+
const dataset = datasetRegistry.getDataset('historic-monuments')
|
|
227
|
+
expect(dataset.sourceId).toBe('geojson-historic-monuments')
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
it('returns source-{id} when there are no tiles and no geojson', () => {
|
|
231
|
+
expect(datasetRegistry.getDataset('ds-bare').sourceId).toBe('source-ds-bare')
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
describe('source', () => {
|
|
236
|
+
it('returns a vector source for a tile dataset', () => {
|
|
237
|
+
expect(datasetRegistry.getDataset('existing-fields').source).toEqual({
|
|
238
|
+
type: 'vector',
|
|
239
|
+
tiles: 'https://farming-tiles-702a60f45633.herokuapp.com/field_parcels_with_hedges/{z}/{x}/{y}',
|
|
240
|
+
minzoom: 10,
|
|
241
|
+
maxzoom: 24
|
|
242
|
+
})
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
it('falls back to 0/22 for minzoom/maxzoom when zoom is not set', () => {
|
|
246
|
+
expect(datasetRegistry.getDataset('ds-tiles-no-zoom').source).toEqual({
|
|
247
|
+
type: 'vector',
|
|
248
|
+
tiles: ['https://example.com/{z}/{x}/{y}'],
|
|
249
|
+
minzoom: 0,
|
|
250
|
+
maxzoom: 22
|
|
251
|
+
})
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
it('returns a geojson source with empty FeatureCollection for a dynamic geojson source', () => {
|
|
255
|
+
expect(datasetRegistry.getDataset('land-covers').source).toEqual({
|
|
256
|
+
type: 'geojson',
|
|
257
|
+
data: { type: 'FeatureCollection', features: [] },
|
|
258
|
+
generateId: true
|
|
259
|
+
})
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
it('returns a geojson source with the geojson data for an object geojson source', () => {
|
|
263
|
+
const dataset = datasetRegistry.getDataset('historic-monuments')
|
|
264
|
+
expect(dataset.source).toEqual({ type: 'geojson', data: dataset.geojson, generateId: true })
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it('returns null when there are no tiles and no geojson', () => {
|
|
268
|
+
expect(datasetRegistry.getDataset('ds-bare').source).toBeNull()
|
|
269
|
+
})
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
describe('getSymbolSource', () => {
|
|
273
|
+
const prehistoricBase = {
|
|
274
|
+
id: 'historic-monuments-prehistoric',
|
|
275
|
+
type: 'symbol',
|
|
276
|
+
source: 'geojson-historic-monuments',
|
|
277
|
+
'source-layer': undefined,
|
|
278
|
+
minzoom: 6, // datasetDefaults.minZoom applied to sublayer (parent's 10 is not inherited)
|
|
279
|
+
maxzoom: 24,
|
|
280
|
+
filter: ['in', ['get', 'category'], 'prehistoric']
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
it('returns a symbol layer spec with the correct shape', () => {
|
|
284
|
+
expect(datasetRegistry.getDataset('historic-monuments-prehistoric').getSymbolSource('my-icon', null, null)).toEqual({
|
|
285
|
+
...prehistoricBase,
|
|
286
|
+
layout: { visibility: 'visible', 'icon-image': 'my-icon', 'icon-anchor': 'center', 'icon-allow-overlap': true }
|
|
287
|
+
})
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('uses the provided anchor when given', () => {
|
|
291
|
+
expect(datasetRegistry.getDataset('historic-monuments-prehistoric').getSymbolSource('icon', [0.1, 0.9], null)).toEqual({
|
|
292
|
+
...prehistoricBase,
|
|
293
|
+
layout: { visibility: 'visible', 'icon-image': 'icon', 'icon-anchor': 'bottom-left', 'icon-allow-overlap': true }
|
|
294
|
+
})
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
it('falls back to symbolDef.anchor when no anchor is provided', () => {
|
|
298
|
+
expect(datasetRegistry.getDataset('historic-monuments-prehistoric').getSymbolSource('icon', null, { anchor: [0.5, 0] })).toEqual({
|
|
299
|
+
...prehistoricBase,
|
|
300
|
+
layout: { visibility: 'visible', 'icon-image': 'icon', 'icon-anchor': 'top', 'icon-allow-overlap': true }
|
|
301
|
+
})
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
it('does not include a filter property when filter is null', () => {
|
|
305
|
+
expect(datasetRegistry.getDataset('historic-monuments').getSymbolSource('icon', null, null)).toEqual({
|
|
306
|
+
id: null,
|
|
307
|
+
type: 'symbol',
|
|
308
|
+
source: 'geojson-historic-monuments',
|
|
309
|
+
'source-layer': undefined,
|
|
310
|
+
minzoom: 10,
|
|
311
|
+
maxzoom: 24,
|
|
312
|
+
layout: { visibility: 'visible', 'icon-image': 'icon', 'icon-anchor': 'center', 'icon-allow-overlap': true }
|
|
313
|
+
})
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
it('includes a filter property when the dataset has a filter', () => {
|
|
317
|
+
expect(datasetRegistry.getDataset('historic-monuments-prehistoric').getSymbolSource('icon', null, null)).toEqual({
|
|
318
|
+
...prehistoricBase,
|
|
319
|
+
layout: { visibility: 'visible', 'icon-image': 'icon', 'icon-anchor': 'center', 'icon-allow-overlap': true }
|
|
320
|
+
})
|
|
321
|
+
})
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
describe('getFillSource', () => {
|
|
325
|
+
const fillBase = {
|
|
326
|
+
id: 'ds-fill-only',
|
|
327
|
+
type: 'fill',
|
|
328
|
+
source: 'source-ds-fill-only',
|
|
329
|
+
'source-layer': undefined,
|
|
330
|
+
minzoom: 10,
|
|
331
|
+
maxzoom: 24,
|
|
332
|
+
layout: { visibility: 'visible' }
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
it('returns a fill layer spec with the correct shape', () => {
|
|
336
|
+
expect(datasetRegistry.getDataset('ds-fill-only').getFillSource({ 'fill-color': '#ff0000' })).toEqual({
|
|
337
|
+
...fillBase,
|
|
338
|
+
paint: { 'fill-color': '#ff0000' }
|
|
339
|
+
})
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
it('does not include a filter property when filter is null', () => {
|
|
343
|
+
expect(datasetRegistry.getDataset('ds-fill-only').getFillSource({})).toEqual({ ...fillBase, paint: {} })
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
it('includes a filter property when the dataset has a filter', () => {
|
|
347
|
+
expect(datasetRegistry.getDataset('existing-fields').getFillSource({})).toEqual({
|
|
348
|
+
id: 'existing-fields',
|
|
349
|
+
type: 'fill',
|
|
350
|
+
source: 'tiles-3delfuv',
|
|
351
|
+
'source-layer': 'field_parcels_filtered',
|
|
352
|
+
minzoom: 10,
|
|
353
|
+
maxzoom: 24,
|
|
354
|
+
layout: { visibility: 'visible' },
|
|
355
|
+
paint: {},
|
|
356
|
+
filter: ['all', ['==', ['get', 'sbi'], '106223377'], ['==', ['get', 'is_dominant_land_cover'], true]]
|
|
357
|
+
})
|
|
358
|
+
})
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
describe('getStrokeSource', () => {
|
|
362
|
+
it('returns a line layer spec with the correct shape', () => {
|
|
363
|
+
expect(datasetRegistry.getDataset('hedge-control')
|
|
364
|
+
.getStrokeSource({ 'line-color': '#ff0000', 'line-width': 2 }))
|
|
365
|
+
.toEqual({
|
|
366
|
+
id: 'hedge-control',
|
|
367
|
+
type: 'line',
|
|
368
|
+
source: 'tiles-3delfuv',
|
|
369
|
+
'source-layer': 'hedge_control',
|
|
370
|
+
minzoom: 10,
|
|
371
|
+
maxzoom: 24,
|
|
372
|
+
layout: { visibility: 'none' },
|
|
373
|
+
paint: { 'line-color': '#ff0000', 'line-width': 2 }
|
|
374
|
+
})
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
it('includes a filter property when the dataset has a filter', () => {
|
|
378
|
+
expect(datasetRegistry.getDataset('existing-fields')
|
|
379
|
+
.getStrokeSource({}))
|
|
380
|
+
.toEqual({
|
|
381
|
+
id: 'existing-fields-stroke',
|
|
382
|
+
type: 'line',
|
|
383
|
+
source: 'tiles-3delfuv',
|
|
384
|
+
'source-layer': 'field_parcels_filtered',
|
|
385
|
+
minzoom: 10,
|
|
386
|
+
maxzoom: 24,
|
|
387
|
+
layout: { visibility: 'visible' },
|
|
388
|
+
paint: {},
|
|
389
|
+
filter: ['all', ['==', ['get', 'sbi'], '106223377'], ['==', ['get', 'is_dominant_land_cover'], true]]
|
|
390
|
+
})
|
|
391
|
+
})
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
describe('_hiddenFeaturesIdExpression', () => {
|
|
395
|
+
it('uses get(idProperty) when idProperty is set', () => {
|
|
396
|
+
expect(datasetRegistry.getDataset('land-covers')._hiddenFeaturesIdExpression).toEqual(['to-string', ['get', 'id']])
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
it('uses the feature id when idProperty is not set', () => {
|
|
400
|
+
expect(datasetRegistry.getDataset('ds-bare')._hiddenFeaturesIdExpression).toEqual(['to-string', ['id']])
|
|
401
|
+
})
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
describe('filter', () => {
|
|
405
|
+
it('returns null when there is no filter and no hidden features', () => {
|
|
406
|
+
expect(datasetRegistry.getDataset('ds-bare').filter).toBeNull()
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
it('returns the own filter directly when it is the only filter', () => {
|
|
410
|
+
expect(datasetRegistry.getDataset('historic-monuments-prehistoric').filter)
|
|
411
|
+
.toEqual(['in', ['get', 'category'], 'prehistoric'])
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
it('returns ["all", parentFilter, ownFilter] when both parent and own filter are present', () => {
|
|
415
|
+
const parentFilter = ['==', ['get', 'cat'], 'a']
|
|
416
|
+
const childFilter = ['==', ['get', 'sub'], 'b']
|
|
417
|
+
const parentDef = { id: 'p-filter', filter: parentFilter, sublayerIds: ['p-filter-child'] }
|
|
418
|
+
const childDef = { id: 'p-filter-child', parentId: 'p-filter', filter: childFilter }
|
|
419
|
+
datasetRegistry.attach({ 'p-filter': parentDef, 'p-filter-child': childDef })
|
|
420
|
+
const dataset = datasetRegistry.getDataset('p-filter-child')
|
|
421
|
+
expect(dataset.filter).toEqual(['all', parentFilter, childFilter])
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
it('returns the hidden features filter directly when it is the only filter', () => {
|
|
425
|
+
expect(datasetRegistry.getDataset('ds-hf-123').filter)
|
|
426
|
+
.toEqual(['!', ['in', ['to-string', ['id']], ['literal', ['1', '2', '3']]]])
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
it('returns ["all", ...] when both own filter and hidden features filter are present', () => {
|
|
430
|
+
const { filter } = datasetRegistry.getDataset('ds-combined')
|
|
431
|
+
expect(filter).toEqual([
|
|
432
|
+
'all',
|
|
433
|
+
['==', ['get', 'type'], 'foo'],
|
|
434
|
+
[
|
|
435
|
+
'!',
|
|
436
|
+
['in', ['to-string', ['id']], ['literal', ['5']]]
|
|
437
|
+
]
|
|
438
|
+
])
|
|
439
|
+
})
|
|
440
|
+
})
|
|
441
|
+
})
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export const addDataset = ({ pluginState, mapState }, dataset) => {
|
|
4
|
-
pluginState.layerAdapter?.addDataset({ ...datasetDefaults, ...dataset }, mapState.mapStyle)
|
|
5
|
-
pluginState.dispatch({ type: 'ADD_DATASET', payload: { dataset, datasetDefaults } })
|
|
1
|
+
export const addDataset = ({ pluginState: { dispatch }, mapState }, dataset) => {
|
|
2
|
+
dispatch({ type: 'ADD_DATASET', payload: { dataset, mapStyle: mapState.mapStyle } })
|
|
6
3
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { addDataset } from './addDataset.js'
|
|
2
|
+
|
|
3
|
+
describe('addDataset', () => {
|
|
4
|
+
it('dispatches ADD_DATASET with the dataset and mapStyle', () => {
|
|
5
|
+
const dispatch = jest.fn()
|
|
6
|
+
const dataset = { id: 'my-dataset', label: 'My Dataset' }
|
|
7
|
+
const mapState = { mapStyle: { version: 8, layers: [] } }
|
|
8
|
+
|
|
9
|
+
addDataset({ pluginState: { dispatch }, mapState }, dataset)
|
|
10
|
+
|
|
11
|
+
expect(dispatch).toHaveBeenCalledWith({
|
|
12
|
+
type: 'ADD_DATASET',
|
|
13
|
+
payload: { dataset, mapStyle: mapState.mapStyle }
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
})
|