forked from MapComplete/MapComplete
		
	More refactoring
This commit is contained in:
		
							parent
							
								
									6890c5189e
								
							
						
					
					
						commit
						c2d477c97a
					
				
					 12 changed files with 91 additions and 73 deletions
				
			
		| 
						 | 
				
			
			@ -25,20 +25,18 @@ import ScrollableFullScreen from "./UI/Base/ScrollableFullScreen";
 | 
			
		|||
import Translations from "./UI/i18n/Translations";
 | 
			
		||||
import MapControlButton from "./UI/MapControlButton";
 | 
			
		||||
import LZString from "lz-string";
 | 
			
		||||
import AllKnownLayers from "./Customizations/AllKnownLayers";
 | 
			
		||||
import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
 | 
			
		||||
import LeftControls from "./UI/BigComponents/LeftControls";
 | 
			
		||||
import RightControls from "./UI/BigComponents/RightControls";
 | 
			
		||||
import {LayoutConfigJson} from "./Models/ThemeConfig/Json/LayoutConfigJson";
 | 
			
		||||
import LayoutConfig from "./Models/ThemeConfig/LayoutConfig";
 | 
			
		||||
import LayerConfig from "./Models/ThemeConfig/LayerConfig";
 | 
			
		||||
import Minimap from "./UI/Base/Minimap";
 | 
			
		||||
import SelectedFeatureHandler from "./Logic/Actors/SelectedFeatureHandler";
 | 
			
		||||
import Combine from "./UI/Base/Combine";
 | 
			
		||||
import {SubtleButton} from "./UI/Base/SubtleButton";
 | 
			
		||||
import ShowTileInfo from "./UI/ShowDataLayer/ShowTileInfo";
 | 
			
		||||
import {Tiles} from "./Models/TileRange";
 | 
			
		||||
import {TileHierarchyAggregator} from "./UI/ShowDataLayer/PerTileCountAggregator";
 | 
			
		||||
import {TileHierarchyAggregator} from "./UI/ShowDataLayer/TileHierarchyAggregator";
 | 
			
		||||
import FilterConfig from "./Models/ThemeConfig/FilterConfig";
 | 
			
		||||
import FilteredLayer from "./Models/FilteredLayer";
 | 
			
		||||
import {BBox} from "./Logic/BBox";
 | 
			
		||||
