forked from MapComplete/MapComplete
		
	Add mssing assets
This commit is contained in:
		
							parent
							
								
									c2d477c97a
								
							
						
					
					
						commit
						09897b47e0
					
				
					 11 changed files with 104 additions and 89 deletions
				
			
		|  | @ -2,7 +2,6 @@ import {UIEventSource} from "../UIEventSource"; | |||
| import Loc from "../../Models/Loc"; | ||||
| import {Or} from "../Tags/Or"; | ||||
| import {Overpass} from "../Osm/Overpass"; | ||||
| import Bounds from "../../Models/Bounds"; | ||||
| import FeatureSource from "../FeatureSource/FeatureSource"; | ||||
| import {Utils} from "../../Utils"; | ||||
| import {TagsFilter} from "../Tags/TagsFilter"; | ||||
|  | @ -36,16 +35,17 @@ export default class OverpassFeatureSource implements FeatureSource { | |||
|      * If the map location changes, we check for each layer if it is loaded: | ||||
|      * we start checking the bounds at the first zoom level the layer might operate. If in bounds - no reload needed, otherwise we continue walking down | ||||
|      */ | ||||
|     private readonly _previousBounds: Map<number, Bounds[]> = new Map<number, Bounds[]>(); | ||||
|     private readonly _previousBounds: Map<number, BBox[]> = new Map<number, BBox[]>(); | ||||
|     private readonly state: { | ||||
|         readonly locationControl: UIEventSource<Loc>, | ||||
|         readonly layoutToUse: LayoutConfig, | ||||
|         readonly overpassUrl: UIEventSource<string>; | ||||
|         readonly overpassUrl: UIEventSource<string[]>; | ||||
|         readonly overpassTimeout: UIEventSource<number>; | ||||
|         readonly currentBounds: UIEventSource<BBox> | ||||
|     } | ||||
|     private readonly _isActive: UIEventSource<boolean>; | ||||
|     private _onUpdated?: (bbox: BBox, dataFreshness: Date) => void; | ||||
| 
 | ||||
|     /** | ||||
|      * The most important layer should go first, as that one gets first pick for the questions | ||||
|      */ | ||||
|  | @ -53,16 +53,16 @@ export default class OverpassFeatureSource implements FeatureSource { | |||
|         state: { | ||||
|             readonly locationControl: UIEventSource<Loc>, | ||||
|             readonly layoutToUse: LayoutConfig, | ||||
|             readonly overpassUrl: UIEventSource<string>; | ||||
|             readonly overpassUrl: UIEventSource<string[]>; | ||||
|             readonly overpassTimeout: UIEventSource<number>; | ||||
|             readonly overpassMaxZoom: UIEventSource<number>, | ||||
|             readonly currentBounds: UIEventSource<BBox> | ||||
|         }, | ||||
|          | ||||
|         options?: { | ||||
|             isActive?: UIEventSource<boolean>, | ||||
|             onUpdated?: (bbox: BBox, freshness: Date) => void, | ||||
|        relationTracker: RelationsTracker}) { | ||||
|             relationTracker: RelationsTracker | ||||
|         }) { | ||||
| 
 | ||||
|         this.state = state | ||||
|         this._isActive = options.isActive; | ||||
|  | @ -86,7 +86,7 @@ export default class OverpassFeatureSource implements FeatureSource { | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private GetFilter(): Overpass { | ||||
|     private GetFilter(interpreterUrl: string): Overpass { | ||||
|         let filters: TagsFilter[] = []; | ||||
|         let extraScripts: string[] = []; | ||||
|         for (const layer of this.state.layoutToUse.layers) { | ||||
|  | @ -113,7 +113,7 @@ export default class OverpassFeatureSource implements FeatureSource { | |||
|                     continue; | ||||
|                 } | ||||
|                 for (const previousLoadedBound of previousLoadedBounds) { | ||||
|                     previouslyLoaded = previouslyLoaded || this.IsInBounds(previousLoadedBound); | ||||
|                     previouslyLoaded = previouslyLoaded || this.state.currentBounds.data.isContainedIn(previousLoadedBound); | ||||
|                     if (previouslyLoaded) { | ||||
|                         break; | ||||
|                     } | ||||
|  | @ -133,7 +133,7 @@ export default class OverpassFeatureSource implements FeatureSource { | |||
|         if (filters.length + extraScripts.length === 0) { | ||||
|             return undefined; | ||||
|         } | ||||
|         return new Overpass(new Or(filters), extraScripts, this.state.overpassUrl, this.state.overpassTimeout, this.relationsTracker); | ||||
|         return new Overpass(new Or(filters), extraScripts, interpreterUrl, this.state.overpassTimeout, this.relationsTracker); | ||||
|     } | ||||
| 
 | ||||
|     private update() { | ||||
|  | @ -166,47 +166,50 @@ export default class OverpassFeatureSource implements FeatureSource { | |||
|         if (bounds === undefined) { | ||||
|             return undefined; | ||||
|         } | ||||
| 
 | ||||
|         const n = Math.min(90, bounds.getNorth()); | ||||
|         const e = Math.min(180, bounds.getEast()); | ||||
|         const s = Math.max(-90, bounds.getSouth()); | ||||
|         const w = Math.max(-180, bounds.getWest()); | ||||
|         const queryBounds = {north: n, east: e, south: s, west: w}; | ||||
| 
 | ||||
| 
 | ||||
|         const self = this; | ||||
|         const overpass = this.GetFilter(); | ||||
| 
 | ||||
|         let data: any = undefined | ||||
|         let date: Date = undefined | ||||
|         const overpassUrls = self.state.overpassUrl.data | ||||
|         let lastUsed = 0; | ||||
| 
 | ||||
|         do { | ||||
|             try { | ||||
|                 const overpass = this.GetFilter(overpassUrls[lastUsed]); | ||||
| 
 | ||||
|                 if (overpass === undefined) { | ||||
|                     return undefined; | ||||
|                 } | ||||
|                 this.runningQuery.setData(true); | ||||
| 
 | ||||
|         let data: any = undefined | ||||
|         let date: Date = undefined | ||||
| 
 | ||||
|         do { | ||||
| 
 | ||||
|             try { | ||||
|                 [data, date] = await overpass.queryGeoJson(queryBounds) | ||||
|                 [data, date] = await overpass.queryGeoJson(bounds) | ||||
|                 console.log("Querying overpass is done", data) | ||||
|             } catch (e) { | ||||
|                 self.retries.data++; | ||||
|                 self.retries.ping(); | ||||
|                 console.error(`QUERY FAILED (retrying in ${5 * self.retries.data} sec) due to`, e); | ||||
|                 console.error(`QUERY FAILED due to`, e); | ||||
| 
 | ||||
|                 await Utils.waitFor(1000) | ||||
| 
 | ||||
|                 if (lastUsed + 1 < overpassUrls.length) { | ||||
|                     lastUsed++ | ||||
|                     console.log("Trying next time with", overpassUrls[lastUsed]) | ||||
|                 } else { | ||||
|                     lastUsed = 0 | ||||
|                     self.timeout.setData(self.retries.data * 5); | ||||
| 
 | ||||
|                     while (self.timeout.data > 0) { | ||||
|                         await Utils.waitFor(1000) | ||||
|                         console.log(self.timeout.data) | ||||
|                         self.timeout.data-- | ||||
|                         self.timeout.ping(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } while (data === undefined); | ||||
| 
 | ||||
|         const z = Math.floor(this.state.locationControl.data.zoom ?? 0); | ||||
|         self._previousBounds.get(z).push(queryBounds); | ||||
|         self._previousBounds.get(z).push(bounds); | ||||
|         self.retries.setData(0); | ||||
| 
 | ||||
|         try { | ||||
|  | @ -220,20 +223,5 @@ export default class OverpassFeatureSource implements FeatureSource { | |||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private IsInBounds(bounds: Bounds): boolean { | ||||
|         if (this._previousBounds === undefined) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         const b = this.state.currentBounds.data; | ||||
|         return b.getSouth() >= bounds.south && | ||||
|             b.getNorth() <= bounds.north && | ||||
|             b.getEast() <= bounds.east && | ||||
|             b.getWest() >= bounds.west; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -50,7 +50,7 @@ export default class FeaturePipeline { | |||
|             readonly changes: Changes, | ||||
|             readonly  layoutToUse: LayoutConfig, | ||||
|             readonly leafletMap: any, | ||||
|             readonly overpassUrl: UIEventSource<string>; | ||||
|             readonly overpassUrl: UIEventSource<string[]>; | ||||
|             readonly overpassTimeout: UIEventSource<number>; | ||||
|             readonly overpassMaxZoom: UIEventSource<number>; | ||||
|             readonly osmConnection: OsmConnection | ||||
|  | @ -67,6 +67,7 @@ export default class FeaturePipeline { | |||
|         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 => { | ||||
|  | @ -107,6 +108,8 @@ export default class FeaturePipeline { | |||
|             }); | ||||
| 
 | ||||
|         this.overpassUpdater = updater; | ||||
|         this.timeout = updater.timeout | ||||
| 
 | ||||
|         this.sufficientlyZoomed = state.locationControl.map(location => { | ||||
|                 if (location?.zoom === undefined) { | ||||
|                     return false; | ||||
|  | @ -204,7 +207,6 @@ export default class FeaturePipeline { | |||
|         } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|         const osmFeatureSource = new OsmFeatureSource({ | ||||
|             isActive: useOsmApi, | ||||
|             neededTiles: neededTilesFromOsm, | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| import * as OsmToGeoJson from "osmtogeojson"; | ||||
| import Bounds from "../../Models/Bounds"; | ||||
| import {TagsFilter} from "../Tags/TagsFilter"; | ||||
| import RelationsTracker from "./RelationsTracker"; | ||||
| import {Utils} from "../../Utils"; | ||||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import {BBox} from "../BBox"; | ||||
| 
 | ||||
| /** | ||||
|  * Interfaces overpass to get all the latest data | ||||
|  | @ -11,7 +11,7 @@ import {UIEventSource} from "../UIEventSource"; | |||
| export class Overpass { | ||||
|     public static testUrl: string = null | ||||
|     private _filter: TagsFilter | ||||
|     private readonly _interpreterUrl: UIEventSource<string>; | ||||
|     private readonly _interpreterUrl: string; | ||||
|     private readonly _timeout: UIEventSource<number>; | ||||
|     private readonly _extraScripts: string[]; | ||||
|     private _includeMeta: boolean; | ||||
|  | @ -19,7 +19,7 @@ export class Overpass { | |||
| 
 | ||||
| 
 | ||||
|     constructor(filter: TagsFilter, extraScripts: string[], | ||||
|                 interpreterUrl: UIEventSource<string>, | ||||
|                 interpreterUrl: string, | ||||
|                 timeout: UIEventSource<number>, | ||||
|                 relationTracker: RelationsTracker, | ||||
|                 includeMeta = true) { | ||||
|  | @ -31,9 +31,9 @@ export class Overpass { | |||
|         this._relationTracker = relationTracker | ||||
|     } | ||||
| 
 | ||||
|     public async queryGeoJson(bounds: Bounds): Promise<[any, Date]> { | ||||
|     public async queryGeoJson(bounds: BBox): Promise<[any, Date]> { | ||||
| 
 | ||||
|         let query = this.buildQuery("[bbox:" + bounds.south + "," + bounds.west + "," + bounds.north + "," + bounds.east + "]") | ||||
|         let query = this.buildQuery("[bbox:" + bounds.getSouth() + "," + bounds.getWest() + "," + bounds.getNorth() + "," + bounds.getEast() + "]") | ||||
| 
 | ||||
|         if (Overpass.testUrl !== null) { | ||||
|             console.log("Using testing URL") | ||||
|  | @ -68,6 +68,6 @@ export class Overpass { | |||
|         } | ||||
|         const query = | ||||
|             `[out:json][timeout:${this._timeout.data}]${bbox};(${filter});out body;${this._includeMeta ? 'out meta;' : ''}>;out skel qt;` | ||||
|         return `${this._interpreterUrl.data}?data=${encodeURIComponent(query)}` | ||||
|         return `${this._interpreterUrl}?data=${encodeURIComponent(query)}` | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +0,0 @@ | |||
| export default interface Bounds { | ||||
|     north: number, | ||||
|     east: number, | ||||
|     south: number, | ||||
|     west: number | ||||
| } | ||||
|  | @ -4,6 +4,16 @@ export default class Constants { | |||
| 
 | ||||
|     public static vNumber = "0.10.0-alpha-4"; | ||||
|     public static ImgurApiKey = '7070e7167f0a25a' | ||||
|     public static defaultOverpassUrls = [ | ||||
|         // The official instance, 10000 queries per day per project allowed
 | ||||
|         "https://overpass-api.de/api/interpreter", | ||||
|         // 'Fair usage'
 | ||||
|         "https://overpass.kumi.systems/api/interpreter", | ||||
|         // "https://overpass.nchc.org.tw/api/interpreter",
 | ||||
|         "https://overpass.openstreetmap.ru/cgi/interpreter", | ||||
|         // The french api, only 1000 per day per project allowed, so we put it as last resort
 | ||||
|         "https://overpass.openstreetmap.fr/api/interpreter" | ||||
|     ] | ||||
| 
 | ||||
|     // The user journey states thresholds when a new feature gets unlocked
 | ||||
|     public static userJourney = { | ||||
|  |  | |||
|  | @ -263,9 +263,9 @@ export interface LayoutConfigJson { | |||
|     enablePdfDownload?: boolean; | ||||
| 
 | ||||
|     /** | ||||
|      * Set a different overpass URL. Default: https://overpass-api.de/api/interpreter
 | ||||
|      * Set one or more overpass URLs to use for this theme.. | ||||
|      */ | ||||
|     overpassUrl?: string; | ||||
|     overpassUrl?: string | string[]; | ||||
|     /** | ||||
|      * Set a different timeout for overpass queries - in seconds. Default: 30s | ||||
|      */ | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import AllKnownLayers from "../../Customizations/AllKnownLayers"; | |||
| import {Utils} from "../../Utils"; | ||||
| import LayerConfig from "./LayerConfig"; | ||||
| import {LayerConfigJson} from "./Json/LayerConfigJson"; | ||||
| import Constants from "../Constants"; | ||||
| 
 | ||||
| export default class LayoutConfig { | ||||
|     public readonly id: string; | ||||
|  | @ -50,7 +51,7 @@ export default class LayoutConfig { | |||
|     How long is the cache valid, in seconds? | ||||
|      */ | ||||
|     public readonly cacheTimeout?: number; | ||||
|     public readonly overpassUrl: string; | ||||
|     public readonly overpassUrl: string[]; | ||||
|     public readonly overpassTimeout: number; | ||||
|     public readonly official: boolean; | ||||
| 
 | ||||
|  | @ -157,7 +158,14 @@ export default class LayoutConfig { | |||
|         this.enablePdfDownload = json.enablePdfDownload ?? false; | ||||
|         this.customCss = json.customCss; | ||||
|         this.cacheTimeout = json.cacheTimout ?? (60 * 24 * 60 * 60) | ||||
|         this.overpassUrl = json.overpassUrl ?? "https://overpass-api.de/api/interpreter" | ||||
|         this.overpassUrl = Constants.defaultOverpassUrls | ||||
|         if(json.overpassUrl !== undefined){ | ||||
|             if(typeof json.overpassUrl === "string"){ | ||||
|                 this.overpassUrl = [json.overpassUrl] | ||||
|             }else{ | ||||
|                 this.overpassUrl = json.overpassUrl | ||||
|             } | ||||
|         } | ||||
|         this.overpassTimeout = json.overpassTimeout ?? 30 | ||||
| 
 | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										6
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								State.ts
									
										
									
									
									
								
							|  | @ -81,7 +81,7 @@ export default class State { | |||
|     public readonly featureSwitchEnableExport: UIEventSource<boolean>; | ||||
|     public readonly featureSwitchFakeUser: UIEventSource<boolean>; | ||||
|     public readonly featureSwitchExportAsPdf: UIEventSource<boolean>; | ||||
|     public readonly overpassUrl: UIEventSource<string>; | ||||
|     public readonly overpassUrl: UIEventSource<string[]>; | ||||
|     public readonly overpassTimeout: UIEventSource<number>; | ||||
|      | ||||
|      | ||||
|  | @ -321,9 +321,9 @@ export default class State { | |||
|             ); | ||||
| 
 | ||||
|             this.overpassUrl = QueryParameters.GetQueryParameter("overpassUrl", | ||||
|                 layoutToUse?.overpassUrl, | ||||
|                 layoutToUse?.overpassUrl.join(","), | ||||
|                 "Point mapcomplete to a different overpass-instance. Example: https://overpass-api.de/api/interpreter" | ||||
|             ) | ||||
|             ).map(param => param.split(","), [], urls => urls.join(",")) | ||||
| 
 | ||||
|             this.overpassTimeout = QueryParameters.GetQueryParameter("overpassTimeout", | ||||
|                 "" + layoutToUse?.overpassTimeout, | ||||
|  |  | |||
							
								
								
									
										1
									
								
								Utils.ts
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Utils.ts
									
										
									
									
									
								
							|  | @ -320,6 +320,7 @@ export class Utils { | |||
|                 } | ||||
| 
 | ||||
|                 xhr.send(); | ||||
|                 xhr.onerror = reject | ||||
|             } | ||||
|         ) | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										12
									
								
								assets/themes/toerisme_vlaanderen/license_info.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								assets/themes/toerisme_vlaanderen/license_info.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| [ | ||||
|   { | ||||
|     "path": "logo.png", | ||||
|     "license": "Logo (all rights reserved)", | ||||
|     "authors": [ | ||||
|       "Toerisme Vlaanderen" | ||||
|     ], | ||||
|     "sources": [ | ||||
|       "https://www.toerismevlaanderen.be/" | ||||
|     ] | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/themes/toerisme_vlaanderen/logo.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/themes/toerisme_vlaanderen/logo.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 11 KiB | 
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue