@@ -7,12 +7,14 @@ import circle from '@turf/circle'
7
7
import bboxPolygon from '@turf/bbox-polygon'
8
8
import intersects from '@turf/boolean-intersects'
9
9
import { featureEach } from '@turf/meta'
10
- import { unref } from 'vue'
10
+ import { unref , onBeforeMount , onBeforeUnmount } from 'vue'
11
11
import * as composables from '../../../core/client/composables/index.js'
12
- import { getFeatureId } from '../utils.js'
12
+ import * as utils from '../utils.js'
13
13
import { convertPolygonStyleToLeafletPath } from '../leaflet/utils/index.js'
14
14
15
15
export function useSelection ( name , options = { } ) {
16
+ // Data
17
+ let layerServiceEventListeners = { }
16
18
// Retrieve core selection
17
19
const selection = composables . useSelection ( name , options )
18
20
// Selection store, as we store options inside check if already initialized
@@ -29,8 +31,8 @@ export function useSelection (name, options = {}) {
29
31
if ( layer1 !== layer2 ) return false
30
32
// Then compare features
31
33
if ( item1 . feature && item2 . feature ) {
32
- const id1 = getFeatureId ( item1 . feature , item1 . layer )
33
- const id2 = getFeatureId ( item2 . feature , item2 . layer )
34
+ const id1 = utils . getFeatureId ( item1 . feature , item1 . layer )
35
+ const id2 = utils . getFeatureId ( item2 . feature , item2 . layer )
34
36
return id1 === id2
35
37
} else {
36
38
// If only one has a feature then it cannot be the same
@@ -70,13 +72,17 @@ export function useSelection (name, options = {}) {
70
72
activity . $engineEvents . off ( 'click' , onClicked )
71
73
if ( options . boxSelection ) activity . $engineEvents . off ( 'boxselectionend' , onBoxSelection )
72
74
if ( options . clusterSelection ) activity . $engineEvents . off ( 'spiderfied' , onClusterSelection )
75
+ activity . $engineEvents . off ( 'layer-added' , listenToFeaturesServiceEventsForLayer )
76
+ activity . $engineEvents . off ( 'layer-removed' , unlistenToFeaturesServiceEventsForLayer )
73
77
activity . $engineEvents . off ( 'layer-hidden' , onSelectedLayerHidden )
74
78
}
75
79
activity = newActivity
76
80
if ( newActivity && newActivity . $engineEvents ) {
77
81
newActivity . $engineEvents . on ( 'click' , onClicked )
78
82
if ( options . boxSelection ) newActivity . $engineEvents . on ( 'boxselectionend' , onBoxSelection )
79
83
if ( options . clusterSelection ) newActivity . $engineEvents . on ( 'spiderfied' , onClusterSelection )
84
+ newActivity . $engineEvents . on ( 'layer-added' , listenToFeaturesServiceEventsForLayer )
85
+ newActivity . $engineEvents . on ( 'layer-removed' , unlistenToFeaturesServiceEventsForLayer )
80
86
newActivity . $engineEvents . on ( 'layer-hidden' , onSelectedLayerHidden )
81
87
}
82
88
}
@@ -143,17 +149,20 @@ export function useSelection (name, options = {}) {
143
149
function getSelectedLocation ( ) {
144
150
return selection . getSelectedItem ( ) . location
145
151
}
146
- function isFeatureSelected ( feature , layer ) {
152
+ function findSelectedFeature ( feature , layer ) {
147
153
const items = selection . getSelectedItems ( )
148
154
for ( let i = 0 ; i < items . length ; i ++ ) {
149
155
const item = items [ i ]
150
156
if ( item . feature && item . layer && ( item . layer . name === layer . name ) ) {
151
- const selectedId = getFeatureId ( item . feature , item . layer )
152
- const featureId = getFeatureId ( feature , layer )
153
- if ( featureId === selectedId ) return true
157
+ const selectedId = utils . getFeatureId ( item . feature , item . layer )
158
+ const featureId = utils . getFeatureId ( feature , layer )
159
+ if ( featureId === selectedId ) return item
154
160
}
155
161
}
156
- return false
162
+ return null
163
+ }
164
+ function isFeatureSelected ( feature , layer ) {
165
+ return findSelectedFeature ( feature , layer ) !== null
157
166
}
158
167
function getWidgetForSelection ( ) {
159
168
let widget
@@ -341,8 +350,51 @@ export function useSelection (name, options = {}) {
341
350
const hiddenFeatures = selection . getSelectedItems ( ) . filter ( item => layer . name === _ . get ( item , 'layer.name' ) )
342
351
hiddenFeatures . forEach ( ( item ) => selection . unselectItem ( item ) )
343
352
}
353
+ function listenToFeaturesServiceEventsForLayer ( layer ) {
354
+ const listeners = utils . listenToFeaturesServiceEventsForLayer ( layer , {
355
+ all : onFeatureUpdated , removed : onFeatureRemoved
356
+ } , layerServiceEventListeners [ layer . _id ] )
357
+ if ( listeners ) layerServiceEventListeners [ layer . _id ] = listeners
358
+ }
359
+ function unlistenToFeaturesServiceEventsForLayer ( layer ) {
360
+ utils . unlistenToFeaturesServiceEventsForLayer ( layer , layerServiceEventListeners [ layer . _id ] )
361
+ delete layerServiceEventListeners [ layer . _id ]
362
+ }
363
+ function listenToFeaturesServiceEventsForLayers ( ) {
364
+ layerServiceEventListeners = { }
365
+ _ . forEach ( activity . getLayers ( ) , listenToFeaturesServiceEventsForLayer )
366
+ }
367
+ function unlistenToFeaturesServiceEventsForLayers ( ) {
368
+ _ . forOwn ( layerServiceEventListeners , unlistenToFeaturesServiceEventsForLayer )
369
+ layerServiceEventListeners = { }
370
+ }
371
+ function onFeatureUpdated ( feature , layer ) {
372
+ // Find related layer, either directly given in feature if coming from user-defined features service
373
+ // otherwise bound to the listener for features services attached to a built-in layer
374
+ if ( ! layer && feature . layer ) layer = activity . getLayerById ( feature . layer )
375
+ if ( ! layer ) return
376
+ const item = findSelectedFeature ( feature , layer )
377
+ if ( item ) Object . assign ( item . feature , feature )
378
+ }
379
+ function onFeatureRemoved ( feature , layer ) {
380
+ // Find related layer, either directly given in feature if coming from user-defined features service
381
+ // otherwise bound to the listener for features services attached to a built-in layer
382
+ if ( ! layer && feature . layer ) layer = activity . getLayerById ( feature . layer )
383
+ if ( ! layer ) return
384
+ const item = findSelectedFeature ( feature , layer )
385
+ if ( item ) selection . unselectItem ( item )
386
+ }
344
387
345
- // expose
388
+ // Here we need to listen to service events for all realtime layers
389
+ onBeforeMount ( ( ) => {
390
+ listenToFeaturesServiceEventsForLayers ( )
391
+ } )
392
+ // Cleanup on destroy
393
+ onBeforeUnmount ( ( ) => {
394
+ unlistenToFeaturesServiceEventsForLayers ( )
395
+ } )
396
+
397
+ // Expose
346
398
return {
347
399
...selection ,
348
400
getSelectionOptions : ( ) => get ( 'options' ) ,
0 commit comments