forked from MapComplete/MapComplete
		
	Docs: improve typing of FeatureSources
This commit is contained in:
		
							parent
							
								
									c71036d6c6
								
							
						
					
					
						commit
						34924fd4b1
					
				
					 21 changed files with 140 additions and 127 deletions
				
			
		|  | @ -36,6 +36,6 @@ export interface FeatureSourceForTile<T extends Feature = Feature> extends Featu | |||
| /** | ||||
|  * A feature source which is aware of the indexes it contains | ||||
|  */ | ||||
| export interface IndexedFeatureSource extends FeatureSource { | ||||
| export interface IndexedFeatureSource<T extends Feature> extends FeatureSource<T> { | ||||
|     readonly featuresById: Store<Map<string, Feature>> | ||||
| } | ||||
|  |  | |||
|  | @ -1,17 +1,16 @@ | |||
| import { Store, UIEventSource } from "../../UIEventSource" | ||||
| import { FeatureSource, IndexedFeatureSource, UpdatableFeatureSource } from "../FeatureSource" | ||||
| import { Feature } from "geojson" | ||||
| import { OsmFeature } from "../../../Models/OsmFeature" | ||||
| import { Lists } from "../../../Utils/Lists" | ||||
| 
 | ||||
| /** | ||||
|  * The featureSourceMerger receives complete geometries from various sources. | ||||
|  * If multiple sources contain the same object (as determined by 'id'), only one copy of them is retained | ||||
|  */ | ||||
| export default class FeatureSourceMerger<Src extends FeatureSource = FeatureSource> | ||||
|     implements IndexedFeatureSource | ||||
| export default class FeatureSourceMerger<T extends Feature, Src extends FeatureSource<T> = FeatureSource<T>> | ||||
|     implements IndexedFeatureSource<T> | ||||
| { | ||||
|     public features: UIEventSource<Feature[]> = new UIEventSource([]) | ||||
|     public features: UIEventSource<T[]> = new UIEventSource([]) | ||||
|     public readonly featuresById: Store<Map<string, Feature>> | ||||
|     protected readonly _featuresById: UIEventSource<Map<string, Feature>> | ||||
|     protected readonly _sources: Src[] | ||||
|  | @ -55,7 +54,7 @@ export default class FeatureSourceMerger<Src extends FeatureSource = FeatureSour | |||
|      * Returns 'true' if this was a previously unseen item. | ||||
|      * If the item was already present, nothing will happen | ||||
|      */ | ||||
|     public addItem(f: OsmFeature): boolean { | ||||
|     public addItem(f: T): boolean { | ||||
|         const id = f.properties.id | ||||
| 
 | ||||
|         const all = this._featuresById.data | ||||
|  | @ -68,10 +67,10 @@ export default class FeatureSourceMerger<Src extends FeatureSource = FeatureSour | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected addData(sources: Feature[][]) { | ||||
|     protected addData(sources: T[][]) { | ||||
|         sources = Lists.noNull(sources) | ||||
|         let somethingChanged = false | ||||
|         const all: Map<string, Feature> = new Map() | ||||
|         const all: Map<string, T> = new Map() | ||||
|         const unseen = new Set<string>() | ||||
|         // We seed the dictionary with the previously loaded features
 | ||||
|         const oldValues = this.features.data ?? [] | ||||
|  | @ -118,10 +117,11 @@ export default class FeatureSourceMerger<Src extends FeatureSource = FeatureSour | |||
| } | ||||
| 
 | ||||
| export class UpdatableFeatureSourceMerger< | ||||
|         Src extends UpdatableFeatureSource = UpdatableFeatureSource | ||||
|     T extends Feature, | ||||
|         Src extends UpdatableFeatureSource<T> = UpdatableFeatureSource<T> | ||||
|     > | ||||
|     extends FeatureSourceMerger<Src> | ||||
|     implements IndexedFeatureSource, UpdatableFeatureSource | ||||
|     extends FeatureSourceMerger<T, Src> | ||||
|     implements IndexedFeatureSource<T>, UpdatableFeatureSource<T> | ||||
| { | ||||
|     constructor(...sources: Src[]) { | ||||
|         super(...sources) | ||||
|  |  | |||
|  | @ -3,13 +3,15 @@ import { Utils } from "../../../Utils" | |||
| import { FeatureSource } from "../FeatureSource" | ||||
| import { BBox } from "../../BBox" | ||||
| import { GeoOperations } from "../../GeoOperations" | ||||
| import { Feature } from "geojson" | ||||
| import { Feature, Geometry } from "geojson" | ||||
| import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" | ||||
| import { Tiles } from "../../../Models/TileRange" | ||||
| 
 | ||||
| export default class GeoJsonSource implements FeatureSource { | ||||
|     private readonly _features: UIEventSource<Feature[]> = new UIEventSource<Feature[]>(undefined) | ||||
|     public readonly features: Store<Feature[]> = this._features | ||||
| export default class GeoJsonSource<T extends Feature<Geometry, { | ||||
|     id: string | ||||
| } & Record<string, any>>> implements FeatureSource<T> { | ||||
|     private readonly _features: UIEventSource<T[]> = new UIEventSource(undefined) | ||||
|     public readonly features: Store<T[]> = this._features | ||||
|     private readonly seenids: Set<string> | ||||
|     private readonly idKey?: string | ||||
|     private readonly url: string | ||||
|  | @ -96,7 +98,7 @@ export default class GeoJsonSource implements FeatureSource { | |||
|         const url = this.url | ||||
|         try { | ||||
|             const cacheAge = (options?.maxCacheAgeSec ?? 300) * 1000 | ||||
|             let json = <{ features: Feature[] }>await Utils.downloadJsonCached(url, cacheAge) | ||||
|             let json = <{ features: T[] }>await Utils.downloadJsonCached(url, cacheAge) | ||||
| 
 | ||||
|             if (json.features === undefined || json.features === null) { | ||||
|                 json.features = [] | ||||
|  | @ -106,7 +108,7 @@ export default class GeoJsonSource implements FeatureSource { | |||
|                 json = GeoOperations.GeoJsonToWGS84(json) | ||||
|             } | ||||
| 
 | ||||
|             const newFeatures: Feature[] = [] | ||||
|             const newFeatures: T[] = [] | ||||
|             let i = 0 | ||||
|             for (const feature of json.features) { | ||||
|                 if (feature.geometry.type === "Point") { | ||||
|  |  | |||
|  | @ -5,8 +5,8 @@ import { FeatureSourceForTile, UpdatableFeatureSource } from "../FeatureSource" | |||
| import { MvtToGeojson } from "mvt-to-geojson" | ||||
| import { OsmTags } from "../../../Models/OsmFeature" | ||||
| 
 | ||||
| export default class MvtSource implements FeatureSourceForTile, UpdatableFeatureSource { | ||||
|     public readonly features: Store<GeojsonFeature<Geometry, OsmTags>[]> | ||||
| export default class MvtSource<T extends Feature<Geometry, OsmTags>> implements FeatureSourceForTile<T>, UpdatableFeatureSource<T> { | ||||
|     public readonly features: Store<T[]> | ||||
|     public readonly x: number | ||||
|     public readonly y: number | ||||
|     public readonly z: number | ||||
|  |  | |||
|  | @ -4,16 +4,16 @@ import { ImmutableStore, Store, UIEventSource } from "../../UIEventSource" | |||
| import { Tiles } from "../../../Models/TileRange" | ||||
| import { BBox } from "../../BBox" | ||||
| import { TagsFilter } from "../../Tags/TagsFilter" | ||||
| import { Feature } from "geojson" | ||||
| import FeatureSourceMerger from "../Sources/FeatureSourceMerger" | ||||
| import OsmObjectDownloader from "../../Osm/OsmObjectDownloader" | ||||
| import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource" | ||||
| import { Lists } from "../../../Utils/Lists" | ||||
| import { OsmFeature } from "../../../Models/OsmFeature" | ||||
| 
 | ||||
| /** | ||||
|  * If a tile is needed (requested via the UIEventSource in the constructor), will download the appropriate tile and pass it via 'handleTile' | ||||
|  */ | ||||
| export default class OsmFeatureSource extends FeatureSourceMerger { | ||||
| export default class OsmFeatureSource<T extends OsmFeature> extends FeatureSourceMerger<T> { | ||||
|     private readonly _bounds: Store<BBox> | ||||
|     private readonly isActive: Store<boolean> | ||||
|     private readonly _backend: string | ||||
|  | @ -33,7 +33,7 @@ export default class OsmFeatureSource extends FeatureSourceMerger { | |||
|     public readonly isRunning: UIEventSource<boolean> = new UIEventSource<boolean>(false) | ||||
| 
 | ||||
|     private readonly _downloadedTiles: Set<number> = new Set<number>() | ||||
|     private readonly _downloadedData: Feature[][] = [] | ||||
|     private readonly _downloadedData: T[][] = [] | ||||
|     private readonly _patchRelations: boolean | ||||
|     /** | ||||
|      * Downloads data directly from the OSM-api within the given bounds. | ||||
|  | @ -90,7 +90,7 @@ export default class OsmFeatureSource extends FeatureSourceMerger { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private registerFeatures(features: Feature[]): void { | ||||
|     private registerFeatures(features: T[]): void { | ||||
|         this._downloadedData.push(features) | ||||
|         super.addData(this._downloadedData) | ||||
|     } | ||||
|  | @ -160,7 +160,7 @@ export default class OsmFeatureSource extends FeatureSourceMerger { | |||
|             const osmJson = await Utils.downloadJsonCached(url, 2000) | ||||
|             try { | ||||
|                 this.options?.fullNodeDatabase?.handleOsmJson(osmJson, z, x, y) | ||||
|                 let features = <Feature<any, { id: string }>[]>OsmToGeoJson(osmJson, { | ||||
|                 let features = <T[]>OsmToGeoJson(osmJson, { | ||||
|                     flatProperties: true, | ||||
|                 }).features | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| import { Feature, FeatureCollection, Geometry } from "geojson" | ||||
| import { UpdatableFeatureSource } from "../FeatureSource" | ||||
| import { ImmutableStore, Store, UIEventSource } from "../../UIEventSource" | ||||
| import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" | ||||
|  | @ -7,20 +6,20 @@ import { Overpass } from "../../Osm/Overpass" | |||
| import { Utils } from "../../../Utils" | ||||
| import { TagsFilter } from "../../Tags/TagsFilter" | ||||
| import { BBox } from "../../BBox" | ||||
| import { OsmTags } from "../../../Models/OsmFeature" | ||||
| import { OsmFeature } from "../../../Models/OsmFeature" | ||||
| import { Lists } from "../../../Utils/Lists" | ||||
| 
 | ||||
| ;("use strict") | ||||
| ("use strict") | ||||
| 
 | ||||
| /** | ||||
|  * A wrapper around the 'Overpass'-object. | ||||
|  * It has more logic and will automatically fetch the data for the right bbox and the active layers | ||||
|  */ | ||||
| export default class OverpassFeatureSource implements UpdatableFeatureSource { | ||||
| export default class OverpassFeatureSource<T extends OsmFeature = OsmFeature> implements UpdatableFeatureSource<T> { | ||||
|     /** | ||||
|      * The last loaded features, as geojson | ||||
|      */ | ||||
|     public readonly features: UIEventSource<Feature[]> = new UIEventSource(undefined) | ||||
|     public readonly features: UIEventSource<T[]> = new UIEventSource(undefined) | ||||
| 
 | ||||
|     public readonly runningQuery: UIEventSource<boolean> = new UIEventSource<boolean>(false) | ||||
|     public readonly timeout: UIEventSource<number> = new UIEventSource<number>(0) | ||||
|  | @ -111,7 +110,7 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource { | |||
|         if (!navigator.onLine) { | ||||
|             return | ||||
|         } | ||||
|         let data: FeatureCollection<Geometry, OsmTags> = undefined | ||||
|         let data: { features: T[] } = undefined | ||||
|         let lastUsed = 0 | ||||
|         const start = new Date() | ||||
|         const layersToDownload = this._layersToDownload.data | ||||
|  | @ -143,7 +142,7 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource { | |||
|                     return undefined | ||||
|                 } | ||||
|                 this.runningQuery.setData(true) | ||||
|                 data = (await overpass.queryGeoJson(bounds))[0] | ||||
|                 data = (await overpass.queryGeoJson<T>(bounds))[0] | ||||
|             } catch (e) { | ||||
|                 this.retries.data++ | ||||
|                 this.retries.ping() | ||||
|  |  | |||
|  | @ -26,9 +26,6 @@ export default class StaticFeatureSource<T extends Feature = Feature> implements | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static fromGeojson<T extends Feature>(geojson: T[]): StaticFeatureSource<T> { | ||||
|         return new StaticFeatureSource(geojson) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export class WritableStaticFeatureSource<T extends Feature = Feature> | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ import LocalStorageFeatureSource from "../TiledFeatureSource/LocalStorageFeature | |||
| import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource" | ||||
| import DynamicMvtileSource from "../TiledFeatureSource/DynamicMvtTileSource" | ||||
| import FeatureSourceMerger from "./FeatureSourceMerger" | ||||
| import { Feature } from "geojson" | ||||
| import { Feature, Geometry } from "geojson" | ||||
| import { OsmFeature } from "../../../Models/OsmFeature" | ||||
| 
 | ||||
| /** | ||||
|  | @ -20,7 +20,7 @@ import { OsmFeature } from "../../../Models/OsmFeature" | |||
|  * | ||||
|  * Note that special layers (with `source=null` will be ignored) | ||||
|  */ | ||||
| export default class ThemeSource implements IndexedFeatureSource { | ||||
| export default class ThemeSource<T extends Feature<Geometry, Record<string, any> & {id: string}>> implements IndexedFeatureSource<T> { | ||||
|     /** | ||||
|      * Indicates if a data source is loading something | ||||
|      */ | ||||
|  | @ -28,12 +28,12 @@ export default class ThemeSource implements IndexedFeatureSource { | |||
| 
 | ||||
|     public static readonly fromCacheZoomLevel = 15 | ||||
| 
 | ||||
|     public features: UIEventSource<Feature[]> = new UIEventSource([]) | ||||
|     public readonly featuresById: Store<Map<string, Feature>> | ||||
|     private readonly core: Store<ThemeSourceCore> | ||||
|     public features: UIEventSource<T[]> = new UIEventSource([]) | ||||
|     public readonly featuresById: Store<Map<string, T>> | ||||
|     private readonly core: Store<ThemeSourceCore<T>> | ||||
| 
 | ||||
|     private readonly addedSources: FeatureSource[] = [] | ||||
|     private readonly addedItems: OsmFeature[] = [] | ||||
|     private readonly addedSources: FeatureSource<T>[] = [] | ||||
|     private readonly addedItems: T[] = [] | ||||
| 
 | ||||
|     constructor( | ||||
|         layers: LayerConfig[], | ||||
|  | @ -47,11 +47,11 @@ export default class ThemeSource implements IndexedFeatureSource { | |||
|         const isLoading = new UIEventSource(true) | ||||
|         this.isLoading = isLoading | ||||
| 
 | ||||
|         const features = (this.features = new UIEventSource<Feature[]>([])) | ||||
|         const features = (this.features = new UIEventSource<T[]>([])) | ||||
|         const featuresById = (this.featuresById = new UIEventSource(new Map())) | ||||
|         this.core = mvtAvailableLayers.mapD((mvtAvailableLayers) => { | ||||
|             this.core?.data?.destruct() | ||||
|             const core = new ThemeSourceCore( | ||||
|             const core = new ThemeSourceCore<T>( | ||||
|                 layers, | ||||
|                 featureSwitches, | ||||
|                 mapProperties, | ||||
|  | @ -73,12 +73,12 @@ export default class ThemeSource implements IndexedFeatureSource { | |||
|         return this.core.data.downloadAll() | ||||
|     } | ||||
| 
 | ||||
|     public addSource(source: FeatureSource) { | ||||
|     public addSource(source: FeatureSource<T>) { | ||||
|         this.core.data?.addSource(source) | ||||
|         this.addedSources.push(source) | ||||
|     } | ||||
| 
 | ||||
|     public addItem(obj: OsmFeature) { | ||||
|     public addItem(obj: T) { | ||||
|         this.core.data?.addItem(obj) | ||||
|         this.addedItems.push(obj) | ||||
|     } | ||||
|  | @ -89,7 +89,7 @@ export default class ThemeSource implements IndexedFeatureSource { | |||
|  * | ||||
|  * Note that special layers (with `source=null` will be ignored) | ||||
|  */ | ||||
| class ThemeSourceCore extends FeatureSourceMerger { | ||||
| class ThemeSourceCore<T extends OsmFeature> extends FeatureSourceMerger<T> { | ||||
|     /** | ||||
|      * This source is _only_ triggered when the data is downloaded for CSV export | ||||
|      * @private | ||||
|  | @ -113,10 +113,10 @@ class ThemeSourceCore extends FeatureSourceMerger { | |||
| 
 | ||||
|         const geojsonlayers = layers.filter((layer) => layer.source.geojsonSource !== undefined) | ||||
|         const osmLayers = layers.filter((layer) => layer.source.geojsonSource === undefined) | ||||
|         const fromCache = new Map<string, LocalStorageFeatureSource>() | ||||
|         const fromCache = new Map<string, LocalStorageFeatureSource<T>>() | ||||
|         if (featureSwitches.featureSwitchCache.data) { | ||||
|             for (const layer of osmLayers) { | ||||
|                 const src = new LocalStorageFeatureSource( | ||||
|                 const src = new LocalStorageFeatureSource<T>( | ||||
|                     backend, | ||||
|                     layer, | ||||
|                     ThemeSource.fromCacheZoomLevel, | ||||
|  | @ -129,13 +129,13 @@ class ThemeSourceCore extends FeatureSourceMerger { | |||
|                 fromCache.set(layer.id, src) | ||||
|             } | ||||
|         } | ||||
|         const mvtSources: UpdatableFeatureSource[] = osmLayers | ||||
|         const mvtSources: UpdatableFeatureSource<T>[] = osmLayers | ||||
|             .filter((f) => mvtAvailableLayers.has(f.id)) | ||||
|             .map((l) => ThemeSourceCore.setupMvtSource(l, mapProperties, isDisplayed(l.id))) | ||||
|         const nonMvtSources: FeatureSource[] = [] | ||||
|             .map((l) => ThemeSourceCore.setupMvtSource<T>(l, mapProperties, isDisplayed(l.id))) | ||||
|         const nonMvtSources: FeatureSource<T>[] = [] | ||||
|         const nonMvtLayers: LayerConfig[] = osmLayers.filter((l) => !mvtAvailableLayers.has(l.id)) | ||||
| 
 | ||||
|         const osmApiSource = ThemeSourceCore.setupOsmApiSource( | ||||
|         const osmApiSource = ThemeSourceCore.setupOsmApiSource<T>( | ||||
|             osmLayers, | ||||
|             bounds, | ||||
|             zoom, | ||||
|  | @ -145,14 +145,14 @@ class ThemeSourceCore extends FeatureSourceMerger { | |||
|         ) | ||||
|         nonMvtSources.push(osmApiSource) | ||||
| 
 | ||||
|         let overpassSource: OverpassFeatureSource = undefined | ||||
|         let overpassSource: OverpassFeatureSource<T> = undefined | ||||
|         if (nonMvtLayers.length > 0) { | ||||
|             console.log( | ||||
|                 "Layers ", | ||||
|                 nonMvtLayers.map((l) => l.id), | ||||
|                 " cannot be fetched from the cache server, defaulting to overpass/OSM-api" | ||||
|             ) | ||||
|             overpassSource = ThemeSourceCore.setupOverpass(osmLayers, bounds, zoom, featureSwitches) | ||||
|             overpassSource = ThemeSourceCore.setupOverpass<T>(osmLayers, bounds, zoom, featureSwitches) | ||||
|             nonMvtSources.push(overpassSource) | ||||
|         } | ||||
| 
 | ||||
|  | @ -164,11 +164,11 @@ class ThemeSourceCore extends FeatureSourceMerger { | |||
|         overpassSource?.runningQuery?.addCallbackAndRun(() => setIsLoading()) | ||||
|         osmApiSource?.isRunning?.addCallbackAndRun(() => setIsLoading()) | ||||
| 
 | ||||
|         const geojsonSources: UpdatableFeatureSource[] = geojsonlayers.map((l) => | ||||
|         const geojsonSources: UpdatableFeatureSource<T>[] = geojsonlayers.map((l) => | ||||
|             ThemeSourceCore.setupGeojsonSource(l, mapProperties, isDisplayed(l.id)) | ||||
|         ) | ||||
| 
 | ||||
|         const downloadAll = new OverpassFeatureSource( | ||||
|         const downloadAll = new OverpassFeatureSource<T>( | ||||
|             { | ||||
|                 layers: layers.filter((l) => l.isNormal()), | ||||
|                 bounds: mapProperties.bounds, | ||||
|  | @ -196,19 +196,19 @@ class ThemeSourceCore extends FeatureSourceMerger { | |||
|         this._mapBounds = mapProperties.bounds | ||||
|     } | ||||
| 
 | ||||
|     private static setupMvtSource( | ||||
|     private static setupMvtSource<T extends OsmFeature>( | ||||
|         layer: LayerConfig, | ||||
|         mapProperties: { zoom: Store<number>; bounds: Store<BBox> }, | ||||
|         isActive?: Store<boolean> | ||||
|     ): UpdatableFeatureSource { | ||||
|         return new DynamicMvtileSource(layer, mapProperties, { isActive }) | ||||
|     ): UpdatableFeatureSource<T> { | ||||
|         return new DynamicMvtileSource<T>(layer, mapProperties, { isActive }) | ||||
|     } | ||||
| 
 | ||||
|     private static setupGeojsonSource( | ||||
|     private static setupGeojsonSource<T extends OsmFeature>( | ||||
|         layer: LayerConfig, | ||||
|         mapProperties: { zoom: Store<number>; bounds: Store<BBox> }, | ||||
|         isActiveByFilter?: Store<boolean> | ||||
|     ): UpdatableFeatureSource { | ||||
|     ): UpdatableFeatureSource<T> { | ||||
|         const source = layer.source | ||||
|         const isActive = mapProperties.zoom.map( | ||||
|             (z) => (isActiveByFilter?.data ?? true) && z >= layer.minzoom, | ||||
|  | @ -216,20 +216,20 @@ class ThemeSourceCore extends FeatureSourceMerger { | |||
|         ) | ||||
|         if (source.geojsonZoomLevel === undefined) { | ||||
|             // This is a 'load everything at once' geojson layer
 | ||||
|             return new GeoJsonSource(layer, { isActive }) | ||||
|             return new GeoJsonSource<T>(layer, { isActive }) | ||||
|         } else { | ||||
|             return new DynamicGeoJsonTileSource(layer, mapProperties, { isActive }) | ||||
|             return new DynamicGeoJsonTileSource<T>(layer, mapProperties, { isActive }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static setupOsmApiSource( | ||||
|     private static setupOsmApiSource<T extends OsmFeature>( | ||||
|         osmLayers: LayerConfig[], | ||||
|         bounds: Store<BBox>, | ||||
|         zoom: Store<number>, | ||||
|         backend: string, | ||||
|         featureSwitches: FeatureSwitchState, | ||||
|         fullNodeDatabase: FullNodeDatabaseSource | ||||
|     ): OsmFeatureSource | undefined { | ||||
|     ): OsmFeatureSource<T> | undefined { | ||||
|         if (osmLayers.length == 0) { | ||||
|             return undefined | ||||
|         } | ||||
|  | @ -248,7 +248,7 @@ class ThemeSourceCore extends FeatureSourceMerger { | |||
|         if (typeof allowedFeatures === "boolean") { | ||||
|             throw "Invalid filter to init OsmFeatureSource: it optimizes away to " + allowedFeatures | ||||
|         } | ||||
|         return new OsmFeatureSource({ | ||||
|         return new OsmFeatureSource<T>({ | ||||
|             allowedFeatures, | ||||
|             bounds, | ||||
|             backend, | ||||
|  | @ -258,12 +258,12 @@ class ThemeSourceCore extends FeatureSourceMerger { | |||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     private static setupOverpass( | ||||
|     private static setupOverpass<T extends OsmFeature>( | ||||
|         osmLayers: LayerConfig[], | ||||
|         bounds: Store<BBox>, | ||||
|         zoom: Store<number>, | ||||
|         featureSwitches: FeatureSwitchState | ||||
|     ): OverpassFeatureSource | undefined { | ||||
|     ): OverpassFeatureSource<T> | undefined { | ||||
|         if (osmLayers.length == 0) { | ||||
|             return undefined | ||||
|         } | ||||
|  |  | |||
|  | @ -4,8 +4,9 @@ import { Utils } from "../../../Utils" | |||
| import GeoJsonSource from "../Sources/GeoJsonSource" | ||||
| import { BBox } from "../../BBox" | ||||
| import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" | ||||
| import { Feature, Geometry } from "geojson" | ||||
| 
 | ||||
| export default class DynamicGeoJsonTileSource extends UpdatableDynamicTileSource { | ||||
| export default class DynamicGeoJsonTileSource<T extends Feature<Geometry, Record<string, any> & {id: string} > > extends UpdatableDynamicTileSource<T> { | ||||
|     private static whitelistCache = new Map<string, Map<number, Set<number>>>() | ||||
| 
 | ||||
|     constructor( | ||||
|  |  | |||
|  | @ -9,8 +9,10 @@ import Constants from "../../../Models/Constants" | |||
| import { UpdatableFeatureSourceMerger } from "../Sources/FeatureSourceMerger" | ||||
| import { LineSourceMerger } from "./LineSourceMerger" | ||||
| import { PolygonSourceMerger } from "./PolygonSourceMerger" | ||||
| import { OsmFeature, OsmTags } from "../../../Models/OsmFeature" | ||||
| import { Feature, Point } from "geojson" | ||||
| 
 | ||||
| class PolygonMvtSource extends PolygonSourceMerger { | ||||
| class PolygonMvtSource<P extends Record<string, any> & { id: string }> extends PolygonSourceMerger<P> { | ||||
|     constructor( | ||||
|         layer: LayerConfig, | ||||
|         mapProperties: { | ||||
|  | @ -44,7 +46,7 @@ class PolygonMvtSource extends PolygonSourceMerger { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| class LineMvtSource extends LineSourceMerger { | ||||
| class LineMvtSource extends LineSourceMerger<OsmTags> { | ||||
|     constructor( | ||||
|         layer: LayerConfig, | ||||
|         mapProperties: { | ||||
|  | @ -78,7 +80,7 @@ class LineMvtSource extends LineSourceMerger { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| class PointMvtSource extends UpdatableDynamicTileSource { | ||||
| class PointMvtSource<T extends Feature<Point, OsmTags>> extends UpdatableDynamicTileSource<T> { | ||||
|     constructor( | ||||
|         layer: LayerConfig, | ||||
|         mapProperties: { | ||||
|  | @ -102,7 +104,7 @@ class PointMvtSource extends UpdatableDynamicTileSource { | |||
|                     layer: layer.id, | ||||
|                     type: "pois", | ||||
|                 }) | ||||
|                 return new MvtSource(url, x, y, z) | ||||
|                 return new MvtSource<T>(url, x, y, z) | ||||
|             }, | ||||
|             mapProperties, | ||||
|             { | ||||
|  | @ -112,7 +114,7 @@ class PointMvtSource extends UpdatableDynamicTileSource { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| export default class DynamicMvtileSource extends UpdatableFeatureSourceMerger { | ||||
| export default class DynamicMvtileSource<T extends OsmFeature> extends UpdatableFeatureSourceMerger<T> { | ||||
|     constructor( | ||||
|         layer: LayerConfig, | ||||
|         mapProperties: { | ||||
|  | @ -124,9 +126,9 @@ export default class DynamicMvtileSource extends UpdatableFeatureSourceMerger { | |||
|         } | ||||
|     ) { | ||||
|         super( | ||||
|             new PointMvtSource(layer, mapProperties, options), | ||||
|             new LineMvtSource(layer, mapProperties, options), | ||||
|             new PolygonMvtSource(layer, mapProperties, options) | ||||
|             <any>new PointMvtSource(layer, mapProperties, options), | ||||
|             <any>new LineMvtSource(layer, mapProperties, options), | ||||
|             <any>new PolygonMvtSource(layer, mapProperties, options), | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -3,14 +3,15 @@ import { Tiles } from "../../../Models/TileRange" | |||
| import { BBox } from "../../BBox" | ||||
| import { FeatureSource, UpdatableFeatureSource } from "../FeatureSource" | ||||
| import FeatureSourceMerger from "../Sources/FeatureSourceMerger" | ||||
| import { Feature, Geometry } from "geojson" | ||||
| 
 | ||||
| /*** | ||||
|  * A tiled source which dynamically loads the required tiles at a fixed zoom level. | ||||
|  * A single featureSource will be initialized for every tile in view; which will later be merged into this featureSource | ||||
|  */ | ||||
| export default class DynamicTileSource< | ||||
|     Src extends FeatureSource = FeatureSource | ||||
| > extends FeatureSourceMerger<Src> { | ||||
| export default class DynamicTileSource<T extends Feature, | ||||
|     Src extends FeatureSource<T> = FeatureSource<T> | ||||
| > extends FeatureSourceMerger<T, Src> { | ||||
|     private readonly loadedTiles = new Set<number>() | ||||
|     private readonly zDiff: number | ||||
|     private readonly zoomlevel: Store<number> | ||||
|  | @ -97,9 +98,9 @@ export default class DynamicTileSource< | |||
|     } | ||||
| } | ||||
| 
 | ||||
| export class UpdatableDynamicTileSource<Src extends UpdatableFeatureSource = UpdatableFeatureSource> | ||||
|     extends DynamicTileSource<Src> | ||||
|     implements UpdatableFeatureSource | ||||
| export class UpdatableDynamicTileSource<T extends Feature<Geometry, Record<string, any> & {id: string}>, Src extends UpdatableFeatureSource<T> = UpdatableFeatureSource<T>> | ||||
|     extends DynamicTileSource<T, Src> | ||||
|     implements UpdatableFeatureSource<T> | ||||
| { | ||||
|     constructor( | ||||
|         zoomlevel: Store<number>, | ||||
|  |  | |||
|  | @ -1,8 +1,7 @@ | |||
| import { FeatureSourceForTile, UpdatableFeatureSource } from "../FeatureSource" | ||||
| import { Store } from "../../UIEventSource" | ||||
| import { BBox } from "../../BBox" | ||||
| import { Utils } from "../../../Utils" | ||||
| import { Feature, MultiLineString, Position } from "geojson" | ||||
| import { Feature, LineString, MultiLineString, Position } from "geojson" | ||||
| import { GeoOperations } from "../../GeoOperations" | ||||
| import { UpdatableDynamicTileSource } from "./DynamicTileSource" | ||||
| import { Lists } from "../../../Utils/Lists" | ||||
|  | @ -11,15 +10,16 @@ import { Lists } from "../../../Utils/Lists" | |||
|  * The PolygonSourceMerger receives various small pieces of bigger polygons and stitches them together. | ||||
|  * This is used to reconstruct polygons of vector tiles | ||||
|  */ | ||||
| export class LineSourceMerger extends UpdatableDynamicTileSource< | ||||
|     FeatureSourceForTile & UpdatableFeatureSource | ||||
| export class LineSourceMerger<P extends Record<string, any> & { id: string }> extends UpdatableDynamicTileSource< | ||||
|     Feature<LineString | MultiLineString, P>, FeatureSourceForTile<Feature<LineString | MultiLineString, P>> & UpdatableFeatureSource<Feature<LineString | MultiLineString, P>> | ||||
| > { | ||||
|     private readonly _zoomlevel: Store<number> | ||||
| 
 | ||||
|     constructor( | ||||
|         zoomlevel: Store<number>, | ||||
|         minzoom: number, | ||||
|         constructSource: (tileIndex: number) => FeatureSourceForTile & UpdatableFeatureSource, | ||||
|         constructSource: (tileIndex: number) => FeatureSourceForTile< | ||||
|             Feature<LineString | MultiLineString, P>> & UpdatableFeatureSource<Feature<LineString | MultiLineString, P>>, | ||||
|         mapProperties: { | ||||
|             bounds: Store<BBox> | ||||
|             zoom: Store<number> | ||||
|  | @ -32,9 +32,9 @@ export class LineSourceMerger extends UpdatableDynamicTileSource< | |||
|         this._zoomlevel = zoomlevel | ||||
|     } | ||||
| 
 | ||||
|     protected addDataFromSources(sources: FeatureSourceForTile[]) { | ||||
|     protected addDataFromSources(sources: FeatureSourceForTile<Feature<LineString | MultiLineString, P>>[]) { | ||||
|         sources = Lists.noNull(sources) | ||||
|         const all: Map<string, Feature<MultiLineString>> = new Map() | ||||
|         const all: Map<string, Feature<MultiLineString | LineString, P>> = new Map() | ||||
|         const currentZoom = this._zoomlevel?.data ?? 0 | ||||
|         for (const source of sources) { | ||||
|             if (source.z != currentZoom) { | ||||
|  | @ -48,10 +48,10 @@ export class LineSourceMerger extends UpdatableDynamicTileSource< | |||
|                 } else if (f.geometry.type === "MultiLineString") { | ||||
|                     coordinates.push(...f.geometry.coordinates) | ||||
|                 } else { | ||||
|                     console.error("Invalid geometry type:", f.geometry.type) | ||||
|                     console.error("Invalid geometry type:", f.geometry["type"]) | ||||
|                     continue | ||||
|                 } | ||||
|                 const oldV = all.get(id) | ||||
|                 const oldV: Feature<MultiLineString | LineString, P> = all.get(id) | ||||
|                 if (!oldV) { | ||||
|                     all.set(id, { | ||||
|                         type: "Feature", | ||||
|  | @ -63,7 +63,13 @@ export class LineSourceMerger extends UpdatableDynamicTileSource< | |||
|                     }) | ||||
|                     continue | ||||
|                 } | ||||
|                 oldV.geometry.coordinates.push(...coordinates) | ||||
|                 for (const coordinate of coordinates) { | ||||
|                     if (oldV.geometry.type === "LineString") { | ||||
|                         oldV.geometry.coordinates.push(...coordinate) | ||||
|                     } else { | ||||
|                         oldV.geometry.coordinates.push(coordinate) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,11 +2,11 @@ import DynamicTileSource from "./DynamicTileSource" | |||
| import { ImmutableStore, Store } from "../../UIEventSource" | ||||
| import { BBox } from "../../BBox" | ||||
| import TileLocalStorage from "../Actors/TileLocalStorage" | ||||
| import { Feature } from "geojson" | ||||
| import { Feature, Geometry } from "geojson" | ||||
| import StaticFeatureSource from "../Sources/StaticFeatureSource" | ||||
| import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" | ||||
| 
 | ||||
| export default class LocalStorageFeatureSource extends DynamicTileSource { | ||||
| export default class LocalStorageFeatureSource<T extends Feature<Geometry, { [name: string]: any }>> extends DynamicTileSource<T> { | ||||
|     constructor( | ||||
|         backend: string, | ||||
|         layer: LayerConfig, | ||||
|  | @ -30,8 +30,8 @@ export default class LocalStorageFeatureSource extends DynamicTileSource { | |||
|             new ImmutableStore(zoomlevel), | ||||
|             layer.minzoom, | ||||
|             (tileIndex) => | ||||
|                 new StaticFeatureSource( | ||||
|                     storage.getTileSource(tileIndex).mapD((features) => { | ||||
|                 new StaticFeatureSource<T>( | ||||
|                    <Store<T[]>> storage.getTileSource(tileIndex).mapD((features) => { | ||||
|                         if (features.length === undefined) { | ||||
|                             console.trace("These are not features:", features) | ||||
|                             storage.invalidate(tileIndex) | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import { FeatureSourceForTile, UpdatableFeatureSource } from "../FeatureSource" | ||||
| import { Store } from "../../UIEventSource" | ||||
| import { BBox } from "../../BBox" | ||||
| import { Feature } from "geojson" | ||||
| import { Feature, Polygon } from "geojson" | ||||
| import { GeoOperations } from "../../GeoOperations" | ||||
| import { UpdatableDynamicTileSource } from "./DynamicTileSource" | ||||
| import { Lists } from "../../../Utils/Lists" | ||||
|  | @ -10,13 +10,14 @@ import { Lists } from "../../../Utils/Lists" | |||
|  * The PolygonSourceMerger receives various small pieces of bigger polygons and stitches them together. | ||||
|  * This is used to reconstruct polygons of vector tiles | ||||
|  */ | ||||
| export class PolygonSourceMerger extends UpdatableDynamicTileSource< | ||||
|     FeatureSourceForTile & UpdatableFeatureSource | ||||
| export class PolygonSourceMerger<P extends Record<string, any> & { id: string }, | ||||
|     F extends Feature<Polygon, P> = Feature<Polygon, P>> extends UpdatableDynamicTileSource< | ||||
|     F, FeatureSourceForTile<F> & UpdatableFeatureSource<F> | ||||
| > { | ||||
|     constructor( | ||||
|         zoomlevel: Store<number>, | ||||
|         minzoom: number, | ||||
|         constructSource: (tileIndex: number) => FeatureSourceForTile & UpdatableFeatureSource, | ||||
|         constructSource: (tileIndex: number) => FeatureSourceForTile<F> & UpdatableFeatureSource<F>, | ||||
|         mapProperties: { | ||||
|             bounds: Store<BBox> | ||||
|             zoom: Store<number> | ||||
|  | @ -28,9 +29,9 @@ export class PolygonSourceMerger extends UpdatableDynamicTileSource< | |||
|         super(zoomlevel, minzoom, constructSource, mapProperties, options) | ||||
|     } | ||||
| 
 | ||||
|     protected addDataFromSources(sources: FeatureSourceForTile[]) { | ||||
|     protected addDataFromSources(sources: FeatureSourceForTile<F>[]) { | ||||
|         sources = Lists.noNull(sources) | ||||
|         const all: Map<string, Feature> = new Map() | ||||
|         const all: Map<string, F> = new Map() | ||||
|         const zooms: Map<string, number> = new Map() | ||||
| 
 | ||||
|         for (const source of sources) { | ||||
|  | @ -60,7 +61,7 @@ export class PolygonSourceMerger extends UpdatableDynamicTileSource< | |||
|                     zooms.set(id, z) | ||||
|                     continue | ||||
|                 } | ||||
|                 const merged = GeoOperations.union(f, oldV) | ||||
|                 const merged = <F> GeoOperations.union(f, oldV) | ||||
|                 merged.properties = oldV.properties | ||||
|                 all.set(id, merged) | ||||
|                 zooms.set(id, z) | ||||
|  |  | |||
|  | @ -54,11 +54,11 @@ export class GeoOperations { | |||
|     /** | ||||
|      * Create a union between two features | ||||
|      */ | ||||
|     public static union( | ||||
|     public static union<P >( | ||||
|         f0: Feature<Polygon | MultiPolygon>, | ||||
|         f1: Feature<Polygon | MultiPolygon> | ||||
|     ): Feature<Polygon | MultiPolygon> | null { | ||||
|         return turf.union(turf.featureCollection([f0, f1])) | ||||
|     ): Feature<Polygon | MultiPolygon, P> | null { | ||||
|         return turf.union<P>(turf.featureCollection([f0, f1])) | ||||
|     } | ||||
| 
 | ||||
|     public static intersect( | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ import CreateNewWayAction from "./CreateNewWayAction" | |||
| import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig" | ||||
| import FullNodeDatabaseSource from "../../FeatureSource/TiledFeatureSource/FullNodeDatabaseSource" | ||||
| import { Position } from "geojson" | ||||
| import type { OsmFeature } from "../../../Models/OsmFeature" | ||||
| 
 | ||||
| export interface MergePointConfig { | ||||
|     withinRangeOfM: number | ||||
|  | @ -71,7 +72,7 @@ export default class CreateWayWithPointReuseAction | |||
|     private readonly _state: { | ||||
|         theme: ThemeConfig | ||||
|         changes: Changes | ||||
|         indexedFeatures: IndexedFeatureSource | ||||
|         indexedFeatures: IndexedFeatureSource<OsmFeature> | ||||
|         fullNodeDatabase?: FullNodeDatabaseSource | ||||
|     } | ||||
|     private readonly _config: MergePointConfig[] | ||||
|  | @ -82,7 +83,7 @@ export default class CreateWayWithPointReuseAction | |||
|         state: { | ||||
|             theme: ThemeConfig | ||||
|             changes: Changes | ||||
|             indexedFeatures: IndexedFeatureSource | ||||
|             indexedFeatures: IndexedFeatureSource<OsmFeature> | ||||
|             fullNodeDatabase?: FullNodeDatabaseSource | ||||
|         }, | ||||
|         config: MergePointConfig[] | ||||
|  | @ -199,7 +200,7 @@ export default class CreateWayWithPointReuseAction | |||
|             } | ||||
|             features.push(newGeometry) | ||||
|         } | ||||
|         return StaticFeatureSource.fromGeojson(features) | ||||
|         return new StaticFeatureSource(features) | ||||
|     } | ||||
| 
 | ||||
|     public async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> { | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ import { OsmConnection } from "../OsmConnection" | |||
| import { Feature, Geometry, LineString, Point } from "geojson" | ||||
| import FullNodeDatabaseSource from "../../FeatureSource/TiledFeatureSource/FullNodeDatabaseSource" | ||||
| import { Lists } from "../../../Utils/Lists" | ||||
| import { OsmFeature } from "../../../Models/OsmFeature" | ||||
| 
 | ||||
| export default class ReplaceGeometryAction extends OsmChangeAction implements PreviewableAction { | ||||
|     /** | ||||
|  | @ -90,13 +91,13 @@ export default class ReplaceGeometryAction extends OsmChangeAction implements Pr | |||
|     public async getPreview(): Promise<FeatureSource> { | ||||
|         const { closestIds, allNodesById, detachedNodes, reprojectedNodes } = | ||||
|             await this.GetClosestIds() | ||||
|         const preview: Feature<Geometry>[] = closestIds.map((newId, i) => { | ||||
|         const preview: Feature<Geometry, {id: string}>[] = closestIds.map((newId, i) => { | ||||
|             if (this.identicalTo[i] !== undefined) { | ||||
|                 return undefined | ||||
|             } | ||||
| 
 | ||||
|             if (newId === undefined) { | ||||
|                 return { | ||||
|                 return <OsmFeature> { | ||||
|                     type: "Feature", | ||||
|                     properties: { | ||||
|                         newpoint: "yes", | ||||
|  | @ -127,7 +128,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction implements Pr | |||
| 
 | ||||
|         reprojectedNodes.forEach(({ newLat, newLon, nodeId }) => { | ||||
|             const origNode = allNodesById.get(nodeId) | ||||
|             const feature: Feature<LineString> = { | ||||
|             const feature: Feature<LineString, {id: string} & Record<string, any>> = { | ||||
|                 type: "Feature", | ||||
|                 properties: { | ||||
|                     move: "yes", | ||||
|  | @ -149,7 +150,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction implements Pr | |||
| 
 | ||||
|         detachedNodes.forEach(({ reason }, id) => { | ||||
|             const origNode = allNodesById.get(id) | ||||
|             const feature: Feature<Point> = { | ||||
|             const feature: OsmFeature & Feature<Point> = { | ||||
|                 type: "Feature", | ||||
|                 properties: { | ||||
|                     detach: "yes", | ||||
|  | @ -165,7 +166,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction implements Pr | |||
|             preview.push(feature) | ||||
|         }) | ||||
| 
 | ||||
|         return StaticFeatureSource.fromGeojson(Lists.noNull(preview)) | ||||
|         return new StaticFeatureSource(Lists.noNull(preview)) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  |  | |||
|  | @ -3,9 +3,9 @@ import { Utils } from "../../Utils" | |||
| import { ImmutableStore, Store } from "../UIEventSource" | ||||
| import { BBox } from "../BBox" | ||||
| import osmtogeojson from "osmtogeojson" | ||||
| import { FeatureCollection, Geometry } from "geojson" | ||||
| import { OsmTags } from "../../Models/OsmFeature" | ||||
| ;("use strict") | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| ("use strict") | ||||
| /** | ||||
|  * Interfaces overpass to get all the latest data | ||||
|  */ | ||||
|  | @ -37,7 +37,7 @@ export class Overpass { | |||
|         this._includeMeta = includeMeta | ||||
|     } | ||||
| 
 | ||||
|     public async queryGeoJson(bounds: BBox): Promise<[FeatureCollection<Geometry, OsmTags>, Date]> { | ||||
|     public async queryGeoJson<T extends Feature>(bounds: BBox): Promise<[{features: T[]}, Date]> { | ||||
|         const bbox = | ||||
|             "[bbox:" + | ||||
|             bounds.getSouth() + | ||||
|  | @ -49,16 +49,16 @@ export class Overpass { | |||
|             bounds.getEast() + | ||||
|             "]" | ||||
|         const query = this.buildScript(bbox) | ||||
|         return await this.ExecuteQuery(query) | ||||
|         return await this.ExecuteQuery<T>(query) | ||||
|     } | ||||
| 
 | ||||
|     public buildUrl(query: string) { | ||||
|         return `${this._interpreterUrl}?data=${encodeURIComponent(query)}` | ||||
|     } | ||||
| 
 | ||||
|     private async ExecuteQuery( | ||||
|     private async ExecuteQuery<T extends Feature>( | ||||
|         query: string | ||||
|     ): Promise<[FeatureCollection<Geometry, OsmTags>, Date]> { | ||||
|     ): Promise<[{features: T[]}, Date]> { | ||||
|         const json = await Utils.downloadJson<{ | ||||
|             elements: [] | ||||
|             remark | ||||
|  | @ -73,7 +73,7 @@ export class Overpass { | |||
|             console.warn("No features for", this.buildUrl(query)) | ||||
|         } | ||||
| 
 | ||||
|         const geojson = <FeatureCollection<Geometry, OsmTags>>osmtogeojson(json) | ||||
|         const geojson = <{features: T[]}> <any> osmtogeojson(json) | ||||
|         const osmTime = new Date(json.osm3s.timestamp_osm_base) | ||||
|         return [geojson, osmTime] | ||||
|     } | ||||
|  |  | |||
|  | @ -357,7 +357,7 @@ export default class ShowDataLayer { | |||
| 
 | ||||
|     public static showMultipleLayers( | ||||
|         mlmap: UIEventSource<MlMap>, | ||||
|         features: FeatureSource, | ||||
|         features: FeatureSource<Feature<Geometry, Record<string, any> & {id: string}>>, | ||||
|         layers: LayerConfig[], | ||||
|         options?: Partial<Omit<ShowDataLayerOptions, "features" | "layer">> | ||||
|     ) { | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ import { IndexedFeatureSource } from "../../Logic/FeatureSource/FeatureSource" | |||
| import SvelteUIElement from "../Base/SvelteUIElement" | ||||
| import { Feature } from "geojson" | ||||
| import AutoApplyButton from "./AutoApplyButton.svelte" | ||||
| import { OsmFeature } from "../../Models/OsmFeature" | ||||
| 
 | ||||
| export abstract class AutoAction extends SpecialVisualization { | ||||
|     supportsAutoAction: boolean | ||||
|  | @ -20,7 +21,7 @@ export abstract class AutoAction extends SpecialVisualization { | |||
|         state: { | ||||
|             theme: ThemeConfig | ||||
|             changes: Changes | ||||
|             indexedFeatures: IndexedFeatureSource | ||||
|             indexedFeatures: IndexedFeatureSource<OsmFeature> | ||||
|         }, | ||||
|         tagSource: UIEventSource<Record<string, string>>, | ||||
|         argument: string[] | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ import CreateMultiPolygonWithPointReuseAction from "../../../Logic/Osm/Actions/C | |||
| import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig" | ||||
| import { Changes } from "../../../Logic/Osm/Changes" | ||||
| import FullNodeDatabaseSource from "../../../Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource" | ||||
| import { OsmFeature } from "../../../Models/OsmFeature" | ||||
| 
 | ||||
| export interface WayImportFlowArguments extends ImportFlowArguments { | ||||
|     max_snap_distance: string | ||||
|  | @ -54,7 +55,7 @@ export default class WayImportFlowState extends ImportFlow<WayImportFlowArgument | |||
|         state: { | ||||
|             theme: ThemeConfig | ||||
|             changes: Changes | ||||
|             indexedFeatures: IndexedFeatureSource | ||||
|             indexedFeatures: IndexedFeatureSource<OsmFeature> | ||||
|             fullNodeDatabase?: FullNodeDatabaseSource | ||||
|         }, | ||||
|         tagsToApply: Store<Tag[]>, | ||||
|  | @ -82,7 +83,7 @@ export default class WayImportFlowState extends ImportFlow<WayImportFlowArgument | |||
|             const coors = feature.geometry.coordinates | ||||
|             return new CreateWayWithPointReuseAction(tagsToApply.data, coors, state, mergeConfigs) | ||||
|         } else { | ||||
|             throw "Unsupported type" | ||||
|             throw "Unsupported type: cannot import something of type "+feature.geometry["type"]+", only Polygon and LineString are supported" | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue