forked from MapComplete/MapComplete
		
	First version of automatic dependency injection
This commit is contained in:
		
							parent
							
								
									2dc6d4658f
								
							
						
					
					
						commit
						62f280feae
					
				
					 3 changed files with 81 additions and 32 deletions
				
			
		|  | @ -1,7 +1,7 @@ | |||
| import {Translation} from "../../UI/i18n/Translation"; | ||||
| import SourceConfig from "./SourceConfig"; | ||||
| import TagRenderingConfig from "./TagRenderingConfig"; | ||||
| import PresetConfig from "./PresetConfig"; | ||||
| import PresetConfig, {PreciseInput} from "./PresetConfig"; | ||||
| import {LayerConfigJson} from "./Json/LayerConfigJson"; | ||||
| import Translations from "../../UI/i18n/Translations"; | ||||
| import {TagUtils} from "../../Logic/Tags/TagUtils"; | ||||
|  | @ -26,19 +26,19 @@ import * as icons from "../../assets/tagRenderings/icons.json" | |||
| 
 | ||||
| export default class LayerConfig extends WithContextLoader { | ||||
| 
 | ||||
|     id: string; | ||||
|     name: Translation; | ||||
|     description: Translation; | ||||
|     source: SourceConfig; | ||||
|     calculatedTags: [string, string][]; | ||||
|     doNotDownload: boolean; | ||||
|     passAllFeatures: boolean; | ||||
|     isShown: TagRenderingConfig; | ||||
|     minzoom: number; | ||||
|     minzoomVisible: number; | ||||
|     maxzoom: number; | ||||
|     title?: TagRenderingConfig; | ||||
|     titleIcons: TagRenderingConfig[]; | ||||
|     public readonly id: string; | ||||
|     public readonly name: Translation; | ||||
|     public readonly description: Translation; | ||||
|     public readonly source: SourceConfig; | ||||
|     public readonly calculatedTags: [string, string][]; | ||||
|     public readonly doNotDownload: boolean; | ||||
|     public readonly  passAllFeatures: boolean; | ||||
|     public readonly isShown: TagRenderingConfig; | ||||
|     public readonly  minzoom: number; | ||||
|     public readonly  minzoomVisible: number; | ||||
|     public readonly  maxzoom: number; | ||||
|     public readonly title?: TagRenderingConfig; | ||||
|     public readonly titleIcons: TagRenderingConfig[]; | ||||
| 
 | ||||
|     public readonly mapRendering: PointRenderingConfig[] | ||||
|     public readonly lineRendering: LineRenderingConfig[] | ||||
|  | @ -52,10 +52,10 @@ export default class LayerConfig extends WithContextLoader { | |||
|      */ | ||||
|     public readonly maxAgeOfCache: number | ||||
| 
 | ||||
|     presets: PresetConfig[]; | ||||
|     public readonly presets: PresetConfig[]; | ||||
| 
 | ||||
|     tagRenderings: TagRenderingConfig[]; | ||||
|     filters: FilterConfig[]; | ||||
|     public readonly tagRenderings: TagRenderingConfig[]; | ||||
|     public readonly filters: FilterConfig[]; | ||||
| 
 | ||||
|     constructor( | ||||
|         json: LayerConfigJson, | ||||
|  | @ -151,8 +151,7 @@ export default class LayerConfig extends WithContextLoader { | |||
|             throw "Presets should be a list of items (at " + context + ")" | ||||
|         } | ||||
|         this.presets = (json.presets ?? []).map((pr, i) => { | ||||
| 
 | ||||
|             let preciseInput: any = { | ||||
|             let preciseInput: PreciseInput = { | ||||
|                 preferredBackground: ["photo"], | ||||
|                 snapToLayers: undefined, | ||||
|                 maxSnapDistance: undefined | ||||
|  | @ -163,6 +162,7 @@ export default class LayerConfig extends WithContextLoader { | |||
|                         preferredBackground: undefined | ||||
|                     } | ||||
|                 } | ||||
|                  | ||||
|                 let snapToLayers: string[]; | ||||
|                 if (typeof pr.preciseInput.snapToLayer === "string") { | ||||
|                     snapToLayers = [pr.preciseInput.snapToLayer] | ||||
|  | @ -178,7 +178,7 @@ export default class LayerConfig extends WithContextLoader { | |||
|                 } | ||||
|                 preciseInput = { | ||||
|                     preferredBackground: preferredBackground, | ||||
|                     snapToLayers: snapToLayers, | ||||
|                     snapToLayers, | ||||
|                     maxSnapDistance: pr.preciseInput.maxSnapDistance ?? 10 | ||||
|                 } | ||||
|             } | ||||
|  | @ -439,6 +439,10 @@ export default class LayerConfig extends WithContextLoader { | |||
|             ] | ||||
|         } | ||||
| 
 | ||||
|         for (const dep of Array.from(this.getDependencies())) { | ||||
|             extraProps.push(new Combine(["This layer will automatically load ", new Link(dep, "#"+dep)," into the layout as it depends on it."])) | ||||
|         } | ||||
| 
 | ||||
|         return new Combine([ | ||||
|             new Title(this.id, 3), | ||||
|             this.description, | ||||
|  | @ -478,4 +482,23 @@ export default class LayerConfig extends WithContextLoader { | |||
|     public isLeftRightSensitive(): boolean { | ||||
|         return this.lineRendering.some(lr => lr.leftRightSensitive) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a set of all other layer-ids that this layer needs to function. | ||||
|      * E.g. if this layers does snap to another layer in the preset, this other layer id will be mentioned | ||||
|      */ | ||||
|     public getDependencies(): Set<string>{ | ||||
|         const deps = new Set<string>() | ||||
| 
 | ||||
|         for (const preset of this.presets ?? []) { | ||||
|             if(preset.preciseInput?.snapToLayers === undefined){ | ||||
|                 continue | ||||
|             } | ||||
|             preset.preciseInput?.snapToLayers?.forEach(id => { | ||||
|                 deps.add(id); | ||||
|             }) | ||||
|         } | ||||
|          | ||||
|         return deps | ||||
|     } | ||||
| } | ||||
|  | @ -166,7 +166,7 @@ export default class LayoutConfig { | |||
|                         return | ||||
|                     } else { | ||||
|                         const shared = AllKnownLayers.sharedLayers.get(layer) | ||||
|                         if(shared === undefined){ | ||||
|                         if (shared === undefined) { | ||||
|                             throw `Shared layer ${layer} not found (at ${context}.layers[${i}])` | ||||
|                         } | ||||
|                         result.push(shared) | ||||
|  | @ -212,15 +212,39 @@ export default class LayoutConfig { | |||
|             }) | ||||
| 
 | ||||
|         }); | ||||
|          | ||||
| 
 | ||||
|         // Some special layers which are always included by default
 | ||||
|         for (const defaultLayer of AllKnownLayers.added_by_default) { | ||||
|             if(result.some(l => l?.id === defaultLayer)){ | ||||
|             if (result.some(l => l?.id === defaultLayer)) { | ||||
|                 continue; // Already added
 | ||||
|             } | ||||
|             result.push(AllKnownLayers.sharedLayers.get(defaultLayer)) | ||||
|             const sharedLayer = AllKnownLayers.sharedLayers.get(defaultLayer) | ||||
|             if (sharedLayer !== undefined) { | ||||
|                 result.push(sharedLayer) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         let unmetDependencies: { dependency: string, layer: string }[] = [] | ||||
|         do { | ||||
|             const dependencies: { dependency: string, layer: string }[] = [].concat(...result.map(l => Array.from(l.getDependencies()).map(d => ({ | ||||
|                 dependency: d, | ||||
|                 layer: l.id | ||||
|             })))) | ||||
|             const loadedLayers = new Set(result.map(r => r.id)) | ||||
|             unmetDependencies = dependencies.filter(dep => !loadedLayers.has(dep.dependency)) | ||||
|             for (const unmetDependency of unmetDependencies) { | ||||
| 
 | ||||
|                 console.log("Recursively loading unmet dependency ", unmetDependency.dependency, "(needed by " + unmetDependency.layer + ")") | ||||
|                 const dep = AllKnownLayers.sharedLayers.get(unmetDependency.dependency) | ||||
|                 if (dep === undefined) { | ||||
|                     throw "The layer '" + unmetDependency.layer + "' needs '" + unmetDependency.dependency + "' to be loaded, but it could not be found as builtin layer (at " + context + ")" | ||||
|                 } | ||||
|                 result.unshift(dep) | ||||
|                 unmetDependencies = unmetDependencies.filter(d => d.dependency !== unmetDependency.dependency) | ||||
|             } | ||||
| 
 | ||||
|         } while (unmetDependencies.length > 0) | ||||
|         return {layers: result, extractAllNodes: exportAllNodes} | ||||
|     } | ||||
| 
 | ||||
|  | @ -300,9 +324,9 @@ export default class LayoutConfig { | |||
|     public isLeftRightSensitive() { | ||||
|         return this.layers.some(l => l.isLeftRightSensitive()) | ||||
|     } | ||||
|      | ||||
|     public getMatchingLayer(tags: any) : LayerConfig | undefined{ | ||||
|         if(tags === undefined){ | ||||
| 
 | ||||
|     public getMatchingLayer(tags: any): LayerConfig | undefined { | ||||
|         if (tags === undefined) { | ||||
|             return undefined | ||||
|         } | ||||
|         for (const layer of this.layers) { | ||||
|  |  | |||
|  | @ -1,6 +1,12 @@ | |||
| import {Translation} from "../../UI/i18n/Translation"; | ||||
| import {Tag} from "../../Logic/Tags/Tag"; | ||||
| 
 | ||||
| export interface PreciseInput { | ||||
|     preferredBackground?: string[], | ||||
|     snapToLayers?: string[], | ||||
|     maxSnapDistance?: number | ||||
| } | ||||
| 
 | ||||
| export default interface PresetConfig { | ||||
|     title: Translation, | ||||
|     tags: Tag[], | ||||
|  | @ -8,9 +14,5 @@ export default interface PresetConfig { | |||
|     /** | ||||
|      * If precise input is set, then an extra map is shown in which the user can drag the map to the precise location | ||||
|      */ | ||||
|     preciseInput?: { | ||||
|         preferredBackground?: string[], | ||||
|         snapToLayers?: string[], | ||||
|         maxSnapDistance?: number | ||||
|     } | ||||
|     preciseInput?: PreciseInput | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue