|
1 | 1 | import debounce from 'lodash.debounce' |
| 2 | +import { Feature as GeoJsonFeature } from 'geojson' |
2 | 3 | import { Style, Fill, Stroke } from 'ol/style' |
3 | | -import Overlay from 'ol/Overlay' |
4 | 4 | import { GeoJSON } from 'ol/format' |
5 | 5 | import { Feature } from 'ol' |
6 | | -import { Feature as GeoJsonFeature, GeoJsonProperties } from 'geojson' |
7 | 6 | import { PolarActionTree } from '@polar/lib-custom-types' |
8 | | -import getCluster from '@polar/lib-get-cluster' |
9 | | -import { getTooltip, Tooltip } from '@polar/lib-tooltip' |
10 | | -import { DragBox } from 'ol/interaction' |
11 | | -import { platformModifierKeyOnly } from 'ol/events/condition' |
12 | 7 | import { getFeatureDisplayLayer, clear } from '../../utils/displayFeatureLayer' |
13 | | -import { GfiGetters, GfiState } from '../../types' |
14 | | -import { getOriginalFeature } from '../../utils/getOriginalFeature' |
| 8 | +import { FeaturesByLayerId, GfiGetters, GfiState } from '../../types' |
| 9 | +import { filterFeatures } from '../../utils/filterFeatures' |
| 10 | +import { renderFeatures } from '../../utils/renderFeatures' |
15 | 11 | import { debouncedGfiRequest } from './debouncedGfiRequest' |
| 12 | +import { |
| 13 | + setupCoreListener, |
| 14 | + setupMultiSelection, |
| 15 | + setupTooltip, |
| 16 | + setupZoomListeners, |
| 17 | +} from './setup' |
16 | 18 |
|
17 | 19 | // OK for module action set creation |
18 | 20 | // eslint-disable-next-line max-lines-per-function |
@@ -67,131 +69,10 @@ export const makeActions = () => { |
67 | 69 | dispatch('setupZoomListeners') |
68 | 70 | dispatch('setupMultiSelection') |
69 | 71 | }, |
70 | | - setupCoreListener({ |
71 | | - getters: { gfiConfiguration }, |
72 | | - rootGetters, |
73 | | - dispatch, |
74 | | - }) { |
75 | | - if (gfiConfiguration.featureList?.bindWithCoreHoverSelect) { |
76 | | - this.watch( |
77 | | - () => rootGetters.selected, |
78 | | - (feature) => dispatch('setOlFeatureInformation', { feature }), |
79 | | - { deep: true } |
80 | | - ) |
81 | | - } |
82 | | - }, |
83 | | - setupMultiSelection({ dispatch, getters, rootGetters }) { |
84 | | - if (getters.gfiConfiguration.boxSelect) { |
85 | | - const dragBox = new DragBox({ condition: platformModifierKeyOnly }) |
86 | | - dragBox.on('boxend', () => |
87 | | - dispatch('getFeatureInfo', { |
88 | | - coordinateOrExtent: dragBox.getGeometry().getExtent(), |
89 | | - modifierPressed: true, |
90 | | - }) |
91 | | - ) |
92 | | - rootGetters.map.addInteraction(dragBox) |
93 | | - } |
94 | | - if (getters.gfiConfiguration.directSelect) { |
95 | | - rootGetters.map.on('click', ({ coordinate, originalEvent }) => |
96 | | - dispatch('getFeatureInfo', { |
97 | | - coordinateOrExtent: coordinate, |
98 | | - modifierPressed: |
99 | | - navigator.userAgent.indexOf('Mac') !== -1 |
100 | | - ? originalEvent.metaKey |
101 | | - : originalEvent.ctrlKey, |
102 | | - }) |
103 | | - ) |
104 | | - } |
105 | | - }, |
106 | | - setupZoomListeners({ dispatch, getters, rootGetters }) { |
107 | | - if (getters.gfiConfiguration.featureList) { |
108 | | - this.watch( |
109 | | - () => rootGetters.zoomLevel, |
110 | | - () => { |
111 | | - const { |
112 | | - featureInformation, |
113 | | - listableLayerSources, |
114 | | - visibleWindowFeatureIndex, |
115 | | - windowFeatures, |
116 | | - } = getters |
117 | | - |
118 | | - if (windowFeatures.length) { |
119 | | - const layerId: string = |
120 | | - // @ts-expect-error | if windowFeatures has features, visibleWindowFeatureIndex is in the range of possible features |
121 | | - windowFeatures[visibleWindowFeatureIndex].polarInternalLayerKey |
122 | | - const selectedFeatureProperties: GeoJsonProperties = { |
123 | | - // eslint-disable-next-line @typescript-eslint/naming-convention |
124 | | - _gfiLayerId: layerId, |
125 | | - ...featureInformation[layerId][visibleWindowFeatureIndex] |
126 | | - .properties, |
127 | | - } |
128 | | - const originalFeature = getOriginalFeature( |
129 | | - listableLayerSources, |
130 | | - selectedFeatureProperties |
131 | | - ) |
132 | | - if (originalFeature) { |
133 | | - dispatch('setOlFeatureInformation', { |
134 | | - feature: getCluster( |
135 | | - rootGetters.map, |
136 | | - originalFeature, |
137 | | - '_gfiLayerId' |
138 | | - ), |
139 | | - }) |
140 | | - } |
141 | | - } |
142 | | - } |
143 | | - ) |
144 | | - } |
145 | | - }, |
146 | | - setupTooltip({ getters: { gfiConfiguration }, rootGetters: { map } }) { |
147 | | - const tooltipLayerIds = Object.keys(gfiConfiguration.layers).filter( |
148 | | - (key) => gfiConfiguration.layers[key].showTooltip |
149 | | - ) |
150 | | - if (!tooltipLayerIds.length) { |
151 | | - return |
152 | | - } |
153 | | - |
154 | | - let element: Tooltip['element'], unregister: Tooltip['unregister'] |
155 | | - const overlay = new Overlay({ |
156 | | - positioning: 'bottom-center', |
157 | | - offset: [0, -5], |
158 | | - }) |
159 | | - map.addOverlay(overlay) |
160 | | - map.on('pointermove', ({ pixel, dragging, originalEvent }) => { |
161 | | - if (dragging || ['touch', 'pen'].includes(originalEvent.pointerType)) { |
162 | | - return |
163 | | - } |
164 | | - let hasFeatureAtPixel = false |
165 | | - // stops on return `true`, thus only using the uppermost feature |
166 | | - map.forEachFeatureAtPixel( |
167 | | - pixel, |
168 | | - (feature, layer) => { |
169 | | - if (!(feature instanceof Feature)) { |
170 | | - return false |
171 | | - } |
172 | | - hasFeatureAtPixel = true |
173 | | - overlay.setPosition(map.getCoordinateFromPixel(pixel)) |
174 | | - if (unregister) { |
175 | | - unregister() |
176 | | - } |
177 | | - ;({ element, unregister } = getTooltip({ |
178 | | - localeKeys: |
179 | | - // @ts-expect-error | it exists by virtue of layerFilter below |
180 | | - gfiConfiguration.layers[layer.get('id')].showTooltip( |
181 | | - feature, |
182 | | - map |
183 | | - ), |
184 | | - })) |
185 | | - overlay.setElement(element) |
186 | | - return true |
187 | | - }, |
188 | | - { layerFilter: (layer) => tooltipLayerIds.includes(layer.get('id')) } |
189 | | - ) |
190 | | - if (!hasFeatureAtPixel) { |
191 | | - overlay.setPosition(undefined) |
192 | | - } |
193 | | - }) |
194 | | - }, |
| 72 | + setupCoreListener, |
| 73 | + setupMultiSelection, |
| 74 | + setupTooltip, |
| 75 | + setupZoomListeners, |
195 | 76 | setupFeatureVisibilityUpdates({ commit, state, getters, rootGetters }) { |
196 | 77 | // debounce to prevent update spam |
197 | 78 | debouncedVisibilityChangeIndicator = debounce( |
@@ -283,6 +164,34 @@ export const makeActions = () => { |
283 | 164 | dispatch('setCoreSelection', { feature, centerOnFeature }) |
284 | 165 | } |
285 | 166 | }, |
| 167 | + setFeatureInformation( |
| 168 | + { commit, getters }, |
| 169 | + featuresByLayerId: FeaturesByLayerId |
| 170 | + ) { |
| 171 | + commit('clearFeatureInformation') |
| 172 | + commit('setVisibleWindowFeatureIndex', 0) |
| 173 | + clear(featureDisplayLayer) |
| 174 | + |
| 175 | + const filteredFeatures = Object.fromEntries( |
| 176 | + Object.entries(filterFeatures(featuresByLayerId)).map( |
| 177 | + ([layerId, features]) => { |
| 178 | + const { isSelectable } = getters.gfiConfiguration.layers[layerId] |
| 179 | + return [ |
| 180 | + layerId, |
| 181 | + typeof isSelectable === 'function' |
| 182 | + ? features.filter((feature) => isSelectable(feature)) |
| 183 | + : features, |
| 184 | + ] |
| 185 | + } |
| 186 | + ) |
| 187 | + ) |
| 188 | + commit('setFeatureInformation', filteredFeatures) |
| 189 | + renderFeatures( |
| 190 | + featureDisplayLayer, |
| 191 | + getters.geometryLayerKeys, |
| 192 | + filteredFeatures |
| 193 | + ) |
| 194 | + }, |
286 | 195 | hover({ commit, rootGetters }, feature: Feature) { |
287 | 196 | if (rootGetters.configuration.extendedMasterportalapiMarkers) { |
288 | 197 | commit('setHovered', feature, { root: true }) |
|
0 commit comments