| 
						 | 
				
			
			@ -435,6 +433,7 @@ export class InitUiElements {
 | 
			
		|||
            features: clusterCounter.getCountsForZoom(State.state.locationControl, State.state.layoutToUse.clustering.minNeededElements),
 | 
			
		||||
            leafletMap: State.state.leafletMap,
 | 
			
		||||
            layerToShow: ShowTileInfo.styling,
 | 
			
		||||
            enablePopups: false
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        State.state.featurePipeline = new FeaturePipeline(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ export default class TitleHandler {
 | 
			
		|||
                    if (layer.source.osmTags.matchesProperties(tags)) {
 | 
			
		||||
                        const tagsSource = state.allElements.getEventSourceById(tags.id)
 | 
			
		||||
                        const title = new TagRenderingAnswer(tagsSource, layer.title)
 | 
			
		||||
                        return new Combine([defaultTitle, " | ", title]).ConstructElement().innerText;
 | 
			
		||||
                        return new Combine([defaultTitle, " | ", title]).ConstructElement()?.innerText ?? defaultTitle;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return defaultTitle
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,11 +39,10 @@ export class ElementStorage {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    getEventSourceById(elementId): UIEventSource<any> {
 | 
			
		||||
        if (this._elements.has(elementId)) {
 | 
			
		||||
            return this._elements.get(elementId);
 | 
			
		||||
        if(elementId === undefined){
 | 
			
		||||
            return undefined;
 | 
			
		||||
        }
 | 
			
		||||
        console.error("Can not find eventsource with id ", elementId);
 | 
			
		||||
        return undefined;
 | 
			
		||||
            return this._elements.get(elementId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    has(id) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,11 +62,35 @@ export default class FeaturePipeline {
 | 
			
		|||
        /**
 | 
			
		||||
         * Maps tileid onto last download moment
 | 
			
		||||
         */
 | 
			
		||||
        const tileFreshnesses = new Map<number, Date>()
 | 
			
		||||
        const tileFreshnesses = new UIEventSource<Map<number, Date>>(new Map<number, Date>())
 | 
			
		||||
        const osmSourceZoomLevel = 14
 | 
			
		||||
        const useOsmApi = state.locationControl.map(l => l.zoom > (state.overpassMaxZoom.data ?? 12))
 | 
			
		||||
        this.relationTracker = new RelationsTracker()
 | 
			
		||||
 | 
			
		||||
        console.log("Tilefreshnesses are", tileFreshnesses.data)
 | 
			
		||||
        const oldestAllowedDate = new Date(new Date().getTime() - (60 * 60 * 24 * 30 * 1000));
 | 
			
		||||
        const neededTilesFromOsm = state.currentBounds.map(bbox => {
 | 
			
		||||
            if (bbox === undefined) {
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
            const range = bbox.containingTileRange(osmSourceZoomLevel)
 | 
			
		||||
            const tileIndexes = []
 | 
			
		||||
            if (range.total > 100) {
 | 
			
		||||
                // Too much tiles!
 | 
			
		||||
                return []
 | 
			
		||||
            }
 | 
			
		||||
            Tiles.MapRange(range, (x, y) => {
 | 
			
		||||
                const i = Tiles.tile_index(osmSourceZoomLevel, x, y);
 | 
			
		||||
                if (tileFreshnesses.data.get(i) > oldestAllowedDate) {
 | 
			
		||||
                    console.debug("Skipping tile", osmSourceZoomLevel, x, y, "as a decently fresh one is available")
 | 
			
		||||
                    // The cached tiles contain decently fresh data
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                tileIndexes.push(i)
 | 
			
		||||
            })
 | 
			
		||||
            return tileIndexes
 | 
			
		||||
        }, [tileFreshnesses])
 | 
			
		||||
        
 | 
			
		||||
        const updater = new OverpassFeatureSource(state,
 | 
			
		||||
            {
 | 
			
		||||
                relationTracker: this.relationTracker,
 | 
			
		||||
| 
						 | 
				
			
			@ -75,8 +99,9 @@ export default class FeaturePipeline {
 | 
			
		|||
                    // This callback contains metadata of the overpass call
 | 
			
		||||
                    const range = bbox.containingTileRange(osmSourceZoomLevel)
 | 
			
		||||
                    Tiles.MapRange(range, (x, y) => {
 | 
			
		||||
                        tileFreshnesses.set(Tiles.tile_index(osmSourceZoomLevel, x, y), freshness)
 | 
			
		||||
                        tileFreshnesses.data.set(Tiles.tile_index(osmSourceZoomLevel, x, y), freshness)
 | 
			
		||||
                    })
 | 
			
		||||
                    tileFreshnesses.ping();
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
| 
						 | 
				
			
			@ -137,17 +162,17 @@ export default class FeaturePipeline {
 | 
			
		|||
                    }, state)
 | 
			
		||||
 | 
			
		||||
                localStorage.tileFreshness.forEach((value, key) => {
 | 
			
		||||
                    if (tileFreshnesses.has(key)) {
 | 
			
		||||
                        const previous = tileFreshnesses.get(key)
 | 
			
		||||
                    if (tileFreshnesses.data.has(key)) {
 | 
			
		||||
                        const previous = tileFreshnesses.data.get(key)
 | 
			
		||||
                        if (value < previous) {
 | 
			
		||||
                            tileFreshnesses.set(key, value)
 | 
			
		||||
                            tileFreshnesses.data.set(key, value)
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        tileFreshnesses.set(key, value)
 | 
			
		||||
                        tileFreshnesses.data.set(key, value)
 | 
			
		||||
                    }
 | 
			
		||||
                    tileFreshnesses.ping()
 | 
			
		||||
                })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -178,30 +203,7 @@ export default class FeaturePipeline {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        console.log("Tilefreshnesses are", tileFreshnesses)
 | 
			
		||||
        const oldestAllowedDate = new Date(new Date().getTime() - (60 * 60 * 24 * 30 * 1000));
 | 
			
		||||
        
 | 
			
		||||
        const neededTilesFromOsm = state.currentBounds.map(bbox => {
 | 
			
		||||
            if (bbox === undefined) {
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
            const range = bbox.containingTileRange(osmSourceZoomLevel)
 | 
			
		||||
            const tileIndexes = []
 | 
			
		||||
            if (range.total > 100) {
 | 
			
		||||
                // Too much tiles!
 | 
			
		||||
                return []
 | 
			
		||||
            }
 | 
			
		||||
            Tiles.MapRange(range, (x, y) => {
 | 
			
		||||
                const i = Tiles.tile_index(osmSourceZoomLevel, x, y);
 | 
			
		||||
                if (tileFreshnesses.get(i) > oldestAllowedDate) {
 | 
			
		||||
                    console.debug("Skipping tile", osmSourceZoomLevel, x, y, "as a decently fresh one is available")
 | 
			
		||||
                    // The cached tiles contain decently fresh data
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                tileIndexes.push(i)
 | 
			
		||||
            })
 | 
			
		||||
            return tileIndexes
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
       const osmFeatureSource = new OsmFeatureSource({
 | 
			
		||||
            isActive: useOsmApi,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
 | 
			
		|||
        const layer = upstream.layer;
 | 
			
		||||
        
 | 
			
		||||
        function update() {
 | 
			
		||||
            
 | 
			
		||||
            const features: { feature: any; freshness: Date }[] = upstream.features.data;
 | 
			
		||||
            const newFeatures = features.filter((f) => {
 | 
			
		||||
                if (
 | 
			
		||||
| 
						 | 
				
			
			@ -60,11 +61,6 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
 | 
			
		|||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                if (!layer.isDisplayed) {
 | 
			
		||||
                    // 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;
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -75,20 +71,8 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
 | 
			
		|||
            update();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        layer.isDisplayed.addCallback(isShown => {
 | 
			
		||||
            if (isShown) {
 | 
			
		||||
                update();
 | 
			
		||||
            } else {
 | 
			
		||||
                self.features.setData([])
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        layer.appliedFilters.addCallback(_ => {
 | 
			
		||||
            if (!layer.isDisplayed.data) {
 | 
			
		||||
                // Currently not shown.
 | 
			
		||||
                // Note that a change in 'isSHown' will trigger an update as well, so we don't have to watch it another time
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            update()
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ export default class MetaTagging {
 | 
			
		|||
                        }
 | 
			
		||||
                        somethingChanged = somethingChanged || metatag.applyMetaTagsOnFeature(feature, freshness)
 | 
			
		||||
                    } catch (e) {
 | 
			
		||||
                        console.error("Could not calculate metatag for ", metatag.keys.join(","), ":", e)
 | 
			
		||||
                        console.error("Could not calculate metatag for ", metatag.keys.join(","), ":", e, e.stack)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,14 +149,13 @@ export class Changes {
 | 
			
		|||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public applyAction(action: OsmChangeAction) {
 | 
			
		||||
        action.Perform(this).then(changes => {
 | 
			
		||||
            console.log("Received changes:", changes)
 | 
			
		||||
            this.pendingChanges.data.push(...changes);
 | 
			
		||||
            this.pendingChanges.ping();
 | 
			
		||||
            this.allChanges.data.push(...changes)
 | 
			
		||||
            this.allChanges.ping()
 | 
			
		||||
        })
 | 
			
		||||
    public async applyAction(action: OsmChangeAction): Promise<void> {
 | 
			
		||||
        const changes = await action.Perform(this)
 | 
			
		||||
        console.log("Received changes:", changes)
 | 
			
		||||
        this.pendingChanges.data.push(...changes);
 | 
			
		||||
        this.pendingChanges.ping();
 | 
			
		||||
        this.allChanges.data.push(...changes)
 | 
			
		||||
        this.allChanges.ping()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private CreateChangesetObjects(changes: ChangeDescription[], downloadedOsmObjects: OsmObject[]): {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,9 @@ export class RegexTag extends TagsFilter {
 | 
			
		|||
        if (fromTag === undefined) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if(typeof fromTag === "number"){
 | 
			
		||||
            fromTag = "" + fromTag;
 | 
			
		||||
        }
 | 
			
		||||
        if (typeof possibleRegex === "string") {
 | 
			
		||||
            return fromTag === possibleRegex;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ import {Utils} from "../Utils";
 | 
			
		|||
 | 
			
		||||
export default class Constants {
 | 
			
		||||
 | 
			
		||||
    public static vNumber = "0.10.0-alpha-3";
 | 
			
		||||
    public static vNumber = "0.10.0-alpha-4";
 | 
			
		||||
    public static ImgurApiKey = '7070e7167f0a25a'
 | 
			
		||||
 | 
			
		||||
    // The user journey states thresholds when a new feature gets unlocked
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										36
									
								
								assets/layers/cluster_style/cluster_style.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								assets/layers/cluster_style/cluster_style.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
{
 | 
			
		||||
  "id": "cluster_style",
 | 
			
		||||
  "description": "The style for the clustering in all themes.",
 | 
			
		||||
  "source": {
 | 
			
		||||
    "osmTags": "tileId~*"
 | 
			
		||||
  },
 | 
			
		||||
  "color": {
 | 
			
		||||
    "render": "#3c3",
 | 
			
		||||
    "mappings": [
 | 
			
		||||
      {
 | 
			
		||||
        "if": "count>200",
 | 
			
		||||
        "then": "#f33"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "if": "count>100",
 | 
			
		||||
        "then": "#c93"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "if": "count>50",
 | 
			
		||||
        "then": "#cc3"
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "width": {
 | 
			
		||||
    "render": "1"
 | 
			
		||||
  },
 | 
			
		||||
  "label": {
 | 
			
		||||
    "render": "<div class='rounded-full text-xl font-bold' style='width: 2rem; height: 2rem; background: white'>{count}</div>",
 | 
			
		||||
    "mappings": [
 | 
			
		||||
      {
 | 
			
		||||
        "if": "count>99",
 | 
			
		||||
        "then": "<div class='rounded-full text-xl font-bold flex flex-col' style='width: 2.5rem; height: 2.5rem; background: white'>>99</div>"
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,7 @@
 | 
			
		|||
    "nl": "Een kaart om toeristisch relevante info op aan te duiden"
 | 
			
		||||
  },
 | 
			
		||||
  "description": {
 | 
			
		||||
    "nl": "Op deze kaart kan je info zien voor toeristen en zelf aanpasingen maken, zichtbaar voor iedereen"
 | 
			
		||||
    "nl": "Op deze kaart kan je info zien die relevant is voor toerisme, zoals:<br/><ul><li>Eetgelegenheden</li><li>Cafés en bars</li><li>(Fiets)oplaadpunten</li><li>Fietspompen, fietserverhuur en fietswinkels</li><li>Uitkijktorens</li><li>...</li></ul> Zie je fouten op de kaart? Dan kan je zelf makkelijk aanpasingen maken, die zichtbaar zijn voor iedereen. Hiervoor dien je een gratis OpenStreetMap account voor te maken.<br/><br/>Met de steun van Toerisme Vlaanderen<img src='./assets/themes/toerisme_vlaanderen/logo.png' />"
 | 
			
		||||
  },
 | 
			
		||||
  "icon": "./assets/svg/star.svg",
 | 
			
		||||
  "startZoom": 8,
 | 
			
		||||
| 
						 | 
				
			
			@ -39,9 +39,5 @@
 | 
			
		|||
    "binocular",
 | 
			
		||||
    "observation_tower"
 | 
			
		||||
  ],
 | 
			
		||||
  "overiddeAll": {
 | 
			
		||||
    "minZoomVisible": 0 
 | 
			
		||||
  },
 | 
			
		||||
  
 | 
			
		||||
  "hideFromOverview": true
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1008,7 +1008,7 @@
 | 
			
		|||
        "title": "Surveillance under Surveillance"
 | 
			
		||||
    },
 | 
			
		||||
    "toerisme_vlaanderen": {
 | 
			
		||||
        "description": "Op deze kaart kan je info zien voor toeristen en zelf aanpasingen maken, zichtbaar voor iedereen",
 | 
			
		||||
        "description": "Op deze kaart kan je info zien die relevant is voor toerisme, zoals:<br/><ul><li>Eetgelegenheden</li><li>Cafés en bars</li><li>(Fiets)oplaadpunten</li><li>Fietspompen, fietserverhuur en fietswinkels</li><li>Uitkijktorens</li><li>...</li></ul> Zie je fouten op de kaart? Dan kan je zelf makkelijk aanpasingen maken, die zichtbaar zijn voor iedereen. Hiervoor dien je een gratis OpenStreetMap account voor te maken.<br/><br/>Met de steun van Toerisme Vlaanderen<img src='./assets/themes/toerisme_vlaanderen/logo.png' />",
 | 
			
		||||
        "shortDescription": "Een kaart om toeristisch relevante info op aan te duiden",
 | 
			
		||||
        "title": "Toeristisch relevante info"
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue