forked from MapComplete/MapComplete
		
	Fixing too many bugs, cleaning up some old parts of the code
This commit is contained in:
		
							parent
							
								
									3d05999f85
								
							
						
					
					
						commit
						00a6611e1f
					
				
					 21 changed files with 706 additions and 436 deletions
				
			
		|  | @ -259,8 +259,14 @@ export class FromJSON { | |||
|         const iconSize = FromJSON.TagRenderingWithDefault(json.iconSize, "iconSize", "40,40,center"); | ||||
|         const color = FromJSON.TagRenderingWithDefault(json.color, "layercolor", "#0000ff"); | ||||
|         const width = FromJSON.TagRenderingWithDefault(json.width, "layerwidth", "10"); | ||||
|         const tagRenderings =  json.tagRenderings?.map(FromJSON.TagRendering) ?? []; | ||||
|          | ||||
| 
 | ||||
|         let tagRenderingDefs = json.tagRenderings ?? []; | ||||
|         if (tagRenderingDefs.indexOf("images") < 0) { | ||||
|             tagRenderingDefs = ["images", ...tagRenderingDefs]; | ||||
|         } | ||||
|         let tagRenderings = tagRenderingDefs.map(FromJSON.TagRendering); | ||||
| 
 | ||||
| 
 | ||||
|         const renderTags = {"id": "node/-1"} | ||||
|         const presets: Preset[] = json?.presets?.map(preset => { | ||||
|             return ({ | ||||
|  | @ -294,7 +300,7 @@ export class FromJSON { | |||
| 
 | ||||
|             // the anchor is always set from the center of the point
 | ||||
|             // x, y with x going right and y going down if the values are bigger
 | ||||
|             const popupAnchor = [0, -iconAnchor[1]+3]; | ||||
|             const popupAnchor = [0, 3 - iconAnchor[1]]; | ||||
| 
 | ||||
|             return { | ||||
|                 color: color.GetContent(tags).txt, | ||||
|  |  | |||
|  | @ -105,7 +105,16 @@ export class UIEventSource<T>{ | |||
|         }); | ||||
|          | ||||
|         return newSource; | ||||
|          | ||||
|     } | ||||
|      | ||||
|     public static Chronic(millis: number):UIEventSource<Date>{ | ||||
|         const source = new UIEventSource<Date>(undefined); | ||||
|         function run() { | ||||
|             source.setData(new Date()); | ||||
|             window.setTimeout(run, millis); | ||||
|         } | ||||
|         run(); | ||||
|         return source; | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										35
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								State.ts
									
										
									
									
									
								
							|  | @ -23,16 +23,15 @@ export class State { | |||
|     // The singleton of the global state
 | ||||
|     public static state: State; | ||||
|      | ||||
|     public static vNumber = "0.0.7d Refactored"; | ||||
|     public static vNumber = "0.0.7e Fixing all the bugs"; | ||||
|      | ||||
|     // The user journey states thresholds when a new feature gets unlocked
 | ||||
|     public static userJourney = { | ||||
|         customLayoutUnlock: 50, | ||||
|         themeGeneratorUnlock: 500, | ||||
|         tagsVisibleAt: 200, | ||||
|         tagsVisibleAndWikiLinked: 250 | ||||
| 
 | ||||
| 
 | ||||
|         personalLayoutUnlock: 20, | ||||
|         tagsVisibleAt: 100, | ||||
|         tagsVisibleAndWikiLinked: 150, | ||||
|         themeGeneratorReadOnlyUnlock: 200, | ||||
|         themeGeneratorFullUnlock: 500, | ||||
|     }; | ||||
| 
 | ||||
|     public static runningFromConsole: boolean = false;  | ||||
|  | @ -68,13 +67,6 @@ export class State { | |||
|      *  The message that should be shown at the center of the screen | ||||
|      */ | ||||
|     public readonly centerMessage = new UIEventSource<string>(""); | ||||
| 
 | ||||
|     /** | ||||
|      * The countdown: if set to e.g. ten, it'll start counting down. When reaching zero, changes will be saved. NB: this is implemented later, not in the eventSource | ||||
|      */ | ||||
|     public readonly secondsTillChangesAreSaved = new UIEventSource<number>(0); | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      This message is shown full screen on mobile devices | ||||
|      */ | ||||
|  | @ -116,10 +108,6 @@ export class State { | |||
|         latlng: number, | ||||
|         accuracy: number | ||||
|     }> = new UIEventSource<{ latlng: number, accuracy: number }>(undefined); | ||||
| 
 | ||||
|     /** After this many milliseconds without changes, saves are sent of to OSM | ||||
|      */ | ||||
|     public readonly saveTimeout = new UIEventSource<number>(30 * 1000); | ||||
|     public layoutDefinition: string; | ||||
|     public installedThemes: UIEventSource<{ layout: Layout; definition: string }[]>; | ||||
| 
 | ||||
|  | @ -259,16 +247,5 @@ export class State { | |||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         | ||||
| 
 | ||||
|     } | ||||
|      | ||||
|     public GetFilteredLayerFor(id: string) : FilteredLayer{ | ||||
|         for (const flayer of this.filteredLayers.data) { | ||||
|             if(flayer.layerDef.id === id){ | ||||
|                 return flayer; | ||||
|             } | ||||
|         } | ||||
|         return undefined; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import {LayoutConfigJson} from "../../Customizations/JSON/LayoutConfigJson"; | |||
| import Combine from "../Base/Combine"; | ||||
| import {GenerateEmpty} from "./GenerateEmpty"; | ||||
| import LayerPanelWithPreview from "./LayerPanelWithPreview"; | ||||
| import {UserDetails} from "../../Logic/Osm/OsmConnection"; | ||||
| 
 | ||||
| export default class AllLayersPanel extends UIElement { | ||||
| 
 | ||||
|  | @ -15,28 +16,29 @@ export default class AllLayersPanel extends UIElement { | |||
|     private readonly languages: UIEventSource<string[]>; | ||||
| 
 | ||||
|     constructor(config: UIEventSource<LayoutConfigJson>, | ||||
|                 languages: UIEventSource<any>) { | ||||
|                 languages: UIEventSource<any>, userDetails: UserDetails) { | ||||
|         super(undefined); | ||||
|         this._config = config; | ||||
|         this.languages = languages; | ||||
| 
 | ||||
|         this.createPanels(); | ||||
|         this.createPanels(userDetails); | ||||
|         const self = this; | ||||
|         config.map<number>(config => config.layers.length).addCallback(() => self.createPanels()); | ||||
|         config.map<number>(config => config.layers.length).addCallback(() => self.createPanels(userDetails)); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     private createPanels() { | ||||
|     private createPanels(userDetails: UserDetails) { | ||||
|         const self = this; | ||||
|         const tabs = []; | ||||
| 
 | ||||
|         const layers = this._config.data.layers; | ||||
|         for (let i = 0; i < layers.length; i++) { | ||||
|    | ||||
| 
 | ||||
|             tabs.push({ | ||||
|                 header: "<img src='./assets/bug.svg'>", | ||||
|                 content: new LayerPanelWithPreview(this._config, this.languages, i)}); | ||||
|                 content: new LayerPanelWithPreview(this._config, this.languages, i, userDetails) | ||||
|             }); | ||||
|         } | ||||
|         tabs.push({ | ||||
|             header: "<img src='./assets/layersAdd.svg'>", | ||||
|  |  | |||
|  | @ -0,0 +1,115 @@ | |||
| import {UIElement} from "../UIElement"; | ||||
| import {OsmConnection, UserDetails} from "../../Logic/Osm/OsmConnection"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| import SingleSetting from "./SingleSetting"; | ||||
| import GeneralSettings from "./GeneralSettings"; | ||||
| import Combine from "../Base/Combine"; | ||||
| import {VariableUiElement} from "../Base/VariableUIElement"; | ||||
| import {TabbedComponent} from "../Base/TabbedComponent"; | ||||
| import PageSplit from "../Base/PageSplit"; | ||||
| import HelpText from "../../Customizations/HelpText"; | ||||
| import AllLayersPanel from "./AllLayersPanel"; | ||||
| import SharePanel from "./SharePanel"; | ||||
| import {LayoutConfigJson} from "../../Customizations/JSON/LayoutConfigJson"; | ||||
| import {SubtleButton} from "../Base/SubtleButton"; | ||||
| import {State} from "../../State"; | ||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | ||||
| import SavePanel from "./SavePanel"; | ||||
| import {LocalStorageSource} from "../../Logic/Web/LocalStorageSource"; | ||||
| 
 | ||||
| 
 | ||||
| export default class CustomGeneratorPanel extends UIElement { | ||||
|     private mainPanel: UIElement; | ||||
|     private loginButton: UIElement; | ||||
| 
 | ||||
|     private connection: OsmConnection; | ||||
| 
 | ||||
|     constructor(connection: OsmConnection, layout: LayoutConfigJson) { | ||||
|         super(connection.userDetails); | ||||
|         this.connection = connection; | ||||
|         this.SetClass("main-tabs"); | ||||
|         this.loginButton = new SubtleButton("", "Login to create a custom theme").onClick(() => connection.AttemptLogin()) | ||||
|         const self = this; | ||||
|         self.mainPanel = new FixedUiElement("Attempting to log in..."); | ||||
|         connection.OnLoggedIn(userDetails => { | ||||
|             self.InitMainPanel(layout, userDetails, connection); | ||||
|             self.Update(); | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     private InitMainPanel(layout: LayoutConfigJson, userDetails: UserDetails, connection: OsmConnection) { | ||||
|         const es = new UIEventSource(layout); | ||||
|         const encoded = es.map(config => btoa(JSON.stringify(config))); | ||||
|         encoded.addCallback(encoded => LocalStorageSource.Get("\"last-custom-theme\"")) | ||||
|         const liveUrl = encoded.map(encoded => `./index.html?userlayout=${es.data.id}#${encoded}`) | ||||
|         const iframe = liveUrl.map(url => `<iframe src='${url}' width='100%' height='99%' style="box-sizing: border-box" title='Theme Preview'></iframe>`); | ||||
|         const currentSetting = new UIEventSource<SingleSetting<any>>(undefined) | ||||
|         const generalSettings = new GeneralSettings(es, currentSetting); | ||||
|         const languages = generalSettings.languages; | ||||
| 
 | ||||
|         const chronic = UIEventSource.Chronic(120 * 1000) | ||||
|             .map(date => { | ||||
|                 if (es.data.id == undefined) { | ||||
|                     return undefined | ||||
|                 } | ||||
|                 if (es.data.id === "") { | ||||
|                     return undefined; | ||||
|                 } | ||||
|                 const pref = connection.GetLongPreference("installed-theme-" + es.data.id); | ||||
|                 pref.setData(encoded.data); | ||||
|                 return date; | ||||
|             }); | ||||
| 
 | ||||
|         const preview = new Combine([ | ||||
|             new VariableUiElement(iframe.stabilized(2500)) | ||||
|         ]).SetClass("preview") | ||||
|         this.mainPanel = new TabbedComponent([ | ||||
|             { | ||||
|                 header: "<img src='./assets/gear.svg'>", | ||||
|                 content: | ||||
|                     new PageSplit( | ||||
|                         generalSettings.SetStyle("width: 50vw;"), | ||||
|                         new Combine([ | ||||
|                             new HelpText(currentSetting).SetStyle("height:calc(100% - 65vh); width: 100%; display:block; overflow-y: auto"), | ||||
|                             preview.SetStyle("height:65vh; width:100%; display:block") | ||||
|                         ]).SetStyle("position:relative; width: 50%;") | ||||
|                     ) | ||||
|             }, | ||||
|             { | ||||
|                 header: "<img src='./assets/layers.svg'>", | ||||
|                 content: new AllLayersPanel(es, languages, userDetails) | ||||
|             }, | ||||
|             { | ||||
|                 header: "<img src='./assets/floppy.svg'>", | ||||
|                 content: new SavePanel(this.connection, es, chronic) | ||||
| 
 | ||||
|             }, | ||||
|             { | ||||
|                 header: "<img src='./assets/share.svg'>", | ||||
|                 content: new SharePanel(es, liveUrl) | ||||
|             } | ||||
|         ]) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
|         const ud = this.connection.userDetails.data; | ||||
|         if (!ud.loggedIn) { | ||||
|             return new Combine([ | ||||
|                 "<h3>Not Logged in</h3>", | ||||
|                 "You need to be logged in in order to create a custom theme", | ||||
|                 this.loginButton | ||||
|             ]).Render(); | ||||
|         } | ||||
|         if (ud.csCount <= State.userJourney.themeGeneratorReadOnlyUnlock) { | ||||
|             return new Combine([ | ||||
|                 "<h3>Too little experience/h3>", | ||||
|                 `Creating your own (readonly) themes can only be done if you have more then <b>${State.userJourney.themeGeneratorReadOnlyUnlock}</b> changesets made`, | ||||
|                 `Making a theme including survey options can be done at <b>${State.userJourney.themeGeneratorFullUnlock}</b> changesets`, | ||||
|                 this.loginButton | ||||
|             ]).Render(); | ||||
|         } | ||||
|         return this.mainPanel.Render() | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -16,6 +16,9 @@ import {TagRenderingConfigJson} from "../../Customizations/JSON/TagRenderingConf | |||
| import {MultiInput} from "../Input/MultiInput"; | ||||
| import {LayerConfigJson} from "../../Customizations/JSON/LayerConfigJson"; | ||||
| import PresetInputPanel from "./PresetInputPanel"; | ||||
| import {UserDetails} from "../../Logic/Osm/OsmConnection"; | ||||
| import {State} from "../../State"; | ||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | ||||
| 
 | ||||
| /** | ||||
|  * Shows the configuration for a single layer | ||||
|  | @ -38,10 +41,11 @@ export default class LayerPanel extends UIElement { | |||
|     constructor(config: UIEventSource<LayoutConfigJson>, | ||||
|                 languages: UIEventSource<string[]>, | ||||
|                 index: number, | ||||
|                 currentlySelected: UIEventSource<SingleSetting<any>>) { | ||||
|                 currentlySelected: UIEventSource<SingleSetting<any>>, | ||||
|                 userDetails: UserDetails) { | ||||
|         super(); | ||||
|         this._config = config; | ||||
|         this.mapRendering = this.setupRenderOptions(config, languages, index, currentlySelected); | ||||
|         this.mapRendering = this.setupRenderOptions(config, languages, index, currentlySelected, userDetails); | ||||
| 
 | ||||
|         const actualDeleteButton = new SubtleButton( | ||||
|             "./assets/delete.svg", | ||||
|  | @ -100,7 +104,7 @@ export default class LayerPanel extends UIElement { | |||
|             currentlySelected); | ||||
|         const self = this; | ||||
| 
 | ||||
|         const popupTitleRendering = new TagRenderingPanel(languages, currentlySelected, { | ||||
|         const popupTitleRendering = new TagRenderingPanel(languages, currentlySelected, userDetails, { | ||||
|             title: "Popup title", | ||||
|             description: "This is the rendering shown as title in the popup for this element", | ||||
|             disableQuestions: true | ||||
|  | @ -113,7 +117,7 @@ export default class LayerPanel extends UIElement { | |||
|         const tagRenderings = new MultiInput<TagRenderingConfigJson>("Add a tag rendering/question", | ||||
|             () => ({}), | ||||
|             () => { | ||||
|                 const tagPanel = new TagRenderingPanel(languages, currentlySelected) | ||||
|                 const tagPanel = new TagRenderingPanel(languages, currentlySelected, userDetails) | ||||
|                 self.registerTagRendering(tagPanel); | ||||
|                 return tagPanel; | ||||
|             }); | ||||
|  | @ -124,11 +128,16 @@ export default class LayerPanel extends UIElement { | |||
|             } | ||||
|         ) | ||||
| 
 | ||||
|         const presetPanel = new MultiInput("Add a preset", | ||||
|             () => ({tags: [], title: {}}), | ||||
|             () => new PresetInputPanel(currentlySelected, languages)); | ||||
|         this.presetsPanel = presetPanel; | ||||
|         new SingleSetting(config, presetPanel, ["layers", index, "presets"], "Presets", "") | ||||
|         if (userDetails.csCount >= State.userJourney.themeGeneratorFullUnlock) { | ||||
| 
 | ||||
|             const presetPanel = new MultiInput("Add a preset", | ||||
|                 () => ({tags: [], title: {}}), | ||||
|                 () => new PresetInputPanel(currentlySelected, languages)); | ||||
|             new SingleSetting(config, presetPanel, ["layers", index, "presets"], "Presets", "") | ||||
|             this.presetsPanel = presetPanel; | ||||
|         } else { | ||||
|             this.presetsPanel = new FixedUiElement(`Creating a custom theme which also edits OSM is only unlocked after ${State.userJourney.themeGeneratorFullUnlock} changesets`).SetClass("alert"); | ||||
|         } | ||||
| 
 | ||||
|         function loadTagRenderings() { | ||||
|             const values = (config.data.layers[index] as LayerConfigJson).tagRenderings; | ||||
|  | @ -152,27 +161,29 @@ export default class LayerPanel extends UIElement { | |||
|     private setupRenderOptions(config: UIEventSource<LayoutConfigJson>, | ||||
|                                languages: UIEventSource<string[]>, | ||||
|                                index: number, | ||||
|                                currentlySelected: UIEventSource<SingleSetting<any>>): UIElement { | ||||
|                                currentlySelected: UIEventSource<SingleSetting<any>>, | ||||
|                                userDetails: UserDetails | ||||
|     ): UIElement { | ||||
|         const iconSelect = new TagRenderingPanel( | ||||
|             languages, currentlySelected, | ||||
|             languages, currentlySelected, userDetails, | ||||
|             { | ||||
|                 title: "Icon", | ||||
|                 description: "A visual representation for this layer and for the points on the map.", | ||||
|                 disableQuestions: true | ||||
|             }); | ||||
|         const size = new TagRenderingPanel(languages, currentlySelected, | ||||
|         const size = new TagRenderingPanel(languages, currentlySelected, userDetails, | ||||
|             { | ||||
|                 title: "Icon Size", | ||||
|                 description: "The size of the icons on the map in pixels. Can vary based on the tagging", | ||||
|                 disableQuestions: true | ||||
|             }); | ||||
|         const color = new TagRenderingPanel(languages, currentlySelected, | ||||
|         const color = new TagRenderingPanel(languages, currentlySelected, userDetails, | ||||
|             { | ||||
|                 title: "Way and area color", | ||||
|                 description: "The color or a shown way or area. Can vary based on the tagging", | ||||
|                 disableQuestions: true | ||||
|             }); | ||||
|         const stroke = new TagRenderingPanel(languages, currentlySelected, | ||||
|         const stroke = new TagRenderingPanel(languages, currentlySelected, userDetails, | ||||
|             { | ||||
|                 title: "Stroke width", | ||||
|                 description: "The width of lines representing ways and the outline of areas. Can vary based on the tags", | ||||
|  |  | |||
|  | @ -8,16 +8,17 @@ import {FromJSON} from "../../Customizations/JSON/FromJSON"; | |||
| import Combine from "../Base/Combine"; | ||||
| import PageSplit from "../Base/PageSplit"; | ||||
| import TagRenderingPreview from "./TagRenderingPreview"; | ||||
| import {UserDetails} from "../../Logic/Osm/OsmConnection"; | ||||
| 
 | ||||
| 
 | ||||
| export default class LayerPanelWithPreview extends UIElement{ | ||||
|     private panel: UIElement; | ||||
|      | ||||
|     constructor(config: UIEventSource<any>, languages: UIEventSource<string[]>, index: number) { | ||||
|     constructor(config: UIEventSource<any>, languages: UIEventSource<string[]>, index: number, userDetails: UserDetails) { | ||||
|         super(); | ||||
| 
 | ||||
|         const currentlySelected = new UIEventSource<(SingleSetting<any>)>(undefined); | ||||
|         const layer = new LayerPanel(config, languages, index, currentlySelected); | ||||
|         const layer = new LayerPanel(config, languages, index, currentlySelected, userDetails); | ||||
|         const helpText = new HelpText(currentlySelected); | ||||
| 
 | ||||
|         const previewTagInput = new MultiTagInput(); | ||||
|  |  | |||
							
								
								
									
										49
									
								
								UI/CustomGenerator/SavePanel.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								UI/CustomGenerator/SavePanel.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | |||
| import {UIElement} from "../UIElement"; | ||||
| import {VariableUiElement} from "../Base/VariableUIElement"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| import {LayoutConfigJson} from "../../Customizations/JSON/LayoutConfigJson"; | ||||
| import Combine from "../Base/Combine"; | ||||
| import {OsmConnection} from "../../Logic/Osm/OsmConnection"; | ||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | ||||
| 
 | ||||
| export default class SavePanel extends UIElement { | ||||
|     private json: UIElement; | ||||
|     private lastSaveEl: UIElement; | ||||
| 
 | ||||
|     constructor( | ||||
|         connection: OsmConnection, | ||||
|         config: UIEventSource<LayoutConfigJson>, | ||||
|         chronic: UIEventSource<Date>) { | ||||
|         super(); | ||||
| 
 | ||||
|       | ||||
| 
 | ||||
|         this.lastSaveEl = new VariableUiElement(chronic | ||||
|             .map(date => { | ||||
|                 if (date === undefined) { | ||||
|                     return new FixedUiElement("Your theme will be saved automatically within two minutes... Click here to force saving").SetClass("alert").Render() | ||||
|                 } | ||||
|                 return "Your theme was last saved at " + date.toISOString() | ||||
|             })).onClick(() => chronic.setData(new Date())); | ||||
| 
 | ||||
|         this.json = new VariableUiElement(config.map(config => { | ||||
|             return JSON.stringify(config, null, 2) | ||||
|                 .replace(/\n/g, "<br/>") | ||||
|                 .replace(/ /g, " "); | ||||
|         })) | ||||
|             .SetClass("literal-code"); | ||||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
|         return new Combine([ | ||||
|             "<h3>Saving</h3>", | ||||
|             this.lastSaveEl, | ||||
|             "<h3>JSON configuration</h3>", | ||||
|             "The url hash is actually no more then a BASE64-encoding of the below JSON. This json contains the full configuration of the theme.<br/>" + | ||||
|             "This configuration is mainly useful for debugging", | ||||
|             this.json | ||||
|         ]).SetClass("scrollable") | ||||
|             .Render(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -12,6 +12,8 @@ import {MultiInput} from "../Input/MultiInput"; | |||
| import MappingInput from "./MappingInput"; | ||||
| import {AndOrTagConfigJson} from "../../Customizations/JSON/TagConfigJson"; | ||||
| import {TagRenderingConfigJson} from "../../Customizations/JSON/TagRenderingConfigJson"; | ||||
| import {UserDetails} from "../../Logic/Osm/OsmConnection"; | ||||
| import {State} from "../../State"; | ||||
| 
 | ||||
| export default class TagRenderingPanel extends InputElement<TagRenderingConfigJson> { | ||||
| 
 | ||||
|  | @ -24,6 +26,7 @@ export default class TagRenderingPanel extends InputElement<TagRenderingConfigJs | |||
| 
 | ||||
|     constructor(languages: UIEventSource<string[]>, | ||||
|                 currentlySelected: UIEventSource<SingleSetting<any>>, | ||||
|                 userDetails: UserDetails, | ||||
|                 options?: { | ||||
|                     title?: string, | ||||
|                     description?: string, | ||||
|  | @ -36,6 +39,10 @@ export default class TagRenderingPanel extends InputElement<TagRenderingConfigJs | |||
|         this.SetClass("min-height"); | ||||
| 
 | ||||
|         this.options = options ?? {}; | ||||
|         const questionsNotUnlocked = userDetails.csCount < State.userJourney.themeGeneratorFullUnlock; | ||||
|         this.options.disableQuestions =  | ||||
|             (this.options.disableQuestions ?? false) &&  | ||||
|             questionsNotUnlocked;  | ||||
| 
 | ||||
|         this.intro = new Combine(["<h3>", options?.title ?? "TagRendering", "</h3>", options?.description ?? ""]) | ||||
|         this.IsImage = options?.isImage ?? false; | ||||
|  | @ -47,9 +54,9 @@ export default class TagRenderingPanel extends InputElement<TagRenderingConfigJs | |||
|             return new SingleSetting<any>(value, input, id, name, description); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         const questionSettings = [ | ||||
| 
 | ||||
|              | ||||
|             setting(new MultiLingualTextFields(languages), "question", "Question", "If the key or mapping doesn't match, this question is asked"), | ||||
| 
 | ||||
|             setting(new AndOrTagInput(), "condition", "Condition", | ||||
|  | @ -70,6 +77,8 @@ export default class TagRenderingPanel extends InputElement<TagRenderingConfigJs | |||
| 
 | ||||
|         const settings: (string | SingleSetting<any>)[] = [ | ||||
|             setting(new MultiLingualTextFields(languages), "render", "Value to show", " Renders this value. Note that <span class='literal-code'>{key}</span>-parts are substituted by the corresponding values of the element. If neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value."), | ||||
|              | ||||
|             questionsNotUnlocked ? `You need at least ${State.userJourney.themeGeneratorFullUnlock} changesets to unlock the 'question'-field and to use your theme to edit OSM data`: "", | ||||
|             ...(options?.disableQuestions ? [] : questionSettings), | ||||
| 
 | ||||
|             "<h3>Mappings</h3>", | ||||
|  |  | |||
|  | @ -26,10 +26,10 @@ export class FeatureInfoBox extends UIElement { | |||
|     private readonly _title: UIElement; | ||||
|     private readonly _osmLink: UIElement; | ||||
|     private readonly _wikipedialink: UIElement; | ||||
|     private _infoboxes: TagDependantUIElement[]; | ||||
|     private readonly _infoboxes: TagDependantUIElement[]; | ||||
| 
 | ||||
|     private _oneSkipped = Translations.t.general.oneSkippedQuestion.Clone(); | ||||
|     private _someSkipped = Translations.t.general.skippedQuestions.Clone(); | ||||
|     private readonly _oneSkipped = Translations.t.general.oneSkippedQuestion.Clone(); | ||||
|     private readonly _someSkipped = Translations.t.general.skippedQuestions.Clone(); | ||||
| 
 | ||||
|     constructor( | ||||
|         feature: any, | ||||
|  | @ -53,7 +53,7 @@ export class FeatureInfoBox extends UIElement { | |||
|                 tagRenderingOption.construct(deps)); | ||||
|         } | ||||
|         function initTags() { | ||||
|             self._infoboxes = [] | ||||
|             self._infoboxes.splice(0, self._infoboxes.length); | ||||
|             for (const tagRenderingOption of elementsToShow) { | ||||
|                 self._infoboxes.push( | ||||
|                     tagRenderingOption.construct(deps)); | ||||
|  | @ -101,10 +101,10 @@ export class FeatureInfoBox extends UIElement { | |||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         let questionsHtml = ""; | ||||
|         let questionElement: UIElement; | ||||
| 
 | ||||
|         if (!State.state.osmConnection.userDetails.data.loggedIn) { | ||||
|             let mostImportantQuestion; | ||||
|             let mostImportantQuestion ; | ||||
|             let score = -1000; | ||||
|             for (const question of questions) { | ||||
| 
 | ||||
|  | @ -114,7 +114,7 @@ export class FeatureInfoBox extends UIElement { | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             questionsHtml = mostImportantQuestion?.Render() ?? ""; | ||||
|             questionElement = mostImportantQuestion; | ||||
|         } else if (questions.length > 0) { | ||||
|             // We select the most important question and render that one
 | ||||
|             let mostImportantQuestion; | ||||
|  | @ -127,11 +127,11 @@ export class FeatureInfoBox extends UIElement { | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             questionsHtml = mostImportantQuestion?.Render() ?? ""; | ||||
|             questionElement = mostImportantQuestion; | ||||
|         } else if (skippedQuestions == 1) { | ||||
|             questionsHtml = this._oneSkipped.Render(); | ||||
|             questionElement = this._oneSkipped; | ||||
|         } else if (skippedQuestions > 0) { | ||||
|             questionsHtml = this._someSkipped.Render(); | ||||
|             questionElement = this._someSkipped; | ||||
|         } | ||||
| 
 | ||||
|         const title = new Combine([ | ||||
|  | @ -140,12 +140,16 @@ export class FeatureInfoBox extends UIElement { | |||
|             this._osmLink]); | ||||
| 
 | ||||
|         const infoboxcontents = new Combine( | ||||
|             [ new VerticalCombine(info, "infobox-information "), questionsHtml]); | ||||
|             [ new VerticalCombine(info, "infobox-information "), questionElement ?? ""]); | ||||
| 
 | ||||
|         return "<div class='featureinfobox'>" + | ||||
|             new Combine([ | ||||
|                 "<div class='featureinfoboxtitle'>" + title.Render() + "</div>", | ||||
|                 "<div class='infoboxcontents'>" + infoboxcontents.Render() + "</div>"]).Render() + "</div>"; | ||||
|                 "<div class='featureinfoboxtitle'>", | ||||
|                 title,  | ||||
|                 "</div>", | ||||
|                 "<div class='infoboxcontents'>", | ||||
|                 infoboxcontents, | ||||
|                 "</div>"]).Render() + "</div>"; | ||||
|     } | ||||
|      | ||||
|      | ||||
|  |  | |||
|  | @ -1,24 +1,36 @@ | |||
| import {UIElement} from "./UIElement"; | ||||
| import {VariableUiElement} from "./Base/VariableUIElement"; | ||||
| import Translations from "./i18n/Translations"; | ||||
| import {State} from "../State"; | ||||
| import {UIEventSource} from "../Logic/UIEventSource"; | ||||
| import Combine from "./Base/Combine"; | ||||
| 
 | ||||
| /** | ||||
|  * Handles the full screen popup on mobile | ||||
|  */ | ||||
| export class FullScreenMessageBoxHandler { | ||||
| export class FullScreenMessageBox extends UIElement { | ||||
| 
 | ||||
|     private _uielement: UIEventSource<UIElement>; | ||||
|     private _uielement: UIElement; | ||||
|     private returnToTheMap: UIElement; | ||||
| 
 | ||||
|     constructor(onClear: (() => void)) { | ||||
|         this._uielement = State.state.fullScreenMessage; | ||||
|         super(undefined); | ||||
| 
 | ||||
|         const self = this; | ||||
|         this._uielement.addCallback(function () { | ||||
|             self.update(); | ||||
| 
 | ||||
|         State.state.fullScreenMessage.addCallback(uielement => { | ||||
|             return self._uielement = uielement?.SetClass("messagesboxmobile-scroll")?.Activate(); | ||||
|         }); | ||||
|          | ||||
|         this.update(); | ||||
|         this._uielement = State.state.fullScreenMessage.data; | ||||
|         this.ListenTo(State.state.fullScreenMessage); | ||||
|         this.HideOnEmpty(true); | ||||
| 
 | ||||
|         State.state.fullScreenMessage.addCallback(latestData => { | ||||
|             if (latestData === undefined) { | ||||
|                 location.hash = ""; | ||||
|             } else { | ||||
|                 location.hash = "#element"; | ||||
|             } | ||||
|             this.Update(); | ||||
|         }) | ||||
| 
 | ||||
|         if (window !== undefined) { | ||||
|             window.onhashchange = function () { | ||||
|  | @ -30,36 +42,24 @@ export class FullScreenMessageBoxHandler { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Translations.t.general.returnToTheMap | ||||
|         this.returnToTheMap = Translations.t.general.returnToTheMap.Clone() | ||||
|             .SetClass("to-the-map") | ||||
|             .onClick(() => { | ||||
|                 self._uielement.setData(undefined); | ||||
|                 console.log("Returning...") | ||||
|                 State.state.fullScreenMessage.setData(undefined); | ||||
|                 onClear(); | ||||
|             }) | ||||
|             .AttachTo("to-the-map"); | ||||
| 
 | ||||
|                 self.Update(); | ||||
|             }); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     update() { | ||||
|         const wrapper = document.getElementById("messagesboxmobilewrapper"); | ||||
|         const gen = this._uielement.data; | ||||
|         if (gen === undefined) { | ||||
|             wrapper.classList.add("hidden") | ||||
|             if (location.hash !== "") { | ||||
|                 location.hash = "" | ||||
|             } | ||||
|             return; | ||||
|     InnerRender(): string { | ||||
|         if (this._uielement === undefined) { | ||||
|             return ""; | ||||
|         } | ||||
|         location.hash = "#element" | ||||
|         wrapper.classList.remove("hidden"); | ||||
| 
 | ||||
|         gen | ||||
|             ?.HideOnEmpty(true) | ||||
|             ?.AttachTo("messagesboxmobile") | ||||
|             ?.Activate(); | ||||
| 
 | ||||
| 
 | ||||
|         return new Combine([this._uielement, this.returnToTheMap]).SetStyle("").Render(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -72,7 +72,7 @@ export class MoreScreen extends UIElement { | |||
| 
 | ||||
|         els.push(new VariableUiElement( | ||||
|             State.state.osmConnection.userDetails.map(userDetails => { | ||||
|                 if (userDetails.csCount < State.userJourney.themeGeneratorUnlock) { | ||||
|                 if (userDetails.csCount < State.userJourney.themeGeneratorReadOnlyUnlock) { | ||||
|                     return tr.requestATheme.Render(); | ||||
|                 } | ||||
|                 return new SubtleButton("./assets/pencil.svg", tr.createYourOwnTheme, { | ||||
|  | @ -86,7 +86,7 @@ export class MoreScreen extends UIElement { | |||
|         for (const k in AllKnownLayouts.allSets) { | ||||
|             const layout : Layout = AllKnownLayouts.allSets[k]; | ||||
|             if (k === PersonalLayout.NAME) { | ||||
|                 if (State.state.osmConnection.userDetails.data.csCount < State.userJourney.customLayoutUnlock) { | ||||
|                 if (State.state.osmConnection.userDetails.data.csCount < State.userJourney.personalLayoutUnlock) { | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|  | @ -99,7 +99,6 @@ export class MoreScreen extends UIElement { | |||
| 
 | ||||
|         const customThemesNames = State.state.installedThemes.data ?? []; | ||||
|         if (customThemesNames.length > 0) { | ||||
|             console.log(customThemesNames) | ||||
|             els.push(Translations.t.general.customThemeIntro) | ||||
| 
 | ||||
|             for (const installed of State.state.installedThemes.data) { | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ export abstract class UIElement extends UIEventSource<string> { | |||
|         if (UIElement.runningFromConsole) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|          | ||||
|         let element = document.getElementById(this.id); | ||||
|         if (element === undefined || element === null) { | ||||
|             // The element is not painted
 | ||||
|  | @ -99,7 +99,7 @@ export abstract class UIElement extends UIEventSource<string> { | |||
|             if (element.innerHTML === "") { | ||||
|                 element.parentElement.style.display = "none"; | ||||
|             } else { | ||||
|                 element.parentElement.style.display = undefined; | ||||
|                 element.parentElement.style.display = "block"; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -174,7 +174,7 @@ export abstract class UIElement extends UIEventSource<string> { | |||
| 
 | ||||
|     public abstract InnerRender(): string; | ||||
| 
 | ||||
|     public Activate(): void { | ||||
|     public Activate(): UIElement { | ||||
|         for (const i in this) { | ||||
|             const child = this[i]; | ||||
|             if (child instanceof UIElement) { | ||||
|  | @ -187,6 +187,7 @@ export abstract class UIElement extends UIEventSource<string> { | |||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return this; | ||||
|     }; | ||||
| 
 | ||||
|     public IsEmpty(): boolean { | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| import {UIElement} from "./UIElement"; | ||||
| import Locale from "../UI/i18n/Locale"; | ||||
| import {State} from "../State"; | ||||
| import {Layout} from "../Customizations/Layout"; | ||||
| import Translations from "./i18n/Translations"; | ||||
| import Combine from "./Base/Combine"; | ||||
| import {InitUiElements} from "../InitUiElements"; | ||||
|  | @ -20,27 +19,18 @@ export class WelcomeMessage extends UIElement { | |||
|         super(State.state.osmConnection.userDetails); | ||||
|         this.ListenTo(Locale.language); | ||||
|         this.languagePicker = InitUiElements.CreateLanguagePicker(Translations.t.general.pickLanguage); | ||||
|         const layout = State.state.layoutToUse.data; | ||||
| 
 | ||||
|         function fromLayout(f: (layout: Layout) => (string | UIElement)): UIElement { | ||||
|             return Translations.W(f(State.state.layoutToUse.data)); | ||||
|         } | ||||
| 
 | ||||
|         this.description = fromLayout((layout) => layout.welcomeMessage); | ||||
|         this.plzLogIn =  | ||||
|             fromLayout((layout) => layout.gettingStartedPlzLogin | ||||
|                 .onClick(() => {State.state.osmConnection.AttemptLogin()}) | ||||
|             ); | ||||
|         this.welcomeBack = fromLayout((layout) => layout.welcomeBackMessage); | ||||
|         this.tail = fromLayout((layout) => layout.welcomeTail); | ||||
|         this.description =Translations.W(layout.welcomeMessage); | ||||
|         this.plzLogIn = | ||||
|             Translations.W(layout.gettingStartedPlzLogin) | ||||
|                 .onClick(() => { | ||||
|                     State.state.osmConnection.AttemptLogin() | ||||
|                 }); | ||||
|         this.welcomeBack = Translations.W(layout.welcomeBackMessage); | ||||
|         this.tail = Translations.W(layout.welcomeTail); | ||||
|     } | ||||
| 
 | ||||
|     protected InnerUpdate(htmlElement: HTMLElement) { | ||||
|         super.InnerUpdate(htmlElement); | ||||
|         console.log("Innerupdating welcome message") | ||||
|         this.plzLogIn.Update(); | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
| 
 | ||||
|         let loginStatus = undefined; | ||||
|  | @ -52,7 +42,8 @@ export class WelcomeMessage extends UIElement { | |||
|         return new Combine([ | ||||
|             this.description, | ||||
|             "<br/></br>", | ||||
|            // TODO this button is broken - figure out why loginStatus,
 | ||||
|             // TODO this button is broken - figure out why loginStatus,
 | ||||
|             loginStatus, | ||||
|             this.tail, | ||||
|             "<br/>", | ||||
|             this.languagePicker | ||||
|  |  | |||
							
								
								
									
										76
									
								
								assets/arrow-left-smooth.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								assets/arrow-left-smooth.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| 
 | ||||
| <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" | ||||
|    width="100" | ||||
|    height="100" | ||||
|    viewBox="0 0 26.458333 26.458334" | ||||
|    version="1.1" | ||||
|    id="svg8" | ||||
|    sodipodi:docname="arrow-left-smooth.svg" | ||||
|    inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> | ||||
|   <defs | ||||
|      id="defs2" /> | ||||
|   <sodipodi:namedview | ||||
|      id="base" | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1.0" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:zoom="4" | ||||
|      inkscape:cx="19.262262" | ||||
|      inkscape:cy="36.323203" | ||||
|      inkscape:document-units="px" | ||||
|      inkscape:current-layer="layer1" | ||||
|      showgrid="false" | ||||
|      units="px" | ||||
|      showguides="true" | ||||
|      inkscape:guide-bbox="true" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="1001" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|      inkscape:window-maximized="1"> | ||||
|     <sodipodi:guide | ||||
|        position="13.229167,23.859748" | ||||
|        orientation="1,0" | ||||
|        id="guide815" | ||||
|        inkscape:locked="false" /> | ||||
|     <sodipodi:guide | ||||
|        position="14.944824,13.229167" | ||||
|        orientation="0,1" | ||||
|        id="guide817" | ||||
|        inkscape:locked="false" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata5"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      inkscape:label="Layer 1" | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer1" | ||||
|      transform="translate(0,-270.54165)"> | ||||
|     <path | ||||
|        style="fill:none;stroke:#ffffff;stroke-width:3.59588718;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|        d="m 20.139011,294.16029 c 0,0 -13.7995299,-7.53922 -13.8484369,-10.36091 -0.04891,-2.82169 13.8484369,-10.38607 13.8484369,-10.38607" | ||||
|        id="path821" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.3 KiB | 
							
								
								
									
										76
									
								
								assets/arrow-right-smooth.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								assets/arrow-right-smooth.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| 
 | ||||
| <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" | ||||
|    width="100" | ||||
|    height="100" | ||||
|    viewBox="0 0 26.458333 26.458334" | ||||
|    version="1.1" | ||||
|    id="svg8" | ||||
|    sodipodi:docname="arrow-right-smooth.svg" | ||||
|    inkscape:version="0.92.4 (5da689c313, 2019-01-14)"> | ||||
|   <defs | ||||
|      id="defs2" /> | ||||
|   <sodipodi:namedview | ||||
|      id="base" | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1.0" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:zoom="4" | ||||
|      inkscape:cx="-22.237738" | ||||
|      inkscape:cy="36.323203" | ||||
|      inkscape:document-units="px" | ||||
|      inkscape:current-layer="layer1" | ||||
|      showgrid="false" | ||||
|      units="px" | ||||
|      showguides="true" | ||||
|      inkscape:guide-bbox="true" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="1001" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="0" | ||||
|      inkscape:window-maximized="1"> | ||||
|     <sodipodi:guide | ||||
|        position="13.229167,23.859748" | ||||
|        orientation="1,0" | ||||
|        id="guide815" | ||||
|        inkscape:locked="false" /> | ||||
|     <sodipodi:guide | ||||
|        position="14.944824,13.229167" | ||||
|        orientation="0,1" | ||||
|        id="guide817" | ||||
|        inkscape:locked="false" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata5"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title /> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      inkscape:label="Layer 1" | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer1" | ||||
|      transform="translate(0,-270.54165)"> | ||||
|     <path | ||||
|        style="fill:none;stroke:#ffffff;stroke-width:3.59588718;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||||
|        d="m 6.3128214,273.41335 c 0,0 13.7995296,7.53922 13.8484366,10.36091 0.04891,2.82169 -13.8484366,10.38607 -13.8484366,10.38607" | ||||
|        id="path821" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.3 KiB | 
|  | @ -12,7 +12,11 @@ | |||
|       "amenity=bicycle_parking" | ||||
|     ] | ||||
|   }, | ||||
|   "icon": "./assets/layers/bike_parking/parking.svg", | ||||
|   "icon": { | ||||
|     "render": { | ||||
|       "en": "./assets/layers/bike_parking/parking.svg" | ||||
|     } | ||||
|   }, | ||||
|   "size": { | ||||
|     "render": { | ||||
|       "en": "50,50,bottom" | ||||
|  |  | |||
|  | @ -1,70 +1,25 @@ | |||
| import {UIEventSource} from "./Logic/UIEventSource"; | ||||
| import SingleSetting from "./UI/CustomGenerator/SingleSetting"; | ||||
| import Combine from "./UI/Base/Combine"; | ||||
| import {VariableUiElement} from "./UI/Base/VariableUIElement"; | ||||
| import GeneralSettings from "./UI/CustomGenerator/GeneralSettings"; | ||||
| import {TabbedComponent} from "./UI/Base/TabbedComponent"; | ||||
| import AllLayersPanel from "./UI/CustomGenerator/AllLayersPanel"; | ||||
| import SharePanel from "./UI/CustomGenerator/SharePanel"; | ||||
| import {GenerateEmpty} from "./UI/CustomGenerator/GenerateEmpty"; | ||||
| import PageSplit from "./UI/Base/PageSplit"; | ||||
| import HelpText from "./Customizations/HelpText"; | ||||
| import {TagRendering} from "./Customizations/TagRendering"; | ||||
| import {LayoutConfigJson} from "./Customizations/JSON/LayoutConfigJson"; | ||||
| 
 | ||||
| import {OsmConnection} from "./Logic/Osm/OsmConnection"; | ||||
| import CustomGeneratorPanel from "./UI/CustomGenerator/CustomGeneratorPanel"; | ||||
| import {LocalStorageSource} from "./Logic/Web/LocalStorageSource"; | ||||
| 
 | ||||
| let layout = GenerateEmpty.createEmptyLayout(); | ||||
| if(window.location.hash.length > 10){ | ||||
| if (window.location.hash.length > 10) { | ||||
|     layout = JSON.parse(atob(window.location.hash.substr(1))) as LayoutConfigJson; | ||||
| } else { | ||||
|     const hash = LocalStorageSource.Get("last-custom-theme").data | ||||
|     if (hash !== undefined) { | ||||
|         layout = JSON.parse(atob(hash)) as LayoutConfigJson; | ||||
|     } | ||||
| } | ||||
| const es = new UIEventSource(layout); | ||||
| const encoded = es.map(config => btoa(JSON.stringify(config))); | ||||
| const liveUrl = encoded.map(encoded => `./index.html?userlayout=${es.data.id}#${encoded}`) | ||||
| const iframe = liveUrl.map(url => `<iframe src='${url}' width='100%' height='99%' style="box-sizing: border-box" title='Theme Preview'></iframe>`); | ||||
| 
 | ||||
| TagRendering.injectFunction(); | ||||
| 
 | ||||
| const currentSetting = new UIEventSource<SingleSetting<any>>(undefined) | ||||
| const connection = new OsmConnection(false, new UIEventSource<string>(undefined), "customGenerator", false); | ||||
| 
 | ||||
| const generalSettings = new GeneralSettings(es, currentSetting); | ||||
| const languages = generalSettings.languages; | ||||
| 
 | ||||
| 
 | ||||
| // The preview
 | ||||
| const preview = new Combine([ | ||||
|     new VariableUiElement(iframe.stabilized(2500)) | ||||
| ]).SetClass("preview") | ||||
| 
 | ||||
| 
 | ||||
| new TabbedComponent([ | ||||
|     { | ||||
|         header: "<img src='./assets/gear.svg'>", | ||||
|         content: | ||||
|             new PageSplit( | ||||
|                 generalSettings.SetStyle("width: 50vw;"), | ||||
|                 new Combine([ | ||||
|                     new HelpText(currentSetting).SetStyle("height:calc(100% - 65vh); width: 100%; display:block; overflow-y: auto"), | ||||
|                     preview.SetStyle("height:65vh; width:100%; display:block") | ||||
|                 ]).SetStyle("position:relative; width: 50%;") | ||||
|             ) | ||||
|     }, | ||||
|     { | ||||
|         header: "<img src='./assets/layers.svg'>", | ||||
|         content: new AllLayersPanel(es, languages) | ||||
|     }, | ||||
|     { | ||||
|         header: "<img src='./assets/floppy.svg'>", | ||||
|         content: new VariableUiElement(es.map(config => { | ||||
|             return JSON.stringify(config, null, 2) | ||||
|                 .replace(/\n/g, "<br/>") | ||||
|                 .replace(/ /g, " "); | ||||
|         })) | ||||
| 
 | ||||
|     }, | ||||
|     { | ||||
|         header: "<img src='./assets/share.svg'>", | ||||
|         content: new SharePanel(es, liveUrl) | ||||
|     } | ||||
| ]).SetClass("main-tabs") | ||||
| new CustomGeneratorPanel(connection, layout) | ||||
|     .AttachTo("maindiv"); | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										439
									
								
								index.css
									
										
									
									
									
								
							
							
						
						
									
										439
									
								
								index.css
									
										
									
									
									
								
							|  | @ -284,6 +284,9 @@ | |||
|     padding-top: 0.2em; | ||||
|     padding-bottom: 0.2em; | ||||
| } | ||||
|     #hidden-on-mobile { | ||||
|         display: none; /*Only shown on small screens*/ | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| @media only screen and (max-height: 600px) and (not (max-width:700px)) { | ||||
|  | @ -351,9 +354,6 @@ | |||
|     padding-right: 10px; /* Shadow offset */ | ||||
| } | ||||
| 
 | ||||
| #messagesboxmobilewrapper { | ||||
|     display: none; /*Only shown on small screens*/ | ||||
| } | ||||
| 
 | ||||
| .collapse-button { | ||||
|     position: absolute; | ||||
|  | @ -556,6 +556,10 @@ | |||
| 
 | ||||
| 
 | ||||
| @media only screen and (max-width: 600px), only screen and (max-height: 600px) { | ||||
|     #hidden-on-mobile { | ||||
|         display: block; | ||||
|     } | ||||
|    | ||||
|     #messagesbox-wrapper { | ||||
|         display: none; | ||||
|     } | ||||
|  | @ -590,33 +594,20 @@ | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     #messagesboxmobilewrapper { | ||||
|         position: absolute; | ||||
|         padding: 0; | ||||
|         margin: 0; | ||||
|         z-index: 5050; | ||||
|         transition: all 500ms linear; | ||||
|         overflow: hidden; | ||||
|         border-radius: 0; | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         display: block; | ||||
|         background-color: white; | ||||
|     } | ||||
| 
 | ||||
|     #messagesboxmobile-scroll { | ||||
|     .messagesboxmobile-scroll { | ||||
|         display: block; | ||||
|         width: 100vw; | ||||
|         overflow-y: auto; | ||||
|         padding: 0; | ||||
|         box-sizing: border-box; | ||||
|         overflow-y: scroll; | ||||
|         padding: 1em; | ||||
|         margin: 0; | ||||
|         height: calc(100% - 5em); /*Height of to-the-map is 5em*/ | ||||
|         height: calc(100vh - 5em); /*Height of to-the-map is 5em*/ | ||||
|     } | ||||
| 
 | ||||
|     #messagesboxmobile { | ||||
|         padding: 1em; | ||||
|         padding-bottom: 2em; | ||||
|         border-radius: 1em; | ||||
|         display: block; | ||||
|         position: absolute; | ||||
|         z-index: 10000; | ||||
|         background-color: white; | ||||
|     } | ||||
| 
 | ||||
|  | @ -634,77 +625,77 @@ | |||
|         box-shadow: unset; | ||||
|         overflow-y: unset; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #to-the-map { | ||||
|     position: relative; | ||||
| } | ||||
| 
 | ||||
| #to-the-map > span{ | ||||
|      | ||||
|     position: absolute; | ||||
|     box-sizing: border-box; | ||||
|     height: 3em; | ||||
|      | ||||
|     padding: 0.5em; | ||||
|     margin: 0; | ||||
| 
 | ||||
|     padding-top: 0.75em; | ||||
|     text-align: center; | ||||
|     width: 100%; | ||||
|     color: white; | ||||
|     background-color: #7ebc6f; | ||||
|     cursor: pointer; | ||||
|     font-size: xx-large; | ||||
|     font-weight: bold; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @media only screen and (max-height: 400px) { | ||||
|     /* Landscape: small 'to the map' */ | ||||
|     #to-the-map { | ||||
|         position: relative; | ||||
|         height: 100%; | ||||
|         width: 100% | ||||
|     } | ||||
| 
 | ||||
|     #to-the-map span { | ||||
|         width: auto; | ||||
|         border-top-left-radius: 1.5em; | ||||
|         position: absolute; | ||||
|         z-index: 5; | ||||
|         right: 0; | ||||
|         bottom: 0; | ||||
|         height: auto; | ||||
|         margin:0; | ||||
|         padding: 1em; | ||||
|         padding-bottom: 0.75em; | ||||
|         height: 3em; | ||||
|         font-size: x-large; | ||||
|     } | ||||
| 
 | ||||
|     #messagesboxmobile { | ||||
|         padding-bottom: 5em; | ||||
|     } | ||||
| 
 | ||||
|     #messagesboxmobile-scroll { | ||||
|         position: absolute; | ||||
|         z-index: 2; | ||||
|         width: 100vw; | ||||
|         height: 100vh; | ||||
|     .to-the-map { | ||||
|         display: block; | ||||
|         box-sizing: border-box; | ||||
|     } | ||||
|      | ||||
|     #welcomeMessage{ | ||||
|         box-shadow: unset; | ||||
|         max-height: 100vh; | ||||
|         height: 2.5em; | ||||
|         margin: 0; | ||||
|         padding: 0.5em; | ||||
|         padding-top: 0.75em; | ||||
|         text-align: center; | ||||
|         color: white; | ||||
|         background-color: #7ebc6f; | ||||
|         cursor: pointer; | ||||
|         font-size: xx-large; | ||||
|         font-weight: bold; | ||||
|         border-top-left-radius: 0.5em; | ||||
|         border-top-right-radius: 0.5em; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|     @media only screen and (max-height: 400px) { | ||||
|         /* Landscape: small 'to the map' */ | ||||
|         #hidden-on-mobile { | ||||
|             display: unset; | ||||
|         } | ||||
| 
 | ||||
|         .to-the-map { | ||||
|             position: relative; | ||||
|             height: 100%; | ||||
|             width: 100% | ||||
|         } | ||||
| 
 | ||||
|         .to-the-map span { | ||||
|             width: auto; | ||||
|             border-top-left-radius: 1.5em; | ||||
|             position: absolute; | ||||
|             z-index: 5; | ||||
|             right: 0; | ||||
|             bottom: 0; | ||||
|             height: auto; | ||||
|             margin: 0; | ||||
|             padding: 1em; | ||||
|             padding-bottom: 0.75em; | ||||
|             height: 3em; | ||||
|             font-size: x-large; | ||||
|         } | ||||
| 
 | ||||
|         #messagesboxmobile { | ||||
|             position: absolute; | ||||
|             display: block; | ||||
|             z-index: 10000; | ||||
|             padding-bottom: 5em; | ||||
|         } | ||||
| 
 | ||||
|         .messagesboxmobile-scroll { | ||||
|             display: block; | ||||
|             width: 100vw; | ||||
|             height: calc(100vh - 5em); | ||||
|             box-sizing: border-box; | ||||
|             overflow-y: scroll; | ||||
|         } | ||||
| 
 | ||||
|         #welcomeMessage { | ||||
|             box-shadow: unset; | ||||
|             max-height: 100vh; | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| .logo { | ||||
|     float:right; | ||||
|  | @ -841,170 +832,173 @@ | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| .attribution-author { | ||||
|     display: inline-block; | ||||
| } | ||||
|     .attribution-author { | ||||
|         display: inline-block; | ||||
|     } | ||||
| 
 | ||||
| .license { | ||||
|     font-size: small; | ||||
|     font-weight: lighter; | ||||
| } | ||||
|     .license { | ||||
|         font-size: small; | ||||
|         font-weight: lighter; | ||||
|     } | ||||
| 
 | ||||
| .attribution a { | ||||
|     color: white; | ||||
| } | ||||
|     .attribution a { | ||||
|         color: white; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| /**************** Image upload flow ***************/ | ||||
|     /**************** Image upload flow ***************/ | ||||
| 
 | ||||
| .imageflow { | ||||
|     margin-top: 1em; | ||||
|     margin-bottom: 2em; | ||||
|     text-align: center; | ||||
|     .imageflow { | ||||
|         margin-top: 1em; | ||||
|         margin-bottom: 2em; | ||||
|         text-align: center; | ||||
| 
 | ||||
| } | ||||
|     } | ||||
| 
 | ||||
| .imageflow-file-input-wrapper { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|     padding: 0.5em; | ||||
|     border-radius: 1em; | ||||
|     border: 3px solid black; | ||||
| } | ||||
|     .imageflow-file-input-wrapper { | ||||
|         display: flex; | ||||
|         flex-wrap: wrap; | ||||
|         padding: 0.5em; | ||||
|         border-radius: 1em; | ||||
|         border: 3px solid black; | ||||
|     } | ||||
| 
 | ||||
| .imageflow-add-picture { | ||||
|     font-size: 28px; | ||||
|     font-weight: bold; | ||||
|     float: left; | ||||
|     margin-top: 4px; | ||||
|     padding-top: 4px; | ||||
|     padding-bottom: 4px; | ||||
|     padding-left: 13px; | ||||
| } | ||||
|     .imageflow-add-picture { | ||||
|         font-size: 28px; | ||||
|         font-weight: bold; | ||||
|         float: left; | ||||
|         margin-top: 4px; | ||||
|         padding-top: 4px; | ||||
|         padding-bottom: 4px; | ||||
|         padding-left: 13px; | ||||
|     } | ||||
| 
 | ||||
| .imageflow-file-input-wrapper img { | ||||
|     width: 36px; | ||||
|     height: 36px; | ||||
|     padding: 0.1em; | ||||
|     margin-top: 5px; | ||||
|     border-radius: 0; | ||||
|     float: left; | ||||
| } | ||||
|     .imageflow-file-input-wrapper img { | ||||
|         width: 36px; | ||||
|         height: 36px; | ||||
|         padding: 0.1em; | ||||
|         margin-top: 5px; | ||||
|         border-radius: 0; | ||||
|         float: left; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| .license-picker { | ||||
|     float: left; | ||||
| } | ||||
|     .license-picker { | ||||
|         float: left; | ||||
|     } | ||||
| 
 | ||||
| .imageflow > input { | ||||
|     display: none; | ||||
| } | ||||
|     .imageflow > input { | ||||
|         display: none; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| /***************** Info box (box containing features and questions ******************/ | ||||
|     /***************** Info box (box containing features and questions ******************/ | ||||
| 
 | ||||
| .leaflet-popup-content { | ||||
|     width: 40em !important; | ||||
| } | ||||
| 
 | ||||
| #messagesboxmobile .featureinfobox { | ||||
|     max-height: unset; | ||||
|     overflow-y: unset; | ||||
| } | ||||
| 
 | ||||
| #messagesboxmobile .featureinfobox > div { | ||||
|     width: 100%; | ||||
|     max-width: unset; | ||||
|     padding-left: unset; | ||||
| } | ||||
| 
 | ||||
| .featureinfobox { | ||||
|     max-height: 80vh; | ||||
|     overflow-y: auto; | ||||
| } | ||||
| 
 | ||||
| .featureinfobox > div { | ||||
|     width: calc(100% - 2em); | ||||
|     padding-left: 1em; | ||||
| } | ||||
|     .leaflet-popup-content { | ||||
|         width: 40em !important; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| .featureinfoboxtitle { | ||||
|     position: relative; | ||||
| } | ||||
|    | ||||
| 
 | ||||
| .question .form-text-field > input{ | ||||
|     width: 100%; | ||||
|     box-sizing: border-box; | ||||
| }  | ||||
|     #messagesboxmobile .featureinfobox { | ||||
|         max-height: unset; | ||||
|         overflow-y: unset; | ||||
|     } | ||||
| 
 | ||||
| .osmlink { | ||||
|     position: absolute; | ||||
|     right: 0; | ||||
| } | ||||
|     #messagesboxmobile .featureinfobox > div { | ||||
|         width: 100%; | ||||
|         max-width: unset; | ||||
|         padding-left: unset; | ||||
|     } | ||||
| 
 | ||||
| .osm-logo path { | ||||
|     fill: #7ebc6f; | ||||
| } | ||||
|     .featureinfobox { | ||||
|         max-height: 80vh; | ||||
|         overflow-y: auto; | ||||
|     } | ||||
| 
 | ||||
| .featureinfoboxtitle .answer { | ||||
|     display: inline; | ||||
|     margin-right: 3em; | ||||
| } | ||||
| 
 | ||||
| .featureinfoboxtitle .answer-text { | ||||
|     display: inline; | ||||
| } | ||||
| 
 | ||||
| .featureinfoboxtitle .editbutton { | ||||
|     float: none; | ||||
|     width: 0.8em; | ||||
|     height: 0.8em; | ||||
|     padding: 0.3em; | ||||
|     border-radius: 0.35em; | ||||
|     border: solid black 1px; | ||||
|     margin-left: 0.5em; | ||||
|     top: 0.2em; | ||||
|     vertical-align: middle; | ||||
| 
 | ||||
| } | ||||
|     .featureinfobox > div { | ||||
|         width: calc(100% - 2em); | ||||
|         padding-left: 1em; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| .editbutton { | ||||
|     width: 1.3em; | ||||
|     height: 1.3em; | ||||
|     padding: 0.5em; | ||||
|     border-radius: 0.65em; | ||||
|     border: solid black 1px; | ||||
|     .featureinfoboxtitle { | ||||
|         position: relative; | ||||
|     } | ||||
| 
 | ||||
|     font-size: medium; | ||||
|     float: right; | ||||
|     .question .form-text-field > input { | ||||
|         width: 100%; | ||||
|         box-sizing: border-box; | ||||
|     } | ||||
| 
 | ||||
|     .osmlink { | ||||
|         position: absolute; | ||||
|         right: 0; | ||||
|     } | ||||
| 
 | ||||
|     .osm-logo path { | ||||
|         fill: #7ebc6f; | ||||
|     } | ||||
| 
 | ||||
|     .featureinfoboxtitle .answer { | ||||
|         display: inline; | ||||
|         margin-right: 3em; | ||||
|     } | ||||
| 
 | ||||
|     .featureinfoboxtitle .answer-text { | ||||
|         display: inline; | ||||
|     } | ||||
| 
 | ||||
|     .featureinfoboxtitle .editbutton { | ||||
|         float: none; | ||||
|         width: 0.8em; | ||||
|         height: 0.8em; | ||||
|         padding: 0.3em; | ||||
|         border-radius: 0.35em; | ||||
|         border: solid black 1px; | ||||
|         margin-left: 0.5em; | ||||
|         top: 0.2em; | ||||
|         vertical-align: middle; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|     .editbutton { | ||||
|         width: 1.3em; | ||||
|         height: 1.3em; | ||||
|         padding: 0.5em; | ||||
|         border-radius: 0.65em; | ||||
|         border: solid black 1px; | ||||
| 
 | ||||
| .wikipedialink { | ||||
|     position: absolute; | ||||
|     right: 24px; | ||||
|     width: 24px; | ||||
|     height: 24px; | ||||
|     padding-right: 12px; | ||||
| } | ||||
| 
 | ||||
| .wikipedialink img { | ||||
|     width: 24px; | ||||
|     height: 24px; | ||||
| } | ||||
|         font-size: medium; | ||||
|         float: right; | ||||
| 
 | ||||
| 
 | ||||
| .featureinfoboxtitle span { | ||||
|     font-weight: bold; | ||||
|     font-size: x-large; | ||||
| } | ||||
|     } | ||||
| 
 | ||||
| .featureinfoboxtitle a { | ||||
|     float: right; | ||||
|     margin-left: 1em; | ||||
|     .wikipedialink { | ||||
|         position: absolute; | ||||
|         right: 24px; | ||||
|         width: 24px; | ||||
|         height: 24px; | ||||
|         padding-right: 12px; | ||||
|     } | ||||
| 
 | ||||
|     .wikipedialink img { | ||||
|         width: 24px; | ||||
|         height: 24px; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     .featureinfoboxtitle span { | ||||
|         font-weight: bold; | ||||
|         font-size: x-large; | ||||
|     } | ||||
| 
 | ||||
|     .featureinfoboxtitle a { | ||||
|         float: right; | ||||
|         margin-left: 1em; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1273,6 +1267,7 @@ | |||
|     padding: 0.5em; | ||||
|     word-break: break-all; | ||||
|     color: black; | ||||
|     box-sizing: border-box; | ||||
| } | ||||
| 
 | ||||
| .iframe-code-block { | ||||
|  |  | |||
							
								
								
									
										27
									
								
								index.html
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								index.html
									
										
									
									
									
								
							|  | @ -14,7 +14,7 @@ | |||
|     <!-- $$$OG-META --> | ||||
| 
 | ||||
|     <style> | ||||
|         .decoration-desktop img { | ||||
|         #decoration-desktop img { | ||||
|             width: 100%; | ||||
|             height: 100%; | ||||
|         } | ||||
|  | @ -23,33 +23,16 @@ | |||
| </head> | ||||
| <body> | ||||
| 
 | ||||
| <div style="position: absolute; left: 1em; top: 1em; width:35vh; height:35vh;" class="decoration-desktop"> | ||||
| <div style="position: absolute; left: 1em; bottom: 1em; width:35vh; height:35vh;" | ||||
|      id="decoration-desktop"> | ||||
|     <!-- A nice decoration while loading or on errors --> | ||||
|     <!-- DECORATION 0 START --> | ||||
|     <img src="./assets/add.svg"/> | ||||
|     <!-- DECORATION 0 END --> | ||||
| </div> | ||||
| 
 | ||||
| <div id="messagesboxmobilewrapper"> | ||||
|     <div id="decoration" style="position: absolute; left: 1em; top: 1em; z-index: 1; width: 15em; height: 15em"> | ||||
|         <!-- A nice decoration while loading or on errors --> | ||||
|         <!-- DECORATION 1 START --> | ||||
|         <img src="./assets/add.svg"/> | ||||
|         <!-- DECORATION 1 END --> | ||||
|     </div> | ||||
|     <div id="messagesboxmobile-scroll"> | ||||
|         <div id="messagesboxmobile"> | ||||
|             <div style="position: absolute; top: 50vh; left: 25vw; width:50vw; box-sizing: border-box;font-size: x-large"> | ||||
|                 Loading MapComplete | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div id="to-the-map"> | ||||
|         If this message persists: | ||||
|         <ul style="margin:0"> | ||||
|             <li>Is javascript enabled?</li> | ||||
|             <li>Is a scriptblocker (such as UMatrix or Brave) active?</li> | ||||
|         </ul> | ||||
| <div id="hidden-on-mobile"> | ||||
|     <div id="messagesboxmobile"> | ||||
|     </div> | ||||
| </div> | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										23
									
								
								index.ts
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								index.ts
									
										
									
									
									
								
							|  | @ -2,7 +2,6 @@ import {TagRendering} from "./Customizations/TagRendering"; | |||
| import {UserBadge} from "./UI/UserBadge"; | ||||
| import {CenterMessageBox} from "./UI/CenterMessageBox"; | ||||
| import {TagUtils} from "./Logic/Tags"; | ||||
| import {FullScreenMessageBoxHandler} from "./UI/FullScreenMessageBoxHandler"; | ||||
| import {FeatureInfoBox} from "./UI/FeatureInfoBox"; | ||||
| import {SimpleAddUI} from "./UI/SimpleAddUI"; | ||||
| import {SearchAndGo} from "./UI/SearchAndGo"; | ||||
|  | @ -17,6 +16,7 @@ import {QueryParameters} from "./Logic/Web/QueryParameters"; | |||
| import {LocalStorageSource} from "./Logic/Web/LocalStorageSource"; | ||||
| import {PersonalLayout} from "./Logic/PersonalLayout"; | ||||
| import {FromJSON} from "./Customizations/JSON/FromJSON"; | ||||
| import {FullScreenMessageBox} from "./UI/FullScreenMessageBoxHandler"; | ||||
| 
 | ||||
| TagRendering.injectFunction(); | ||||
| 
 | ||||
|  | @ -28,9 +28,9 @@ if (location.href.startsWith("http://buurtnatuur.be")) { | |||
|     window.location.replace("https://buurtnatuur.be"); | ||||
| } | ||||
| 
 | ||||
|     const testing = QueryParameters.GetQueryParameter("test", "true"); | ||||
| if (location.hostname === "localhost" || location.hostname === "127.0.0.1") { | ||||
|     // Set to true if testing and changes should NOT be saved
 | ||||
|     const testing = QueryParameters.GetQueryParameter("test", "true"); | ||||
|     testing.setData(testing.data ?? "true") | ||||
|     // If you have a testfile somewhere, enable this to spoof overpass
 | ||||
|     // This should be hosted independantly, e.g. with `cd assets; webfsd -p 8080` + a CORS plugin to disable cors rules
 | ||||
|  | @ -113,13 +113,17 @@ if (layoutToUse.hideFromOverview) { | |||
| 
 | ||||
| if (layoutFromBase64 !== "false") { | ||||
|     State.state.layoutDefinition = hash.substr(1); | ||||
|     State.state.osmConnection.OnLoggedIn(() => { | ||||
|         State.state.osmConnection.GetLongPreference("installed-theme-" + layoutToUse.id).setData(State.state.layoutDefinition); | ||||
|     }) | ||||
|     if (!testing) { | ||||
|         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"); // Remove the decoration
 | ||||
| new FixedUiElement("").AttachTo("decoration-desktop"); // Remove the decoration
 | ||||
| 
 | ||||
| function setupAllLayerElements() { | ||||
| 
 | ||||
|  | @ -232,9 +236,12 @@ InitUiElements.OnlyIf((State.state.featureSwitchSearch), () => { | |||
|     new SearchAndGo().AttachTo("searchbox"); | ||||
| }); | ||||
| 
 | ||||
| new FullScreenMessageBoxHandler(() => { | ||||
| 
 | ||||
| new FullScreenMessageBox(() => { | ||||
|     State.state.selectedElement.setData(undefined) | ||||
| }).update(); | ||||
| }).AttachTo("messagesboxmobile"); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| InitUiElements.OnlyIf(State.state.featureSwitchWelcomeMessage, () => { | ||||
|     InitUiElements.InitWelcomeMessage() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue