| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  | import FeatureSource from "./FeatureSource"; | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  | import {UIEventSource} from "../UIEventSource"; | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  | import LayerConfig from "../../Customizations/JSON/LayerConfig"; | 
					
						
							|  |  |  | import Loc from "../../Models/Loc"; | 
					
						
							| 
									
										
										
										
											2021-05-13 13:04:17 +02:00
										 |  |  | import Hash from "../Web/Hash"; | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  | import {TagsFilter} from "../Tags/TagsFilter"; | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default class FilteringFeatureSource implements FeatureSource { | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  |     public features: UIEventSource<{ feature: any; freshness: Date }[]> = | 
					
						
							|  |  |  |         new UIEventSource<{ feature: any; freshness: Date }[]>([]); | 
					
						
							|  |  |  |     public readonly name = "FilteringFeatureSource"; | 
					
						
							| 
									
										
										
										
											2021-02-20 01:45:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  |     constructor( | 
					
						
							|  |  |  |         layers: UIEventSource<{ | 
					
						
							| 
									
										
										
										
											2021-07-26 12:26:41 +02:00
										 |  |  |             isDisplayed: UIEventSource<boolean>; | 
					
						
							|  |  |  |             layerDef: LayerConfig; | 
					
						
							|  |  |  |             appliedFilters: UIEventSource<TagsFilter>; | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  |         }[]>, | 
					
						
							|  |  |  |         location: UIEventSource<Loc>, | 
					
						
							|  |  |  |         selectedElement: UIEventSource<any>, | 
					
						
							|  |  |  |         upstream: FeatureSource | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function update() { | 
					
						
							|  |  |  |             const layerDict = {}; | 
					
						
							|  |  |  |             if (layers.data.length == 0) { | 
					
						
							|  |  |  |                 console.warn("No layers defined!"); | 
					
						
							|  |  |  |                 return; | 
					
						
							| 
									
										
										
										
											2021-02-20 01:45:51 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  |             for (const layer of layers.data) { | 
					
						
							|  |  |  |                 const prev = layerDict[layer.layerDef.id] | 
					
						
							|  |  |  |                 if (prev !== undefined) { | 
					
						
							|  |  |  |                     // We have seen this layer before!
 | 
					
						
							|  |  |  |                     // We prefer the one which has a name
 | 
					
						
							|  |  |  |                     if (layer.layerDef.name === undefined) { | 
					
						
							|  |  |  |                         // This one is hidden, so we skip it
 | 
					
						
							|  |  |  |                         console.log("Ignoring layer selection from ", layer) | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 layerDict[layer.layerDef.id] = layer; | 
					
						
							| 
									
										
										
										
											2021-04-23 16:51:44 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-02-14 19:45:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  |             const features: { feature: any; freshness: Date }[] = | 
					
						
							|  |  |  |                 upstream.features.data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const missingLayers = new Set<string>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const newFeatures = features.filter((f) => { | 
					
						
							|  |  |  |                 const layerId = f.feature._matching_layer_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if ( | 
					
						
							|  |  |  |                     selectedElement.data?.id === f.feature.id || | 
					
						
							|  |  |  |                     f.feature.id === Hash.hash.data) { | 
					
						
							|  |  |  |                     // This is the selected object - it gets a free pass even if zoom is not sufficient or it is filtered away
 | 
					
						
							|  |  |  |                     return true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (layerId === undefined) { | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const layer: { | 
					
						
							|  |  |  |                     isDisplayed: UIEventSource<boolean>; | 
					
						
							|  |  |  |                     layerDef: LayerConfig; | 
					
						
							|  |  |  |                     appliedFilters: UIEventSource<TagsFilter>; | 
					
						
							|  |  |  |                 } = layerDict[layerId]; | 
					
						
							|  |  |  |                 if (layer === undefined) { | 
					
						
							|  |  |  |                     missingLayers.add(layerId); | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 const isShown = layer.layerDef.isShown; | 
					
						
							|  |  |  |                 const tags = f.feature.properties; | 
					
						
							|  |  |  |                 if (isShown.IsKnown(tags)) { | 
					
						
							|  |  |  |                     const result = layer.layerDef.isShown.GetRenderValue( | 
					
						
							|  |  |  |                         f.feature.properties | 
					
						
							|  |  |  |                     ).txt; | 
					
						
							|  |  |  |                     if (result !== "yes") { | 
					
						
							|  |  |  |                         return false; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 }  | 
					
						
							|  |  |  |                  | 
					
						
							|  |  |  |                 const tagsFilter = layer.appliedFilters.data; | 
					
						
							|  |  |  |                 if (tagsFilter) { | 
					
						
							|  |  |  |                     if (!tagsFilter.matchesProperties(f.feature.properties)) { | 
					
						
							|  |  |  |                         // Hidden by the filter on the layer itself - we want to hide it no matter wat
 | 
					
						
							|  |  |  |                         return false; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (!FilteringFeatureSource.showLayer(layer, location)) { | 
					
						
							|  |  |  |                     // The layer itself is either disabled or hidden due to zoom constraints
 | 
					
						
							|  |  |  |                     // We should return true, but it might still match some other layer
 | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2021-07-27 22:23:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  |             self.features.setData(newFeatures); | 
					
						
							|  |  |  |             if (missingLayers.size > 0) { | 
					
						
							|  |  |  |                 console.error( | 
					
						
							|  |  |  |                     "Some layers were not found: ", | 
					
						
							|  |  |  |                     Array.from(missingLayers) | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-07-26 12:26:41 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  |         upstream.features.addCallback(() => { | 
					
						
							|  |  |  |             update(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         location | 
					
						
							|  |  |  |             .map((l) => { | 
					
						
							|  |  |  |                 // We want something that is stable for the shown layers
 | 
					
						
							|  |  |  |                 const displayedLayerIndexes = []; | 
					
						
							|  |  |  |                 for (let i = 0; i < layers.data.length; i++) { | 
					
						
							|  |  |  |                     const layer = layers.data[i]; | 
					
						
							|  |  |  |                     if (l.zoom < layer.layerDef.minzoom) { | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                   | 
					
						
							|  |  |  |                     if (!layer.isDisplayed.data) { | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     displayedLayerIndexes.push(i); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return displayedLayerIndexes.join(","); | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             .addCallback(() => { | 
					
						
							|  |  |  |                 update(); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         layers.addCallback(update); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const registered = new Set<UIEventSource<boolean>>(); | 
					
						
							|  |  |  |         layers.addCallbackAndRun((layers) => { | 
					
						
							|  |  |  |             for (const layer of layers) { | 
					
						
							|  |  |  |                 if (registered.has(layer.isDisplayed)) { | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 registered.add(layer.isDisplayed); | 
					
						
							|  |  |  |                 layer.isDisplayed.addCallback(() => update()); | 
					
						
							|  |  |  |                 layer.appliedFilters.addCallback(() => update()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  |         update(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 19:39:57 +02:00
										 |  |  |     private static showLayer( | 
					
						
							|  |  |  |         layer: { | 
					
						
							|  |  |  |             isDisplayed: UIEventSource<boolean>; | 
					
						
							|  |  |  |             layerDef: LayerConfig; | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         location: UIEventSource<Loc> | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         return ( | 
					
						
							|  |  |  |             layer.isDisplayed.data && | 
					
						
							|  |  |  |             layer.layerDef.minzoomVisible <= location.data.zoom | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-26 12:26:41 +02:00
										 |  |  | } |