forked from MapComplete/MapComplete
		
	First steps for a move flow
This commit is contained in:
		
							parent
							
								
									950b979d83
								
							
						
					
					
						commit
						828102c547
					
				
					 9 changed files with 278 additions and 48 deletions
				
			
		|  | @ -1,7 +1,7 @@ | |||
| import {InputElement} from "./InputElement"; | ||||
| import Loc from "../../Models/Loc"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| import Minimap from "../Base/Minimap"; | ||||
| import Minimap, {MinimapObj} from "../Base/Minimap"; | ||||
| import BaseLayer from "../../Models/BaseLayer"; | ||||
| import Combine from "../Base/Combine"; | ||||
| import Svg from "../../Svg"; | ||||
|  | @ -14,8 +14,9 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig"; | |||
| import {BBox} from "../../Logic/BBox"; | ||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | ||||
| import ShowDataLayer from "../ShowDataLayer/ShowDataLayer"; | ||||
| import BaseUIElement from "../BaseUIElement"; | ||||
| 
 | ||||
| export default class LocationInput extends InputElement<Loc> { | ||||
| export default class LocationInput extends InputElement<Loc> implements MinimapObj { | ||||
| 
 | ||||
|     private static readonly matchLayer = new LayerConfig( | ||||
|         { | ||||
|  | @ -41,6 +42,8 @@ export default class LocationInput extends InputElement<Loc> { | |||
|     private readonly _snappedPointTags: any; | ||||
|     private readonly _bounds: UIEventSource<BBox>; | ||||
|     public readonly _matching_layer: LayerConfig; | ||||
|     private readonly map: BaseUIElement & MinimapObj; | ||||
|     private readonly clickLocation: UIEventSource<Loc>; | ||||
| 
 | ||||
|     constructor(options: { | ||||
|         mapBackground?: UIEventSource<BaseLayer>, | ||||
|  | @ -127,6 +130,18 @@ export default class LocationInput extends InputElement<Loc> { | |||
|         } | ||||
|         this.mapBackground = options.mapBackground ?? State.state?.backgroundLayer ?? new UIEventSource(AvailableBaseLayers.osmCarto) | ||||
|         this.SetClass("block h-full") | ||||
| 
 | ||||
| 
 | ||||
|         this.clickLocation = new UIEventSource<Loc>(undefined); | ||||
|         this.map = Minimap.createMiniMap( | ||||
|             { | ||||
|                 location: this._centerLocation, | ||||
|                 background: this.mapBackground, | ||||
|                 attribution: this.mapBackground !== State.state?.backgroundLayer, | ||||
|                 lastClickLocation: this.clickLocation, | ||||
|                 bounds: this._bounds | ||||
|             } | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     GetValue(): UIEventSource<Loc> { | ||||
|  | @ -139,19 +154,8 @@ export default class LocationInput extends InputElement<Loc> { | |||
| 
 | ||||
|     protected InnerConstructElement(): HTMLElement { | ||||
|         try { | ||||
|             const clickLocation = new UIEventSource<Loc>(undefined); | ||||
|             const map = Minimap.createMiniMap( | ||||
|                 { | ||||
|                     location: this._centerLocation, | ||||
|                     background: this.mapBackground, | ||||
|                     attribution: this.mapBackground !== State.state?.backgroundLayer, | ||||
|                     lastClickLocation: clickLocation, | ||||
|                     bounds: this._bounds | ||||
|                 } | ||||
|             ) | ||||
|             clickLocation.addCallbackAndRunD(location => this._centerLocation.setData(location)) | ||||
| 
 | ||||
|             map.installBounds(0.15, true); | ||||
|             this.clickLocation.addCallbackAndRunD(location => this._centerLocation.setData(location)) | ||||
|             this.map.installBounds(0.15, true); | ||||
| 
 | ||||
|             if (this._snapTo !== undefined) { | ||||
|                  | ||||
|  | @ -160,7 +164,7 @@ export default class LocationInput extends InputElement<Loc> { | |||
|                         features: new StaticFeatureSource(this._snapTo, true), | ||||
|                         enablePopups: false, | ||||
|                         zoomToFeatures: false, | ||||
|                         leafletMap: map.leafletMap, | ||||
|                         leafletMap: this.map.leafletMap, | ||||
|                         layers: State.state.filteredLayers | ||||
|                     } | ||||
|                 ) | ||||
|  | @ -175,13 +179,13 @@ export default class LocationInput extends InputElement<Loc> { | |||
|                         features: new StaticFeatureSource(matchPoint, true), | ||||
|                         enablePopups: false, | ||||
|                         zoomToFeatures: false, | ||||
|                         leafletMap: map.leafletMap, | ||||
|                         leafletMap: this.map.leafletMap, | ||||
|                         layerToShow: this._matching_layer | ||||
|                     }) | ||||
|                      | ||||
|             } | ||||
|             this.mapBackground.map(layer => { | ||||
|                 const leaflet = map.leafletMap.data | ||||
|                 const leaflet = this.map.leafletMap.data | ||||
|                 if (leaflet === undefined || layer === undefined) { | ||||
|                     return; | ||||
|                 } | ||||
|  | @ -190,7 +194,7 @@ export default class LocationInput extends InputElement<Loc> { | |||
|                 leaflet.setMinZoom(layer.max_zoom - 2) | ||||
|                 leaflet.setZoom(layer.max_zoom - 1) | ||||
| 
 | ||||
|             }, [map.leafletMap]) | ||||
|             }, [this.map.leafletMap]) | ||||
|              | ||||
|             const animatedHand = Svg.hand_ui() | ||||
|                 .SetStyle("width: 2rem; height: unset;") | ||||
|  | @ -209,7 +213,7 @@ export default class LocationInput extends InputElement<Loc> { | |||
|                     .SetClass("block w-0 h-0 z-10 relative") | ||||
|                     .SetStyle("left: calc(50% + 3rem); top: calc(50% + 2rem); opacity: 0.7"), | ||||
| 
 | ||||
|                 map | ||||
|                 this.map | ||||
|                     .SetClass("z-0 relative block w-full h-full bg-gray-100") | ||||
| 
 | ||||
|             ]).ConstructElement(); | ||||
|  | @ -219,4 +223,10 @@ export default class LocationInput extends InputElement<Loc> { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     readonly leafletMap: UIEventSource<any> = this.map.leafletMap | ||||
| 
 | ||||
|     installBounds(factor: number | BBox, showRange?: boolean): void { | ||||
|         this.map.installBounds(factor, showRange) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										131
									
								
								UI/Popup/MoveWizard.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								UI/Popup/MoveWizard.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,131 @@ | |||
| import {SubtleButton} from "../Base/SubtleButton"; | ||||
| import Combine from "../Base/Combine"; | ||||
| import Svg from "../../Svg"; | ||||
| import {OsmConnection} from "../../Logic/Osm/OsmConnection"; | ||||
| import Toggle from "../Input/Toggle"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| import Translations from "../i18n/Translations"; | ||||
| import {VariableUiElement} from "../Base/VariableUIElement"; | ||||
| import {Translation} from "../i18n/Translation"; | ||||
| import BaseUIElement from "../BaseUIElement"; | ||||
| import LocationInput from "../Input/LocationInput"; | ||||
| import Loc from "../../Models/Loc"; | ||||
| import {GeoOperations} from "../../Logic/GeoOperations"; | ||||
| 
 | ||||
| interface MoveReason  {text: Translation | string, | ||||
|     icon: string | BaseUIElement, | ||||
|     changesetCommentValue: string, | ||||
|     lockBounds: true | boolean, | ||||
|     background: undefined | "map" | "photo", | ||||
|     startZoom: number} | ||||
| 
 | ||||
| export default class MoveWizard extends Toggle { | ||||
|     /** | ||||
|      * The UI-element which helps moving a point | ||||
|      */ | ||||
|     constructor( | ||||
|         featureToMove : any, | ||||
|         state: { | ||||
|         osmConnection: OsmConnection, | ||||
|         featureSwitchUserbadge: UIEventSource<boolean> | ||||
|     },options?: { | ||||
|         reasons?: {text: Translation | string,  | ||||
|             icon: string | BaseUIElement,  | ||||
|             changesetCommentValue: string, | ||||
|             lockBounds?: true | boolean, | ||||
|             background?: undefined | "map" | "photo", | ||||
|             startZoom?: number | 15 | ||||
|         }[] | ||||
|         disableDefaultReasons?: false | boolean | ||||
|          | ||||
|     }) { | ||||
|         //State.state.featureSwitchUserbadge
 | ||||
|        // state = State.state
 | ||||
|         options = options ?? {} | ||||
|        const  t = Translations.t.move | ||||
|         const loginButton = new Toggle( | ||||
|           t.loginToMove.Clone()  .SetClass("btn").onClick(() => state.osmConnection.AttemptLogin()), | ||||
|             undefined, | ||||
|             state.featureSwitchUserbadge | ||||
|         ) | ||||
|          | ||||
|         const currentStep = new UIEventSource<"start" | "reason" | "pick_location">("start") | ||||
|         const moveReason = new UIEventSource<MoveReason>(undefined) | ||||
|         const moveButton = new SubtleButton( | ||||
|             Svg.move_ui(), | ||||
|             t.inviteToMove.Clone() | ||||
|         ).onClick(() => { | ||||
|             currentStep.setData("reason") | ||||
|         }) | ||||
|          | ||||
|          | ||||
|         const reasons : MoveReason[] = [] | ||||
|         if(!options.disableDefaultReasons){ | ||||
|             reasons.push({ | ||||
|                 text: t.reasonRelocation.Clone(), | ||||
|                 icon: Svg.relocation_svg(), | ||||
|                 changesetCommentValue: "relocated", | ||||
|                 lockBounds: false, | ||||
|                 background: undefined, | ||||
|                 startZoom: 12 | ||||
|             }) | ||||
|              | ||||
|             reasons.push({ | ||||
|                 text: t.reasonInaccurate.Clone(), | ||||
|                 icon: Svg.crosshair_svg(), | ||||
|                 changesetCommentValue: "improve_accuracy", | ||||
|                 lockBounds: true, | ||||
|                 background: "photo", | ||||
|                 startZoom: 17 | ||||
|             }) | ||||
|         } | ||||
|         for (const reason of options.reasons ?? []) { | ||||
|             reasons.push({ | ||||
|                 text: reason.text, | ||||
|                 icon: reason.icon, | ||||
|                 changesetCommentValue: reason.changesetCommentValue, | ||||
|                 lockBounds: reason.lockBounds ?? true, | ||||
|                 background: reason.background, | ||||
|                 startZoom: reason.startZoom ?? 15 | ||||
|             }) | ||||
|         } | ||||
|          | ||||
|         const selectReason = new Combine(reasons.map(r => new SubtleButton(r.icon, r.text).onClick(() => { | ||||
|             moveReason.setData(r) | ||||
|             currentStep.setData("pick_location") | ||||
|         }))) | ||||
|          | ||||
|         const cancelButton = new SubtleButton(Svg.close_svg(), t.cancel).onClick(() => currentStep.setData("start")) | ||||
|          | ||||
|          | ||||
|          | ||||
|         const [lon, lat] = GeoOperations.centerpointCoordinates(featureToMove) | ||||
|         const locationInput = new LocationInput({ | ||||
|             centerLocation: new UIEventSource<Loc>({ | ||||
|                 lon: lon, | ||||
|                 lat: lat, | ||||
|                 zoom: moveReason.data.startZoom | ||||
|             }), | ||||
|              | ||||
|         }) | ||||
|         locationInput.SetStyle("height: 25rem") | ||||
|         super( | ||||
|             new VariableUiElement(currentStep.map(currentStep => { | ||||
|                 switch (currentStep){ | ||||
|                     case "start": | ||||
|                         return moveButton; | ||||
|                     case "reason": | ||||
|                         return new Combine([selectReason, cancelButton]); | ||||
|                     case "pick_location": | ||||
|                         return new Combine([locationInput]) | ||||
|                 } | ||||
|                  | ||||
|                  | ||||
|                  | ||||
|                  | ||||
|             })), | ||||
|             loginButton, | ||||
|             state.osmConnection.isLoggedIn | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|  | @ -955,6 +955,16 @@ | |||
|     ], | ||||
|     "sources": [] | ||||
|   }, | ||||
|   { | ||||
|     "path": "move.svg", | ||||
|     "license": "CC-BY-SA 3.0 Unported", | ||||
|     "authors": [ | ||||
|       "MGalloway (WMF)" | ||||
|     ], | ||||
|     "sources": [ | ||||
|       "https://commons.wikimedia.org/wiki/File:Move_icon.svg" | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     "path": "no_checkmark.svg", | ||||
|     "license": "CC0; trivial", | ||||
|  | @ -1137,6 +1147,14 @@ | |||
|     "authors": [], | ||||
|     "sources": [] | ||||
|   }, | ||||
|   { | ||||
|     "path": "relocation.svg", | ||||
|     "license": "CC0", | ||||
|     "authors": [ | ||||
|       "Pieter Vander Vennet" | ||||
|     ], | ||||
|     "sources": [] | ||||
|   }, | ||||
|   { | ||||
|     "path": "ring.svg", | ||||
|     "license": "CC0; trivial", | ||||
|  |  | |||
							
								
								
									
										7
									
								
								assets/svg/move.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								assets/svg/move.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"> | ||||
|   <title> | ||||
|     move | ||||
|   </title> | ||||
|   <path d="M19 10l-4-3v2h-4V5h2l-3-4-3 4h2v4H5V7l-4 3 4 3v-2h4v4H7l3 4 3-4h-2v-4h4v2l4-3z"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 260 B | 
							
								
								
									
										61
									
								
								assets/svg/relocation.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								assets/svg/relocation.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    height="16px" | ||||
|    id="Layer_1" | ||||
|    style="enable-background:new 0 0 16 16;fill: #000000;" | ||||
|    version="1.1" | ||||
|    viewBox="0 0 16 16" | ||||
|    width="16px" | ||||
|    xml:space="preserve" | ||||
|    sodipodi:docname="relocation.svg" | ||||
|    inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"><metadata | ||||
|    id="metadata9"><rdf:RDF><cc:Work | ||||
|        rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type | ||||
|          rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs | ||||
|    id="defs7" /><sodipodi:namedview | ||||
|    pagecolor="#ffffff" | ||||
|    bordercolor="#666666" | ||||
|    borderopacity="1" | ||||
|    objecttolerance="10" | ||||
|    gridtolerance="10" | ||||
|    guidetolerance="10" | ||||
|    inkscape:pageopacity="0" | ||||
|    inkscape:pageshadow="2" | ||||
|    inkscape:window-width="1920" | ||||
|    inkscape:window-height="1003" | ||||
|    id="namedview5" | ||||
|    showgrid="false" | ||||
|    inkscape:zoom="20.85965" | ||||
|    inkscape:cx="10.143178" | ||||
|    inkscape:cy="10.590388" | ||||
|    inkscape:window-x="0" | ||||
|    inkscape:window-y="0" | ||||
|    inkscape:window-maximized="1" | ||||
|    inkscape:current-layer="Layer_1" /> | ||||
|     <path | ||||
|    d="M 15.968433,9.4957631 14.991526,8.5195302 V 6.1271188 c 0,-0.3705509 -0.303177,-0.6737288 -0.673729,-0.6737288 h -0.673728 c -0.370553,0 -0.67373,0.3031779 -0.67373,0.6737288 v 0.372572 L 11.622881,5.1535806 C 11.438954,4.9797587 11.270522,4.7796611 10.949152,4.7796611 c -0.321369,0 -0.489801,0.2000976 -0.67373,0.3739195 L 5.9298726,9.4957631 c -0.2102033,0.21896 -0.3705508,0.378636 -0.3705508,0.6737279 0,0.379309 0.2910508,0.673729 0.6737289,0.673729 h 0.6737287 v 4.042372 c 0,0.370553 0.303178,0.67373 0.6737289,0.67373 h 2.0211871 v -3.368645 c 0,-0.37055 0.303178,-0.673727 0.6737266,-0.673727 h 1.347459 c 0.37055,0 0.673728,0.303177 0.673728,0.673727 v 3.368645 h 2.021188 c 0.370552,0 0.673729,-0.303177 0.673729,-0.67373 V 10.84322 h 0.673729 c 0.382678,0 0.673729,-0.29442 0.673729,-0.673729 0,-0.2950919 -0.160347,-0.4547679 -0.370551,-0.6737279 z" | ||||
|    id="path2" | ||||
|    inkscape:connector-curvature="0" | ||||
|    style="stroke-width:0.67372882" /> | ||||
| <path | ||||
|    d="M 7.5468103,3.8654038 6.9092727,3.2283064 V 1.6669989 c 0,-0.2418245 -0.197856,-0.4396809 -0.4396814,-0.4396809 H 6.0299107 c -0.2418254,0 -0.4396815,0.1978564 -0.4396815,0.4396809 V 1.9101425 L 4.7108672,1.0316599 C 4.5908347,0.91822221 4.4809147,0.78763691 4.2711857,0.78763691 c -0.2097281,0 -0.319648,0.1305853 -0.4396814,0.24402299 L 0.99556255,3.8654038 c -0.1371804,0.1428956 -0.2418245,0.2471013 -0.2418245,0.4396805 0,0.2475406 0.1899421,0.4396815 0.43968095,0.4396815 H 1.6331 v 2.6380853 c 0,0.2418254 0.1978565,0.4396815 0.439681,0.4396815 H 3.3918246 V 5.624127 c 0,-0.2418237 0.1978561,-0.4396797 0.4396797,-0.4396797 h 0.8793629 c 0.2418236,0 0.4396805,0.197856 0.4396805,0.4396797 v 2.1984056 h 1.3190436 c 0.2418254,0 0.4396814,-0.1978561 0.4396814,-0.4396815 V 4.7447658 h 0.4396806 c 0.2497393,0 0.4396815,-0.1921409 0.4396815,-0.4396815 0,-0.1925792 -0.104644,-0.2967849 -0.2418245,-0.4396805 z" | ||||
|    id="path2-3" | ||||
|    inkscape:connector-curvature="0" | ||||
|    style="fill:none;stroke:#808080;stroke-width:0.43968096;stroke-opacity:1" /><path | ||||
|    style="fill:none;stroke:#000000;stroke-width:0.86116266;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|    d="m 4.2635907,11.093613 1.7780944,1.509272 -1.7780944,1.504628" | ||||
|    id="path821" | ||||
|    inkscape:connector-curvature="0" | ||||
|    sodipodi:nodetypes="ccc" /><path | ||||
|    style="fill:none;stroke:#000000;stroke-width:0.79756224;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|    d="M 5.5446079,12.650872 C 4.7207387,12.633302 2.1674541,13.155351 2.3608287,10.176205" | ||||
|    id="path815" | ||||
|    inkscape:connector-curvature="0" | ||||
|    sodipodi:nodetypes="cc" /></svg> | ||||
| After Width: | Height: | Size: 4 KiB | 
|  | @ -151,7 +151,9 @@ | |||
|           }, | ||||
|           "freeform": { | ||||
|             "key": "addr:housenumber", | ||||
|             "addExtraTags": ["nohousenumber="] | ||||
|             "addExtraTags": [ | ||||
|               "nohousenumber=" | ||||
|             ] | ||||
|           }, | ||||
|           "mappings": [ | ||||
|             { | ||||
|  |  | |||
|  | @ -36,6 +36,16 @@ | |||
|         "splitTitle": "Choose on the map where to split this road", | ||||
|         "hasBeenSplit": "This way has been split" | ||||
|     }, | ||||
|     "move": { | ||||
|         "loginToMove": "You must be logged in to move a point", | ||||
|         "inviteToMove": "Move this point", | ||||
|         "selectReason": "Why do you move this object?", | ||||
|         "reasonRelocation": "The object has been relocated to a totally different location", | ||||
|         "reasonInaccurate": "The location of this object is inaccurate and should be moved a few meter", | ||||
|         "onlyPoints": "Only points can be moved", | ||||
|         "isWay": "This feature is a way", | ||||
|         "cancel": "Cancel move" | ||||
|     }, | ||||
|     "delete": { | ||||
|         "delete": "Delete", | ||||
|         "cancel": "Cancel", | ||||
|  |  | |||
|  | @ -1362,11 +1362,6 @@ | |||
|                 "title": { | ||||
|                     "render": "Known address" | ||||
|                 } | ||||
|             }, | ||||
|             "2": { | ||||
|                 "title": { | ||||
|                     "render": "{name}" | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "shortDescription": "Help to build an open dataset of UK addresses", | ||||
|  |  | |||
							
								
								
									
										40
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										40
									
								
								test.ts
									
										
									
									
									
								
							|  | @ -1,26 +1,22 @@ | |||
| import FeatureInfoBox from "./UI/Popup/FeatureInfoBox"; | ||||
| import {UIEventSource} from "./Logic/UIEventSource"; | ||||
| import AllKnownLayers from "./Customizations/AllKnownLayers"; | ||||
| import MoveWizard from "./UI/Popup/MoveWizard"; | ||||
| import State from "./State"; | ||||
| import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; | ||||
| import MinimapImplementation from "./UI/Base/MinimapImplementation"; | ||||
| 
 | ||||
| State.state = new State(AllKnownLayouts.allKnownLayouts.get("charging_stations")) | ||||
| State.state.changes.pendingChanges.setData([]) | ||||
| const geojson = { | ||||
|     type: "Feature", | ||||
|     geometry: { | ||||
|         type: "Point", | ||||
|         coordinates: [51.0, 4] | ||||
|     }, | ||||
|     properties: | ||||
|         { | ||||
|             id: "node/42", | ||||
|             amenity: "charging_station", | ||||
|         } | ||||
| 
 | ||||
| State.state = new State(AllKnownLayouts.allKnownLayouts.get("bookcases")) | ||||
| const feature = { | ||||
|     "type": "Feature", | ||||
|     "properties": {}, | ||||
|     "geometry": { | ||||
|         "type": "Point", | ||||
|         "coordinates": [ | ||||
|             4.21875, | ||||
|             50.958426723359935 | ||||
|         ] | ||||
|     } | ||||
| } | ||||
| State.state.allElements.addOrGetElement(geojson) | ||||
| const tags = State.state.allElements.getEventSourceById("node/42") | ||||
| new FeatureInfoBox( | ||||
|     tags, | ||||
|     AllKnownLayers.sharedLayers.get("charging_station") | ||||
| ).AttachTo("maindiv") | ||||
| MinimapImplementation.initialize() | ||||
| new MoveWizard( | ||||
|     feature, | ||||
|     State.state).AttachTo("maindiv") | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue