| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  | import Translations from "./UI/i18n/Translations"; | 
					
						
							|  |  |  | import {TabbedComponent} from "./UI/Base/TabbedComponent"; | 
					
						
							|  |  |  | import {ShareScreen} from "./UI/ShareScreen"; | 
					
						
							|  |  |  | import {FixedUiElement} from "./UI/Base/FixedUiElement"; | 
					
						
							|  |  |  | import {CheckBox} from "./UI/Input/CheckBox"; | 
					
						
							|  |  |  | import Combine from "./UI/Base/Combine"; | 
					
						
							|  |  |  | import {UIElement} from "./UI/UIElement"; | 
					
						
							| 
									
										
										
										
											2020-07-29 15:48:21 +02:00
										 |  |  | import {MoreScreen} from "./UI/MoreScreen"; | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | import {FilteredLayer} from "./Logic/FilteredLayer"; | 
					
						
							|  |  |  | import {FeatureInfoBox} from "./UI/FeatureInfoBox"; | 
					
						
							| 
									
										
										
										
											2020-09-25 21:58:29 +02:00
										 |  |  | import {Basemap} from "./Logic/Leaflet/Basemap"; | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  | import {State} from "./State"; | 
					
						
							|  |  |  | import {WelcomeMessage} from "./UI/WelcomeMessage"; | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  | import {Img} from "./UI/Img"; | 
					
						
							|  |  |  | import {DropDown} from "./UI/Input/DropDown"; | 
					
						
							|  |  |  | import {LayerSelection} from "./UI/LayerSelection"; | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  | import {Preset} from "./Customizations/LayerDefinition"; | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  | import {VariableUiElement} from "./UI/Base/VariableUIElement"; | 
					
						
							|  |  |  | import {LayerUpdater} from "./Logic/LayerUpdater"; | 
					
						
							| 
									
										
										
										
											2020-08-17 17:23:15 +02:00
										 |  |  | import {UIEventSource} from "./Logic/UIEventSource"; | 
					
						
							|  |  |  | import {QueryParameters} from "./Logic/Web/QueryParameters"; | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  | import {PersonalLayout} from "./Logic/PersonalLayout"; | 
					
						
							|  |  |  | import {PersonalLayersPanel} from "./Logic/PersonalLayersPanel"; | 
					
						
							| 
									
										
										
										
											2020-08-31 02:59:47 +02:00
										 |  |  | import Locale from "./UI/i18n/Locale"; | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  | import {StrayClickHandler} from "./Logic/Leaflet/StrayClickHandler"; | 
					
						
							|  |  |  | import {SimpleAddUI} from "./UI/SimpleAddUI"; | 
					
						
							|  |  |  | import {CenterMessageBox} from "./UI/CenterMessageBox"; | 
					
						
							|  |  |  | import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; | 
					
						
							|  |  |  | import {TagUtils} from "./Logic/Tags"; | 
					
						
							|  |  |  | import {UserBadge} from "./UI/UserBadge"; | 
					
						
							|  |  |  | import {SearchAndGo} from "./UI/SearchAndGo"; | 
					
						
							|  |  |  | import {FullScreenMessageBox} from "./UI/FullScreenMessageBoxHandler"; | 
					
						
							|  |  |  | import {GeoLocationHandler} from "./Logic/Leaflet/GeoLocationHandler"; | 
					
						
							|  |  |  | import {Layout} from "./Customizations/Layout"; | 
					
						
							|  |  |  | import {LocalStorageSource} from "./Logic/Web/LocalStorageSource"; | 
					
						
							|  |  |  | import {FromJSON} from "./Customizations/JSON/FromJSON"; | 
					
						
							| 
									
										
										
										
											2020-09-15 00:25:25 +02:00
										 |  |  | import {Utils} from "./Utils"; | 
					
						
							| 
									
										
										
										
											2020-09-25 21:58:29 +02:00
										 |  |  | import BackgroundSelector from "./UI/BackgroundSelector"; | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class InitUiElements { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-15 02:29:31 +02:00
										 |  |  |     private static setupAllLayerElements() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // ------------- Setup the layers -------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         InitUiElements.InitLayers(); | 
					
						
							|  |  |  |         InitUiElements.InitLayerSelection(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // ------------------ Setup various other UI elements ------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         InitUiElements.OnlyIf(State.state.featureSwitchAddNew, () => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             let presetCount = 0; | 
					
						
							|  |  |  |             for (const layer of State.state.filteredLayers.data) { | 
					
						
							|  |  |  |                 for (const preset of layer.layerDef.presets) { | 
					
						
							|  |  |  |                     presetCount++; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (presetCount == 0) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             new StrayClickHandler(() => { | 
					
						
							|  |  |  |                     return new SimpleAddUI(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         new CenterMessageBox().AttachTo("centermessage"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static InitAll(layoutToUse: Layout, layoutFromBase64: string, testing: UIEventSource<string>, layoutName: string, | 
					
						
							|  |  |  |                    layoutDefinition: string = "") { | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  |         if (layoutToUse === undefined) { | 
					
						
							|  |  |  |             console.log("Incorrect layout") | 
					
						
							| 
									
										
										
										
											2020-09-15 00:25:25 +02:00
										 |  |  |             new FixedUiElement("Error: incorrect layout <i>" + layoutName + "</i><br/><a href='https://pietervdvn.github.io/MapComplete/index.html'>Go back</a>").AttachTo("centermessage").onClick(() => { | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  |             }); | 
					
						
							|  |  |  |             throw "Incorrect layout" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-15 00:25:25 +02:00
										 |  |  |         console.log("Using layout: ", layoutToUse.id, "LayoutFromBase64 is ", layoutFromBase64); | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  |         State.state = new State(layoutToUse); | 
					
						
							| 
									
										
										
										
											2020-09-15 00:25:25 +02:00
										 |  |  |          | 
					
						
							|  |  |  |         // This 'leaks' the global state via the window object, useful for debugging
 | 
					
						
							|  |  |  |         // @ts-ignore
 | 
					
						
							|  |  |  |         window.mapcomplete_state = State.state; | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (layoutToUse.hideFromOverview) { | 
					
						
							|  |  |  |             State.state.osmConnection.GetPreference("hidden-theme-" + layoutToUse.id + "-enabled").setData("true"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (layoutFromBase64 !== "false") { | 
					
						
							| 
									
										
										
										
											2020-09-15 02:29:31 +02:00
										 |  |  |             State.state.layoutDefinition = layoutDefinition; | 
					
						
							|  |  |  |             console.log("Layout definition:", Utils.EllipsesAfter(State.state.layoutDefinition, 100)) | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  |             if (testing.data !== "true") { | 
					
						
							|  |  |  |                 State.state.osmConnection.OnLoggedIn(() => { | 
					
						
							|  |  |  |                     State.state.osmConnection.GetLongPreference("installed-theme-" + layoutToUse.id).setData(State.state.layoutDefinition); | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 console.warn("NOT saving custom layout to OSM as we are tesing -> probably in an iFrame") | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         InitUiElements.InitBaseMap(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         new FixedUiElement("").AttachTo("decoration-desktop"); // Remove the decoration
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-15 02:29:31 +02:00
										 |  |  |         InitUiElements.setupAllLayerElements(); | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function updateFavs() { | 
					
						
							|  |  |  |             const favs = State.state.favouriteLayers.data ?? []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             layoutToUse.layers = []; | 
					
						
							|  |  |  |             for (const fav of favs) { | 
					
						
							|  |  |  |                 const layer = AllKnownLayouts.allLayers[fav]; | 
					
						
							|  |  |  |                 if (!!layer) { | 
					
						
							|  |  |  |                     layoutToUse.layers.push(layer); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for (const layouts of State.state.installedThemes.data) { | 
					
						
							|  |  |  |                     for (const layer of layouts.layout.layers) { | 
					
						
							|  |  |  |                         if (typeof layer === "string") { | 
					
						
							|  |  |  |                             continue; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         if (layer.id === fav) { | 
					
						
							|  |  |  |                             layoutToUse.layers.push(layer); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-15 02:29:31 +02:00
										 |  |  |             InitUiElements.setupAllLayerElements(); | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  |             State.state.layerUpdater.ForceRefresh(); | 
					
						
							| 
									
										
										
										
											2020-09-15 02:29:31 +02:00
										 |  |  |             State.state.layoutToUse.ping(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (layoutToUse === AllKnownLayouts.allSets[PersonalLayout.NAME]) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             State.state.favouriteLayers.addCallback(updateFavs); | 
					
						
							|  |  |  |             State.state.installedThemes.addCallback(updateFavs); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * Show the questions and information for the selected element | 
					
						
							|  |  |  |          * This is given to the div which renders fullscreen on mobile devices | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         State.state.selectedElement.addCallback((feature) => { | 
					
						
							|  |  |  |                 if (feature?.feature?.properties === undefined) { | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const data = feature.feature.properties; | 
					
						
							|  |  |  |                 // Which is the applicable set?
 | 
					
						
							|  |  |  |                 for (const layer of layoutToUse.layers) { | 
					
						
							|  |  |  |                     if (typeof layer === "string") { | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     const applicable = layer.overpassFilter.matches(TagUtils.proprtiesToKV(data)); | 
					
						
							|  |  |  |                     if (applicable) { | 
					
						
							|  |  |  |                         // This layer is the layer that gives the questions
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         const featureBox = new FeatureInfoBox( | 
					
						
							|  |  |  |                             feature.feature, | 
					
						
							|  |  |  |                             State.state.allElements.getElement(data.id), | 
					
						
							|  |  |  |                             layer.title, | 
					
						
							|  |  |  |                             layer.elementsToShow, | 
					
						
							|  |  |  |                         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         State.state.fullScreenMessage.setData(featureBox); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         InitUiElements.OnlyIf(State.state.featureSwitchUserbadge, () => { | 
					
						
							|  |  |  |             new UserBadge().AttachTo('userbadge'); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         InitUiElements.OnlyIf((State.state.featureSwitchSearch), () => { | 
					
						
							|  |  |  |             new SearchAndGo().AttachTo("searchbox"); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         new FullScreenMessageBox(() => { | 
					
						
							|  |  |  |             State.state.selectedElement.setData(undefined) | 
					
						
							|  |  |  |         }).AttachTo("messagesboxmobile"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         InitUiElements.OnlyIf(State.state.featureSwitchWelcomeMessage, () => { | 
					
						
							|  |  |  |             InitUiElements.InitWelcomeMessage() | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((window != window.top && !State.state.featureSwitchWelcomeMessage.data) || State.state.featureSwitchIframe.data) { | 
					
						
							|  |  |  |             const currentLocation = State.state.locationControl; | 
					
						
							|  |  |  |             const url = `${window.location.origin}${window.location.pathname}?z=${currentLocation.data.zoom}&lat=${currentLocation.data.lat}&lon=${currentLocation.data.lon}`; | 
					
						
							|  |  |  |             const content = `<a href='${url}' target='_blank'><span class='iframe-escape'><img src='assets/pop-out.svg'></span></a>`; | 
					
						
							|  |  |  |             new FixedUiElement(content).AttachTo("messagesbox"); | 
					
						
							|  |  |  |             new FixedUiElement(content).AttachTo("help-button-mobile") | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         new GeoLocationHandler().AttachTo("geolocate-button"); | 
					
						
							|  |  |  |         State.state.locationControl.ping(); | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2020-09-15 00:25:25 +02:00
										 |  |  |         | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static LoadLayoutFromHash(userLayoutParam: UIEventSource<string>) { | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             let hash = location.hash.substr(1); | 
					
						
							|  |  |  |             const layoutFromBase64 = userLayoutParam.data; | 
					
						
							|  |  |  |             // layoutFromBase64 contains the name of the theme. This is partly to do tracking with goat counter
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const dedicatedHashFromLocalStorage = LocalStorageSource.Get("user-layout-" + layoutFromBase64.replace(" ", "_")); | 
					
						
							|  |  |  |             if (dedicatedHashFromLocalStorage.data?.length < 10) { | 
					
						
							|  |  |  |                 dedicatedHashFromLocalStorage.setData(undefined); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const hashFromLocalStorage = LocalStorageSource.Get("last-loaded-user-layout"); | 
					
						
							|  |  |  |             if (hash.length < 10) { | 
					
						
							|  |  |  |                 hash = dedicatedHashFromLocalStorage.data ?? hashFromLocalStorage.data; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 console.log("Saving hash to local storage") | 
					
						
							|  |  |  |                 hashFromLocalStorage.setData(hash); | 
					
						
							|  |  |  |                 dedicatedHashFromLocalStorage.setData(hash); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-09-07 17:26:35 +02:00
										 |  |  |             const layoutToUse = FromJSON.FromBase64(hash); | 
					
						
							| 
									
										
										
										
											2020-09-07 02:25:45 +02:00
										 |  |  |             userLayoutParam.setData(layoutToUse.id); | 
					
						
							|  |  |  |             return layoutToUse; | 
					
						
							|  |  |  |         } catch (e) { | 
					
						
							|  |  |  |             new FixedUiElement("Error: could not parse the custom layout:<br/> " + e).AttachTo("centermessage"); | 
					
						
							|  |  |  |             throw e; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |     static OnlyIf(featureSwitch: UIEventSource<boolean>, callback: () => void) { | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  |         featureSwitch.addCallback(() => { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |             if (featureSwitch.data) { | 
					
						
							|  |  |  |                 callback(); | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |         if (featureSwitch.data) { | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  |             callback(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |     private static CreateWelcomePane() { | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |         const layoutToUse = State.state.layoutToUse.data; | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  |         let welcome: UIElement = new WelcomeMessage(); | 
					
						
							| 
									
										
										
										
											2020-08-30 01:13:18 +02:00
										 |  |  |         if (layoutToUse.id === PersonalLayout.NAME) { | 
					
						
							| 
									
										
										
										
											2020-08-26 15:36:04 +02:00
										 |  |  |             welcome = new PersonalLayersPanel(); | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 00:45:33 +02:00
										 |  |  |         const tabs = [ | 
					
						
							| 
									
										
										
										
											2020-08-08 17:50:43 +02:00
										 |  |  |             {header: Img.AsImageElement(layoutToUse.icon), content: welcome}, | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |             {header: `<img src='./assets/osm-logo.svg'>`, content:  | 
					
						
							|  |  |  |                 Translations.t.general.openStreetMapIntro}, | 
					
						
							| 
									
										
										
										
											2020-08-07 00:45:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (State.state.featureSwitchShareScreen.data) { | 
					
						
							| 
									
										
										
										
											2020-08-30 01:13:18 +02:00
										 |  |  |             tabs.push({header: `<img src='./assets/share.svg'>`, content: new ShareScreen()}); | 
					
						
							| 
									
										
										
										
											2020-08-07 00:45:33 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 01:40:43 +02:00
										 |  |  |         if (State.state.featureSwitchMoreQuests.data) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 00:20:20 +02:00
										 |  |  |             tabs.push({ | 
					
						
							| 
									
										
										
										
											2020-09-05 01:40:43 +02:00
										 |  |  |                 header: `<img src='./assets/add.svg'>`, | 
					
						
							|  |  |  |                 content: new VariableUiElement(State.state.osmConnection.userDetails.map(userdetails => { | 
					
						
							|  |  |  |                     if(userdetails.csCount < State.userJourney.moreScreenUnlock){ | 
					
						
							|  |  |  |                         return ""; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     return new MoreScreen().Render() | 
					
						
							|  |  |  |                 }, [Locale.language])) | 
					
						
							| 
									
										
										
										
											2020-08-25 00:20:20 +02:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2020-08-07 00:45:33 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 01:40:43 +02:00
										 |  |  |         tabs.push({ | 
					
						
							|  |  |  |                 header: `<img src='./assets/help.svg'>`, | 
					
						
							|  |  |  |                 content: new VariableUiElement(State.state.osmConnection.userDetails.map(userdetails => { | 
					
						
							|  |  |  |                     if (userdetails.csCount < State.userJourney.mapCompleteHelpUnlock) { | 
					
						
							|  |  |  |                         return "" | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     return Translations.t.general.aboutMapcomplete.Render(); | 
					
						
							|  |  |  |                 }, [Locale.language])) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 01:40:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |         return new TabbedComponent(tabs, State.state.welcomeMessageOpenedTab) | 
					
						
							|  |  |  |             .ListenTo(State.state.osmConnection.userDetails); | 
					
						
							| 
									
										
										
										
											2020-07-29 15:48:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |     static InitWelcomeMessage() { | 
					
						
							| 
									
										
										
										
											2020-07-29 15:48:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |         const fullOptions = this.CreateWelcomePane(); | 
					
						
							| 
									
										
										
										
											2020-07-29 15:48:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  |         const help = new FixedUiElement(`<div class='collapse-button-img'><img src='assets/help.svg'  alt='help'></div>`); | 
					
						
							|  |  |  |         const close = new FixedUiElement(`<div class='collapse-button-img'><img src='assets/close.svg'  alt='close'></div>`); | 
					
						
							| 
									
										
										
										
											2020-07-29 18:35:46 +02:00
										 |  |  |         const checkbox = new CheckBox( | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  |             new Combine([ | 
					
						
							|  |  |  |                 "<span class='collapse-button'>", close, "</span>", | 
					
						
							|  |  |  |                 "<span id='welcomeMessage'>", fullOptions.onClick(() => { | 
					
						
							|  |  |  |                 }), "</span>"]), | 
					
						
							|  |  |  |             new Combine(["<span class='open-button'>", help, "</span>"]) | 
					
						
							|  |  |  |             , true | 
					
						
							|  |  |  |         ).AttachTo("messagesbox"); | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |         const openedTime = new Date().getTime(); | 
					
						
							|  |  |  |         State.state.locationControl.addCallback(() => { | 
					
						
							|  |  |  |             if (new Date().getTime() - openedTime < 15 * 1000) { | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |                 // Don't autoclose the first 15 secs when the map is moving
 | 
					
						
							| 
									
										
										
										
											2020-07-29 18:35:46 +02:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             checkbox.isEnabled.setData(false); | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |         const fullOptions2 = this.CreateWelcomePane(); | 
					
						
							|  |  |  |         State.state.fullScreenMessage.setData(fullOptions2) | 
					
						
							| 
									
										
										
										
											2020-08-30 01:13:18 +02:00
										 |  |  |         new FixedUiElement(`<div class='collapse-button-img shadow'><img src='assets/help.svg'  alt='help'></div>`).onClick(() => { | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |             State.state.fullScreenMessage.setData(fullOptions2) | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  |         }).AttachTo("help-button-mobile"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-31 02:59:47 +02:00
										 |  |  |      | 
					
						
							|  |  |  |     static CreateLanguagePicker(label: string | UIElement = "") { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  |         if (State.state.layoutToUse.data.supportedLanguages.length <= 1) { | 
					
						
							|  |  |  |             return undefined; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 02:59:47 +02:00
										 |  |  |         return new DropDown(label, State.state.layoutToUse.data.supportedLanguages.map(lang => { | 
					
						
							|  |  |  |                 return {value: lang, shown: lang} | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ), Locale.language); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |     private static GenerateLayerControlPanel() { | 
					
						
							| 
									
										
										
										
											2020-09-25 21:58:29 +02:00
										 |  |  |         let layerControlPanel: UIElement = new BackgroundSelector(State.state); | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |         layerControlPanel.SetStyle("margin:1em"); | 
					
						
							| 
									
										
										
										
											2020-09-25 21:58:29 +02:00
										 |  |  |         layerControlPanel.onClick(() => {}); | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  |         if (State.state.filteredLayers.data.length > 1) { | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |             const layerSelection = new LayerSelection(); | 
					
						
							| 
									
										
										
										
											2020-09-25 21:58:29 +02:00
										 |  |  |             layerSelection.onClick(() => {}); | 
					
						
							| 
									
										
										
										
											2020-09-17 20:59:05 +02:00
										 |  |  |             layerControlPanel = new Combine([layerSelection, "<br/>",layerControlPanel]); | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |         return layerControlPanel; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |     static InitLayerSelection() { | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |         InitUiElements.OnlyIf(State.state.featureSwitchLayers, () => { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |             const layerControlPanel = this.GenerateLayerControlPanel() | 
					
						
							|  |  |  |                 .SetStyle("display:block;padding:1em;border-radius:1em;"); | 
					
						
							|  |  |  |             const closeButton = new Combine([Img.openFilterButton]) | 
					
						
							|  |  |  |                 .SetStyle("display:block; width: min-content; background: #e5f5ff;padding:1em; border-radius:1em;"); | 
					
						
							|  |  |  |             const checkbox = new CheckBox( | 
					
						
							|  |  |  |                 new Combine([ | 
					
						
							|  |  |  |                     closeButton, | 
					
						
							|  |  |  |                     layerControlPanel]).SetStyle("display:flex;flex-direction:row;") | 
					
						
							| 
									
										
										
										
											2020-09-17 20:59:05 +02:00
										 |  |  |                     .SetClass("hidden-on-mobile") | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |                 , | 
					
						
							|  |  |  |                 new Combine([Img.closedFilterButton]) | 
					
						
							|  |  |  |                     .SetStyle("display:block;border-radius:50%;background:white;padding:1em;"), | 
					
						
							| 
									
										
										
										
											2020-09-17 23:53:57 +02:00
										 |  |  |                 State.state.layerControlIsOpened | 
					
						
							| 
									
										
										
										
											2020-08-22 13:02:31 +02:00
										 |  |  |             ); | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |             checkbox | 
					
						
							|  |  |  |                 .AttachTo("layer-selection"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |             State.state.bm.Location.addCallback(() => { | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |                 // Close the layer selection when the map is moved
 | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |                 checkbox.isEnabled.setData(false); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-13 03:29:44 +02:00
										 |  |  |             const fullScreen = this.GenerateLayerControlPanel(); | 
					
						
							|  |  |  |             checkbox.isEnabled.addCallback(isEnabled => { | 
					
						
							|  |  |  |                 if (isEnabled) { | 
					
						
							|  |  |  |                     State.state.fullScreenMessage.setData(fullScreen); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             State.state.fullScreenMessage.addCallbackAndRun(latest => { | 
					
						
							|  |  |  |                 if (latest === undefined) { | 
					
						
							|  |  |  |                     checkbox.isEnabled.setData(false); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  |      | 
					
						
							|  |  |  |     static InitBaseMap(){ | 
					
						
							| 
									
										
										
										
											2020-08-08 02:16:42 +02:00
										 |  |  |         const bm = new Basemap("leafletDiv", State.state.locationControl, new VariableUiElement( | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  |             State.state.locationControl.map((location) => { | 
					
						
							| 
									
										
										
										
											2020-09-17 19:24:57 +02:00
										 |  |  |                 const mapComplete = `<a href='https://github.com/pietervdvn/MapComplete' target='_blank'>Mapcomplete ${State.vNumber}</a>` | 
					
						
							|  |  |  |                 const reportBug = `<a href='https://github.com/pietervdvn/MapComplete/issues' target='_blank'><img src='./assets/bug.svg' class='small-userbadge-icon'></a>`; | 
					
						
							|  |  |  |                 | 
					
						
							|  |  |  |                 const layoutId = State.state.layoutToUse.data.id; | 
					
						
							|  |  |  |                 const osmChaLink = `https://osmcha.org/?filters=%7B%22comment%22%3A%5B%7B%22label%22%3A%22%23${layoutId}%22%2C%22value%22%3A%22%23${layoutId}%22%7D%5D%2C%22date__gte%22%3A%5B%7B%22label%22%3A%222020-07-05%22%2C%22value%22%3A%222020-07-05%22%7D%5D%2C%22editor%22%3A%5B%7B%22label%22%3A%22MapComplete%22%2C%22value%22%3A%22MapComplete%22%7D%5D%7D` | 
					
						
							|  |  |  |                 const stats = `<a href='${osmChaLink}' target='_blank'><img src='./assets/statistics.svg' class='small-userbadge-icon'></a>`; | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  |                 let editHere = ""; | 
					
						
							|  |  |  |                 if (location !== undefined) { | 
					
						
							| 
									
										
										
										
											2020-09-17 19:24:57 +02:00
										 |  |  |                     editHere = | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  |                         "<a href='https://www.openstreetmap.org/edit?editor=id#map=" + location.zoom + "/" + location.lat + "/" + location.lon + "' target='_blank'>" + | 
					
						
							|  |  |  |                         "<img src='./assets/pencil.svg' alt='edit here' class='small-userbadge-icon'>" + | 
					
						
							|  |  |  |                         "</a>" | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-09-22 00:22:50 +02:00
										 |  |  |                 let editWithJosm = "" | 
					
						
							|  |  |  |                 if(location !== undefined && | 
					
						
							|  |  |  |                     State.state.osmConnection !== undefined && | 
					
						
							|  |  |  |                     State.state.bm !== undefined && | 
					
						
							|  |  |  |                     State.state.osmConnection.userDetails.data.csCount >= State.userJourney.tagsVisibleAndWikiLinked){ | 
					
						
							| 
									
										
										
										
											2020-09-22 01:15:13 +02:00
										 |  |  |                     const bounds = (State.state.bm as Basemap).map.getBounds(); | 
					
						
							|  |  |  |                     const top = bounds.getNorth(); | 
					
						
							|  |  |  |                     const bottom = bounds.getSouth(); | 
					
						
							|  |  |  |                     const right = bounds.getEast(); | 
					
						
							|  |  |  |                     const left = bounds.getWest(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     const josmLink = `http://127.0.0.1:8111/load_and_zoom?left=${left}&right=${right}&top=${top}&bottom=${bottom}` | 
					
						
							|  |  |  |                     editWithJosm = | 
					
						
							| 
									
										
										
										
											2020-09-22 00:22:50 +02:00
										 |  |  |                         `<a href='${josmLink}' target='_blank'><img src='./assets/josm_logo.svg' alt='edit here' class='small-userbadge-icon'></a>` | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-09-27 01:38:51 +02:00
										 |  |  |                 return new Combine([mapComplete, reportBug, " | ", stats, " | ", editHere, editWithJosm]).Render(); | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-22 00:22:50 +02:00
										 |  |  |             }, [State.state.osmConnection.userDetails]) | 
					
						
							| 
									
										
										
										
											2020-09-27 01:38:51 +02:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2020-09-22 00:22:50 +02:00
										 |  |  |         ); | 
					
						
							| 
									
										
										
										
											2020-08-08 02:16:42 +02:00
										 |  |  |         State.state.bm = bm; | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  |         State.state.layerUpdater = new LayerUpdater(State.state); | 
					
						
							| 
									
										
										
										
											2020-09-27 01:38:51 +02:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2020-08-08 02:16:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     static InitLayers() { | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const flayers: FilteredLayer[] = [] | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  |         const presets: Preset[] = []; | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |         const state = State.state; | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |         for (const layer of state.layoutToUse.data.layers) { | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (typeof (layer) === "string") { | 
					
						
							|  |  |  |                 throw "Layer " + layer + " was not substituted"; | 
					
						
							| 
									
										
										
										
											2020-08-31 02:59:47 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             const generateInfo = (tagsES, feature) => { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return new FeatureInfoBox( | 
					
						
							|  |  |  |                     feature, | 
					
						
							|  |  |  |                     tagsES, | 
					
						
							|  |  |  |                     layer.title, | 
					
						
							|  |  |  |                     layer.elementsToShow, | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (const preset of layer.presets ?? []) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (preset.icon === undefined) { | 
					
						
							|  |  |  |                     const tags = {}; | 
					
						
							|  |  |  |                     for (const tag of preset.tags) { | 
					
						
							|  |  |  |                         const k = tag.key; | 
					
						
							|  |  |  |                         if (typeof (k) === "string") { | 
					
						
							|  |  |  |                             tags[k] = tag.value; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     preset.icon = layer.style(tags)?.icon?.iconUrl; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  |                 presets.push(preset); | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             const flayer: FilteredLayer = FilteredLayer.fromDefinition(layer, generateInfo); | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |             flayers.push(flayer); | 
					
						
							| 
									
										
										
										
											2020-08-08 02:16:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             QueryParameters.GetQueryParameter("layer-" + layer.id, "true") | 
					
						
							|  |  |  |                 .map<boolean>((str) => str !== "false", [], (b) => b.toString()) | 
					
						
							|  |  |  |                 .syncWith( | 
					
						
							|  |  |  |                     flayer.isDisplayed | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  |         State.state.filteredLayers.setData(flayers); | 
					
						
							|  |  |  |         State.state.presets.setData(presets); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |