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 iconSize = FromJSON.TagRenderingWithDefault(json.iconSize, "iconSize", "40,40,center");
 | 
				
			||||||
        const color = FromJSON.TagRenderingWithDefault(json.color, "layercolor", "#0000ff");
 | 
					        const color = FromJSON.TagRenderingWithDefault(json.color, "layercolor", "#0000ff");
 | 
				
			||||||
        const width = FromJSON.TagRenderingWithDefault(json.width, "layerwidth", "10");
 | 
					        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 renderTags = {"id": "node/-1"}
 | 
				
			||||||
        const presets: Preset[] = json?.presets?.map(preset => {
 | 
					        const presets: Preset[] = json?.presets?.map(preset => {
 | 
				
			||||||
            return ({
 | 
					            return ({
 | 
				
			||||||
| 
						 | 
					@ -294,7 +300,7 @@ export class FromJSON {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // the anchor is always set from the center of the point
 | 
					            // 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
 | 
					            // 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 {
 | 
					            return {
 | 
				
			||||||
                color: color.GetContent(tags).txt,
 | 
					                color: color.GetContent(tags).txt,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,7 +105,16 @@ export class UIEventSource<T>{
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        return newSource;
 | 
					        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
 | 
					    // The singleton of the global state
 | 
				
			||||||
    public static state: 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
 | 
					    // The user journey states thresholds when a new feature gets unlocked
 | 
				
			||||||
    public static userJourney = {
 | 
					    public static userJourney = {
 | 
				
			||||||
        customLayoutUnlock: 50,
 | 
					        personalLayoutUnlock: 20,
 | 
				
			||||||
        themeGeneratorUnlock: 500,
 | 
					        tagsVisibleAt: 100,
 | 
				
			||||||
        tagsVisibleAt: 200,
 | 
					        tagsVisibleAndWikiLinked: 150,
 | 
				
			||||||
        tagsVisibleAndWikiLinked: 250
 | 
					        themeGeneratorReadOnlyUnlock: 200,
 | 
				
			||||||
 | 
					        themeGeneratorFullUnlock: 500,
 | 
				
			||||||
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static runningFromConsole: boolean = false; 
 | 
					    public static runningFromConsole: boolean = false; 
 | 
				
			||||||
| 
						 | 
					@ -68,13 +67,6 @@ export class State {
 | 
				
			||||||
     *  The message that should be shown at the center of the screen
 | 
					     *  The message that should be shown at the center of the screen
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public readonly centerMessage = new UIEventSource<string>("");
 | 
					    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
 | 
					     This message is shown full screen on mobile devices
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
| 
						 | 
					@ -116,10 +108,6 @@ export class State {
 | 
				
			||||||
        latlng: number,
 | 
					        latlng: number,
 | 
				
			||||||
        accuracy: number
 | 
					        accuracy: number
 | 
				
			||||||
    }> = new UIEventSource<{ latlng: number, accuracy: number }>(undefined);
 | 
					    }> = 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 layoutDefinition: string;
 | 
				
			||||||
    public installedThemes: UIEventSource<{ layout: Layout; definition: string }[]>;
 | 
					    public installedThemes: UIEventSource<{ layout: Layout; definition: string }[]>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -259,16 +247,5 @@ export class State {
 | 
				
			||||||
            return;
 | 
					            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 Combine from "../Base/Combine";
 | 
				
			||||||
import {GenerateEmpty} from "./GenerateEmpty";
 | 
					import {GenerateEmpty} from "./GenerateEmpty";
 | 
				
			||||||
import LayerPanelWithPreview from "./LayerPanelWithPreview";
 | 
					import LayerPanelWithPreview from "./LayerPanelWithPreview";
 | 
				
			||||||
 | 
					import {UserDetails} from "../../Logic/Osm/OsmConnection";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class AllLayersPanel extends UIElement {
 | 
					export default class AllLayersPanel extends UIElement {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,28 +16,29 @@ export default class AllLayersPanel extends UIElement {
 | 
				
			||||||
    private readonly languages: UIEventSource<string[]>;
 | 
					    private readonly languages: UIEventSource<string[]>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(config: UIEventSource<LayoutConfigJson>,
 | 
					    constructor(config: UIEventSource<LayoutConfigJson>,
 | 
				
			||||||
                languages: UIEventSource<any>) {
 | 
					                languages: UIEventSource<any>, userDetails: UserDetails) {
 | 
				
			||||||
        super(undefined);
 | 
					        super(undefined);
 | 
				
			||||||
        this._config = config;
 | 
					        this._config = config;
 | 
				
			||||||
        this.languages = languages;
 | 
					        this.languages = languages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.createPanels();
 | 
					        this.createPanels(userDetails);
 | 
				
			||||||
        const self = this;
 | 
					        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 self = this;
 | 
				
			||||||
        const tabs = [];
 | 
					        const tabs = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const layers = this._config.data.layers;
 | 
					        const layers = this._config.data.layers;
 | 
				
			||||||
        for (let i = 0; i < layers.length; i++) {
 | 
					        for (let i = 0; i < layers.length; i++) {
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
            tabs.push({
 | 
					            tabs.push({
 | 
				
			||||||
                header: "<img src='./assets/bug.svg'>",
 | 
					                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({
 | 
					        tabs.push({
 | 
				
			||||||
            header: "<img src='./assets/layersAdd.svg'>",
 | 
					            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 {MultiInput} from "../Input/MultiInput";
 | 
				
			||||||
import {LayerConfigJson} from "../../Customizations/JSON/LayerConfigJson";
 | 
					import {LayerConfigJson} from "../../Customizations/JSON/LayerConfigJson";
 | 
				
			||||||
import PresetInputPanel from "./PresetInputPanel";
 | 
					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
 | 
					 * Shows the configuration for a single layer
 | 
				
			||||||
| 
						 | 
					@ -38,10 +41,11 @@ export default class LayerPanel extends UIElement {
 | 
				
			||||||
    constructor(config: UIEventSource<LayoutConfigJson>,
 | 
					    constructor(config: UIEventSource<LayoutConfigJson>,
 | 
				
			||||||
                languages: UIEventSource<string[]>,
 | 
					                languages: UIEventSource<string[]>,
 | 
				
			||||||
                index: number,
 | 
					                index: number,
 | 
				
			||||||
                currentlySelected: UIEventSource<SingleSetting<any>>) {
 | 
					                currentlySelected: UIEventSource<SingleSetting<any>>,
 | 
				
			||||||
 | 
					                userDetails: UserDetails) {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this._config = config;
 | 
					        this._config = config;
 | 
				
			||||||
        this.mapRendering = this.setupRenderOptions(config, languages, index, currentlySelected);
 | 
					        this.mapRendering = this.setupRenderOptions(config, languages, index, currentlySelected, userDetails);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const actualDeleteButton = new SubtleButton(
 | 
					        const actualDeleteButton = new SubtleButton(
 | 
				
			||||||
            "./assets/delete.svg",
 | 
					            "./assets/delete.svg",
 | 
				
			||||||
| 
						 | 
					@ -100,7 +104,7 @@ export default class LayerPanel extends UIElement {
 | 
				
			||||||
            currentlySelected);
 | 
					            currentlySelected);
 | 
				
			||||||
        const self = this;
 | 
					        const self = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const popupTitleRendering = new TagRenderingPanel(languages, currentlySelected, {
 | 
					        const popupTitleRendering = new TagRenderingPanel(languages, currentlySelected, userDetails, {
 | 
				
			||||||
            title: "Popup title",
 | 
					            title: "Popup title",
 | 
				
			||||||
            description: "This is the rendering shown as title in the popup for this element",
 | 
					            description: "This is the rendering shown as title in the popup for this element",
 | 
				
			||||||
            disableQuestions: true
 | 
					            disableQuestions: true
 | 
				
			||||||
| 
						 | 
					@ -113,7 +117,7 @@ export default class LayerPanel extends UIElement {
 | 
				
			||||||
        const tagRenderings = new MultiInput<TagRenderingConfigJson>("Add a tag rendering/question",
 | 
					        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);
 | 
					                self.registerTagRendering(tagPanel);
 | 
				
			||||||
                return tagPanel;
 | 
					                return tagPanel;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
| 
						 | 
					@ -124,11 +128,16 @@ export default class LayerPanel extends UIElement {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const presetPanel = new MultiInput("Add a preset",
 | 
					        if (userDetails.csCount >= State.userJourney.themeGeneratorFullUnlock) {
 | 
				
			||||||
            () => ({tags: [], title: {}}),
 | 
					
 | 
				
			||||||
            () => new PresetInputPanel(currentlySelected, languages));
 | 
					            const presetPanel = new MultiInput("Add a preset",
 | 
				
			||||||
        this.presetsPanel = presetPanel;
 | 
					                () => ({tags: [], title: {}}),
 | 
				
			||||||
        new SingleSetting(config, presetPanel, ["layers", index, "presets"], "Presets", "")
 | 
					                () => 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() {
 | 
					        function loadTagRenderings() {
 | 
				
			||||||
            const values = (config.data.layers[index] as LayerConfigJson).tagRenderings;
 | 
					            const values = (config.data.layers[index] as LayerConfigJson).tagRenderings;
 | 
				
			||||||
| 
						 | 
					@ -152,27 +161,29 @@ export default class LayerPanel extends UIElement {
 | 
				
			||||||
    private setupRenderOptions(config: UIEventSource<LayoutConfigJson>,
 | 
					    private setupRenderOptions(config: UIEventSource<LayoutConfigJson>,
 | 
				
			||||||
                               languages: UIEventSource<string[]>,
 | 
					                               languages: UIEventSource<string[]>,
 | 
				
			||||||
                               index: number,
 | 
					                               index: number,
 | 
				
			||||||
                               currentlySelected: UIEventSource<SingleSetting<any>>): UIElement {
 | 
					                               currentlySelected: UIEventSource<SingleSetting<any>>,
 | 
				
			||||||
 | 
					                               userDetails: UserDetails
 | 
				
			||||||
 | 
					    ): UIElement {
 | 
				
			||||||
        const iconSelect = new TagRenderingPanel(
 | 
					        const iconSelect = new TagRenderingPanel(
 | 
				
			||||||
            languages, currentlySelected,
 | 
					            languages, currentlySelected, userDetails,
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                title: "Icon",
 | 
					                title: "Icon",
 | 
				
			||||||
                description: "A visual representation for this layer and for the points on the map.",
 | 
					                description: "A visual representation for this layer and for the points on the map.",
 | 
				
			||||||
                disableQuestions: true
 | 
					                disableQuestions: true
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        const size = new TagRenderingPanel(languages, currentlySelected,
 | 
					        const size = new TagRenderingPanel(languages, currentlySelected, userDetails,
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                title: "Icon Size",
 | 
					                title: "Icon Size",
 | 
				
			||||||
                description: "The size of the icons on the map in pixels. Can vary based on the tagging",
 | 
					                description: "The size of the icons on the map in pixels. Can vary based on the tagging",
 | 
				
			||||||
                disableQuestions: true
 | 
					                disableQuestions: true
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        const color = new TagRenderingPanel(languages, currentlySelected,
 | 
					        const color = new TagRenderingPanel(languages, currentlySelected, userDetails,
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                title: "Way and area color",
 | 
					                title: "Way and area color",
 | 
				
			||||||
                description: "The color or a shown way or area. Can vary based on the tagging",
 | 
					                description: "The color or a shown way or area. Can vary based on the tagging",
 | 
				
			||||||
                disableQuestions: true
 | 
					                disableQuestions: true
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        const stroke = new TagRenderingPanel(languages, currentlySelected,
 | 
					        const stroke = new TagRenderingPanel(languages, currentlySelected, userDetails,
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                title: "Stroke width",
 | 
					                title: "Stroke width",
 | 
				
			||||||
                description: "The width of lines representing ways and the outline of areas. Can vary based on the tags",
 | 
					                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 Combine from "../Base/Combine";
 | 
				
			||||||
import PageSplit from "../Base/PageSplit";
 | 
					import PageSplit from "../Base/PageSplit";
 | 
				
			||||||
import TagRenderingPreview from "./TagRenderingPreview";
 | 
					import TagRenderingPreview from "./TagRenderingPreview";
 | 
				
			||||||
 | 
					import {UserDetails} from "../../Logic/Osm/OsmConnection";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class LayerPanelWithPreview extends UIElement{
 | 
					export default class LayerPanelWithPreview extends UIElement{
 | 
				
			||||||
    private panel: 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();
 | 
					        super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const currentlySelected = new UIEventSource<(SingleSetting<any>)>(undefined);
 | 
					        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 helpText = new HelpText(currentlySelected);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const previewTagInput = new MultiTagInput();
 | 
					        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 MappingInput from "./MappingInput";
 | 
				
			||||||
import {AndOrTagConfigJson} from "../../Customizations/JSON/TagConfigJson";
 | 
					import {AndOrTagConfigJson} from "../../Customizations/JSON/TagConfigJson";
 | 
				
			||||||
import {TagRenderingConfigJson} from "../../Customizations/JSON/TagRenderingConfigJson";
 | 
					import {TagRenderingConfigJson} from "../../Customizations/JSON/TagRenderingConfigJson";
 | 
				
			||||||
 | 
					import {UserDetails} from "../../Logic/Osm/OsmConnection";
 | 
				
			||||||
 | 
					import {State} from "../../State";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class TagRenderingPanel extends InputElement<TagRenderingConfigJson> {
 | 
					export default class TagRenderingPanel extends InputElement<TagRenderingConfigJson> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +26,7 @@ export default class TagRenderingPanel extends InputElement<TagRenderingConfigJs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(languages: UIEventSource<string[]>,
 | 
					    constructor(languages: UIEventSource<string[]>,
 | 
				
			||||||
                currentlySelected: UIEventSource<SingleSetting<any>>,
 | 
					                currentlySelected: UIEventSource<SingleSetting<any>>,
 | 
				
			||||||
 | 
					                userDetails: UserDetails,
 | 
				
			||||||
                options?: {
 | 
					                options?: {
 | 
				
			||||||
                    title?: string,
 | 
					                    title?: string,
 | 
				
			||||||
                    description?: string,
 | 
					                    description?: string,
 | 
				
			||||||
| 
						 | 
					@ -36,6 +39,10 @@ export default class TagRenderingPanel extends InputElement<TagRenderingConfigJs
 | 
				
			||||||
        this.SetClass("min-height");
 | 
					        this.SetClass("min-height");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.options = options ?? {};
 | 
					        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.intro = new Combine(["<h3>", options?.title ?? "TagRendering", "</h3>", options?.description ?? ""])
 | 
				
			||||||
        this.IsImage = options?.isImage ?? false;
 | 
					        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);
 | 
					            return new SingleSetting<any>(value, input, id, name, description);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        const questionSettings = [
 | 
					        const questionSettings = [
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            setting(new MultiLingualTextFields(languages), "question", "Question", "If the key or mapping doesn't match, this question is asked"),
 | 
					            setting(new MultiLingualTextFields(languages), "question", "Question", "If the key or mapping doesn't match, this question is asked"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            setting(new AndOrTagInput(), "condition", "Condition",
 | 
					            setting(new AndOrTagInput(), "condition", "Condition",
 | 
				
			||||||
| 
						 | 
					@ -70,6 +77,8 @@ export default class TagRenderingPanel extends InputElement<TagRenderingConfigJs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const settings: (string | SingleSetting<any>)[] = [
 | 
					        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."),
 | 
					            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),
 | 
					            ...(options?.disableQuestions ? [] : questionSettings),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            "<h3>Mappings</h3>",
 | 
					            "<h3>Mappings</h3>",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,10 +26,10 @@ export class FeatureInfoBox extends UIElement {
 | 
				
			||||||
    private readonly _title: UIElement;
 | 
					    private readonly _title: UIElement;
 | 
				
			||||||
    private readonly _osmLink: UIElement;
 | 
					    private readonly _osmLink: UIElement;
 | 
				
			||||||
    private readonly _wikipedialink: UIElement;
 | 
					    private readonly _wikipedialink: UIElement;
 | 
				
			||||||
    private _infoboxes: TagDependantUIElement[];
 | 
					    private readonly _infoboxes: TagDependantUIElement[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private _oneSkipped = Translations.t.general.oneSkippedQuestion.Clone();
 | 
					    private readonly _oneSkipped = Translations.t.general.oneSkippedQuestion.Clone();
 | 
				
			||||||
    private _someSkipped = Translations.t.general.skippedQuestions.Clone();
 | 
					    private readonly _someSkipped = Translations.t.general.skippedQuestions.Clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        feature: any,
 | 
					        feature: any,
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ export class FeatureInfoBox extends UIElement {
 | 
				
			||||||
                tagRenderingOption.construct(deps));
 | 
					                tagRenderingOption.construct(deps));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        function initTags() {
 | 
					        function initTags() {
 | 
				
			||||||
            self._infoboxes = []
 | 
					            self._infoboxes.splice(0, self._infoboxes.length);
 | 
				
			||||||
            for (const tagRenderingOption of elementsToShow) {
 | 
					            for (const tagRenderingOption of elementsToShow) {
 | 
				
			||||||
                self._infoboxes.push(
 | 
					                self._infoboxes.push(
 | 
				
			||||||
                    tagRenderingOption.construct(deps));
 | 
					                    tagRenderingOption.construct(deps));
 | 
				
			||||||
| 
						 | 
					@ -101,10 +101,10 @@ export class FeatureInfoBox extends UIElement {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let questionsHtml = "";
 | 
					        let questionElement: UIElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!State.state.osmConnection.userDetails.data.loggedIn) {
 | 
					        if (!State.state.osmConnection.userDetails.data.loggedIn) {
 | 
				
			||||||
            let mostImportantQuestion;
 | 
					            let mostImportantQuestion ;
 | 
				
			||||||
            let score = -1000;
 | 
					            let score = -1000;
 | 
				
			||||||
            for (const question of questions) {
 | 
					            for (const question of questions) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,7 +114,7 @@ export class FeatureInfoBox extends UIElement {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            questionsHtml = mostImportantQuestion?.Render() ?? "";
 | 
					            questionElement = mostImportantQuestion;
 | 
				
			||||||
        } else if (questions.length > 0) {
 | 
					        } else if (questions.length > 0) {
 | 
				
			||||||
            // We select the most important question and render that one
 | 
					            // We select the most important question and render that one
 | 
				
			||||||
            let mostImportantQuestion;
 | 
					            let mostImportantQuestion;
 | 
				
			||||||
| 
						 | 
					@ -127,11 +127,11 @@ export class FeatureInfoBox extends UIElement {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            questionsHtml = mostImportantQuestion?.Render() ?? "";
 | 
					            questionElement = mostImportantQuestion;
 | 
				
			||||||
        } else if (skippedQuestions == 1) {
 | 
					        } else if (skippedQuestions == 1) {
 | 
				
			||||||
            questionsHtml = this._oneSkipped.Render();
 | 
					            questionElement = this._oneSkipped;
 | 
				
			||||||
        } else if (skippedQuestions > 0) {
 | 
					        } else if (skippedQuestions > 0) {
 | 
				
			||||||
            questionsHtml = this._someSkipped.Render();
 | 
					            questionElement = this._someSkipped;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const title = new Combine([
 | 
					        const title = new Combine([
 | 
				
			||||||
| 
						 | 
					@ -140,12 +140,16 @@ export class FeatureInfoBox extends UIElement {
 | 
				
			||||||
            this._osmLink]);
 | 
					            this._osmLink]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const infoboxcontents = new Combine(
 | 
					        const infoboxcontents = new Combine(
 | 
				
			||||||
            [ new VerticalCombine(info, "infobox-information "), questionsHtml]);
 | 
					            [ new VerticalCombine(info, "infobox-information "), questionElement ?? ""]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return "<div class='featureinfobox'>" +
 | 
					        return "<div class='featureinfobox'>" +
 | 
				
			||||||
            new Combine([
 | 
					            new Combine([
 | 
				
			||||||
                "<div class='featureinfoboxtitle'>" + title.Render() + "</div>",
 | 
					                "<div class='featureinfoboxtitle'>",
 | 
				
			||||||
                "<div class='infoboxcontents'>" + infoboxcontents.Render() + "</div>"]).Render() + "</div>";
 | 
					                title, 
 | 
				
			||||||
 | 
					                "</div>",
 | 
				
			||||||
 | 
					                "<div class='infoboxcontents'>",
 | 
				
			||||||
 | 
					                infoboxcontents,
 | 
				
			||||||
 | 
					                "</div>"]).Render() + "</div>";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,24 +1,36 @@
 | 
				
			||||||
import {UIElement} from "./UIElement";
 | 
					import {UIElement} from "./UIElement";
 | 
				
			||||||
import {VariableUiElement} from "./Base/VariableUIElement";
 | 
					 | 
				
			||||||
import Translations from "./i18n/Translations";
 | 
					import Translations from "./i18n/Translations";
 | 
				
			||||||
import {State} from "../State";
 | 
					import {State} from "../State";
 | 
				
			||||||
import {UIEventSource} from "../Logic/UIEventSource";
 | 
					import Combine from "./Base/Combine";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Handles the full screen popup on mobile
 | 
					 * 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)) {
 | 
					    constructor(onClear: (() => void)) {
 | 
				
			||||||
        this._uielement = State.state.fullScreenMessage;
 | 
					        super(undefined);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const self = this;
 | 
					        const self = this;
 | 
				
			||||||
        this._uielement.addCallback(function () {
 | 
					
 | 
				
			||||||
            self.update();
 | 
					        State.state.fullScreenMessage.addCallback(uielement => {
 | 
				
			||||||
 | 
					            return self._uielement = uielement?.SetClass("messagesboxmobile-scroll")?.Activate();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        
 | 
					        this._uielement = State.state.fullScreenMessage.data;
 | 
				
			||||||
        this.update();
 | 
					        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) {
 | 
					        if (window !== undefined) {
 | 
				
			||||||
            window.onhashchange = function () {
 | 
					            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(() => {
 | 
					            .onClick(() => {
 | 
				
			||||||
                self._uielement.setData(undefined);
 | 
					                console.log("Returning...")
 | 
				
			||||||
 | 
					                State.state.fullScreenMessage.setData(undefined);
 | 
				
			||||||
                onClear();
 | 
					                onClear();
 | 
				
			||||||
            })
 | 
					                self.Update();
 | 
				
			||||||
            .AttachTo("to-the-map");
 | 
					            });
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    update() {
 | 
					    InnerRender(): string {
 | 
				
			||||||
        const wrapper = document.getElementById("messagesboxmobilewrapper");
 | 
					        if (this._uielement === undefined) {
 | 
				
			||||||
        const gen = this._uielement.data;
 | 
					            return "";
 | 
				
			||||||
        if (gen === undefined) {
 | 
					 | 
				
			||||||
            wrapper.classList.add("hidden")
 | 
					 | 
				
			||||||
            if (location.hash !== "") {
 | 
					 | 
				
			||||||
                location.hash = ""
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        location.hash = "#element"
 | 
					        return new Combine([this._uielement, this.returnToTheMap]).SetStyle("").Render();
 | 
				
			||||||
        wrapper.classList.remove("hidden");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        gen
 | 
					 | 
				
			||||||
            ?.HideOnEmpty(true)
 | 
					 | 
				
			||||||
            ?.AttachTo("messagesboxmobile")
 | 
					 | 
				
			||||||
            ?.Activate();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,7 @@ export class MoreScreen extends UIElement {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        els.push(new VariableUiElement(
 | 
					        els.push(new VariableUiElement(
 | 
				
			||||||
            State.state.osmConnection.userDetails.map(userDetails => {
 | 
					            State.state.osmConnection.userDetails.map(userDetails => {
 | 
				
			||||||
                if (userDetails.csCount < State.userJourney.themeGeneratorUnlock) {
 | 
					                if (userDetails.csCount < State.userJourney.themeGeneratorReadOnlyUnlock) {
 | 
				
			||||||
                    return tr.requestATheme.Render();
 | 
					                    return tr.requestATheme.Render();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return new SubtleButton("./assets/pencil.svg", tr.createYourOwnTheme, {
 | 
					                return new SubtleButton("./assets/pencil.svg", tr.createYourOwnTheme, {
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,7 @@ export class MoreScreen extends UIElement {
 | 
				
			||||||
        for (const k in AllKnownLayouts.allSets) {
 | 
					        for (const k in AllKnownLayouts.allSets) {
 | 
				
			||||||
            const layout : Layout = AllKnownLayouts.allSets[k];
 | 
					            const layout : Layout = AllKnownLayouts.allSets[k];
 | 
				
			||||||
            if (k === PersonalLayout.NAME) {
 | 
					            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;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,6 @@ export class MoreScreen extends UIElement {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const customThemesNames = State.state.installedThemes.data ?? [];
 | 
					        const customThemesNames = State.state.installedThemes.data ?? [];
 | 
				
			||||||
        if (customThemesNames.length > 0) {
 | 
					        if (customThemesNames.length > 0) {
 | 
				
			||||||
            console.log(customThemesNames)
 | 
					 | 
				
			||||||
            els.push(Translations.t.general.customThemeIntro)
 | 
					            els.push(Translations.t.general.customThemeIntro)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (const installed of State.state.installedThemes.data) {
 | 
					            for (const installed of State.state.installedThemes.data) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ export abstract class UIElement extends UIEventSource<string> {
 | 
				
			||||||
        if (UIElement.runningFromConsole) {
 | 
					        if (UIElement.runningFromConsole) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        let element = document.getElementById(this.id);
 | 
					        let element = document.getElementById(this.id);
 | 
				
			||||||
        if (element === undefined || element === null) {
 | 
					        if (element === undefined || element === null) {
 | 
				
			||||||
            // The element is not painted
 | 
					            // The element is not painted
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ export abstract class UIElement extends UIEventSource<string> {
 | 
				
			||||||
            if (element.innerHTML === "") {
 | 
					            if (element.innerHTML === "") {
 | 
				
			||||||
                element.parentElement.style.display = "none";
 | 
					                element.parentElement.style.display = "none";
 | 
				
			||||||
            } else {
 | 
					            } 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 abstract InnerRender(): string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Activate(): void {
 | 
					    public Activate(): UIElement {
 | 
				
			||||||
        for (const i in this) {
 | 
					        for (const i in this) {
 | 
				
			||||||
            const child = this[i];
 | 
					            const child = this[i];
 | 
				
			||||||
            if (child instanceof UIElement) {
 | 
					            if (child instanceof UIElement) {
 | 
				
			||||||
| 
						 | 
					@ -187,6 +187,7 @@ export abstract class UIElement extends UIEventSource<string> {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        return this;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public IsEmpty(): boolean {
 | 
					    public IsEmpty(): boolean {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,6 @@
 | 
				
			||||||
import {UIElement} from "./UIElement";
 | 
					import {UIElement} from "./UIElement";
 | 
				
			||||||
import Locale from "../UI/i18n/Locale";
 | 
					import Locale from "../UI/i18n/Locale";
 | 
				
			||||||
import {State} from "../State";
 | 
					import {State} from "../State";
 | 
				
			||||||
import {Layout} from "../Customizations/Layout";
 | 
					 | 
				
			||||||
import Translations from "./i18n/Translations";
 | 
					import Translations from "./i18n/Translations";
 | 
				
			||||||
import Combine from "./Base/Combine";
 | 
					import Combine from "./Base/Combine";
 | 
				
			||||||
import {InitUiElements} from "../InitUiElements";
 | 
					import {InitUiElements} from "../InitUiElements";
 | 
				
			||||||
| 
						 | 
					@ -20,27 +19,18 @@ export class WelcomeMessage extends UIElement {
 | 
				
			||||||
        super(State.state.osmConnection.userDetails);
 | 
					        super(State.state.osmConnection.userDetails);
 | 
				
			||||||
        this.ListenTo(Locale.language);
 | 
					        this.ListenTo(Locale.language);
 | 
				
			||||||
        this.languagePicker = InitUiElements.CreateLanguagePicker(Translations.t.general.pickLanguage);
 | 
					        this.languagePicker = InitUiElements.CreateLanguagePicker(Translations.t.general.pickLanguage);
 | 
				
			||||||
 | 
					        const layout = State.state.layoutToUse.data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        function fromLayout(f: (layout: Layout) => (string | UIElement)): UIElement {
 | 
					        this.description =Translations.W(layout.welcomeMessage);
 | 
				
			||||||
            return Translations.W(f(State.state.layoutToUse.data));
 | 
					        this.plzLogIn =
 | 
				
			||||||
        }
 | 
					            Translations.W(layout.gettingStartedPlzLogin)
 | 
				
			||||||
 | 
					                .onClick(() => {
 | 
				
			||||||
        this.description = fromLayout((layout) => layout.welcomeMessage);
 | 
					                    State.state.osmConnection.AttemptLogin()
 | 
				
			||||||
        this.plzLogIn = 
 | 
					                });
 | 
				
			||||||
            fromLayout((layout) => layout.gettingStartedPlzLogin
 | 
					        this.welcomeBack = Translations.W(layout.welcomeBackMessage);
 | 
				
			||||||
                .onClick(() => {State.state.osmConnection.AttemptLogin()})
 | 
					        this.tail = Translations.W(layout.welcomeTail);
 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        this.welcomeBack = fromLayout((layout) => layout.welcomeBackMessage);
 | 
					 | 
				
			||||||
        this.tail = fromLayout((layout) => layout.welcomeTail);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected InnerUpdate(htmlElement: HTMLElement) {
 | 
					 | 
				
			||||||
        super.InnerUpdate(htmlElement);
 | 
					 | 
				
			||||||
        console.log("Innerupdating welcome message")
 | 
					 | 
				
			||||||
        this.plzLogIn.Update();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    InnerRender(): string {
 | 
					    InnerRender(): string {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let loginStatus = undefined;
 | 
					        let loginStatus = undefined;
 | 
				
			||||||
| 
						 | 
					@ -52,7 +42,8 @@ export class WelcomeMessage extends UIElement {
 | 
				
			||||||
        return new Combine([
 | 
					        return new Combine([
 | 
				
			||||||
            this.description,
 | 
					            this.description,
 | 
				
			||||||
            "<br/></br>",
 | 
					            "<br/></br>",
 | 
				
			||||||
           // TODO this button is broken - figure out why loginStatus,
 | 
					            // TODO this button is broken - figure out why loginStatus,
 | 
				
			||||||
 | 
					            loginStatus,
 | 
				
			||||||
            this.tail,
 | 
					            this.tail,
 | 
				
			||||||
            "<br/>",
 | 
					            "<br/>",
 | 
				
			||||||
            this.languagePicker
 | 
					            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"
 | 
					      "amenity=bicycle_parking"
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "icon": "./assets/layers/bike_parking/parking.svg",
 | 
					  "icon": {
 | 
				
			||||||
 | 
					    "render": {
 | 
				
			||||||
 | 
					      "en": "./assets/layers/bike_parking/parking.svg"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  "size": {
 | 
					  "size": {
 | 
				
			||||||
    "render": {
 | 
					    "render": {
 | 
				
			||||||
      "en": "50,50,bottom"
 | 
					      "en": "50,50,bottom"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,70 +1,25 @@
 | 
				
			||||||
import {UIEventSource} from "./Logic/UIEventSource";
 | 
					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 {GenerateEmpty} from "./UI/CustomGenerator/GenerateEmpty";
 | 
				
			||||||
import PageSplit from "./UI/Base/PageSplit";
 | 
					 | 
				
			||||||
import HelpText from "./Customizations/HelpText";
 | 
					 | 
				
			||||||
import {TagRendering} from "./Customizations/TagRendering";
 | 
					import {TagRendering} from "./Customizations/TagRendering";
 | 
				
			||||||
import {LayoutConfigJson} from "./Customizations/JSON/LayoutConfigJson";
 | 
					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();
 | 
					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;
 | 
					    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();
 | 
					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);
 | 
					new CustomGeneratorPanel(connection, layout)
 | 
				
			||||||
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")
 | 
					 | 
				
			||||||
    .AttachTo("maindiv");
 | 
					    .AttachTo("maindiv");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										439
									
								
								index.css
									
										
									
									
									
								
							
							
						
						
									
										439
									
								
								index.css
									
										
									
									
									
								
							| 
						 | 
					@ -284,6 +284,9 @@
 | 
				
			||||||
    padding-top: 0.2em;
 | 
					    padding-top: 0.2em;
 | 
				
			||||||
    padding-bottom: 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)) {
 | 
					@media only screen and (max-height: 600px) and (not (max-width:700px)) {
 | 
				
			||||||
| 
						 | 
					@ -351,9 +354,6 @@
 | 
				
			||||||
    padding-right: 10px; /* Shadow offset */
 | 
					    padding-right: 10px; /* Shadow offset */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#messagesboxmobilewrapper {
 | 
					 | 
				
			||||||
    display: none; /*Only shown on small screens*/
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.collapse-button {
 | 
					.collapse-button {
 | 
				
			||||||
    position: absolute;
 | 
					    position: absolute;
 | 
				
			||||||
| 
						 | 
					@ -556,6 +556,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media only screen and (max-width: 600px), only screen and (max-height: 600px) {
 | 
					@media only screen and (max-width: 600px), only screen and (max-height: 600px) {
 | 
				
			||||||
 | 
					    #hidden-on-mobile {
 | 
				
			||||||
 | 
					        display: block;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
    #messagesbox-wrapper {
 | 
					    #messagesbox-wrapper {
 | 
				
			||||||
        display: none;
 | 
					        display: none;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -590,33 +594,20 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #messagesboxmobilewrapper {
 | 
					    .messagesboxmobile-scroll {
 | 
				
			||||||
        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 {
 | 
					 | 
				
			||||||
        display: block;
 | 
					        display: block;
 | 
				
			||||||
        width: 100vw;
 | 
					        width: 100vw;
 | 
				
			||||||
        overflow-y: auto;
 | 
					        box-sizing: border-box;
 | 
				
			||||||
        padding: 0;
 | 
					        overflow-y: scroll;
 | 
				
			||||||
 | 
					        padding: 1em;
 | 
				
			||||||
        margin: 0;
 | 
					        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 {
 | 
					    #messagesboxmobile {
 | 
				
			||||||
        padding: 1em;
 | 
					        display: block;
 | 
				
			||||||
        padding-bottom: 2em;
 | 
					        position: absolute;
 | 
				
			||||||
        border-radius: 1em;
 | 
					        z-index: 10000;
 | 
				
			||||||
        background-color: white;
 | 
					        background-color: white;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -634,77 +625,77 @@
 | 
				
			||||||
        box-shadow: unset;
 | 
					        box-shadow: unset;
 | 
				
			||||||
        overflow-y: unset;
 | 
					        overflow-y: unset;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#to-the-map {
 | 
					    .to-the-map {
 | 
				
			||||||
    position: relative;
 | 
					        display: block;
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#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;
 | 
					 | 
				
			||||||
        box-sizing: border-box;
 | 
					        box-sizing: border-box;
 | 
				
			||||||
    }
 | 
					        height: 2.5em;
 | 
				
			||||||
    
 | 
					        margin: 0;
 | 
				
			||||||
    #welcomeMessage{
 | 
					        padding: 0.5em;
 | 
				
			||||||
        box-shadow: unset;
 | 
					        padding-top: 0.75em;
 | 
				
			||||||
        max-height: 100vh;
 | 
					        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 {
 | 
					.logo {
 | 
				
			||||||
    float:right;
 | 
					    float:right;
 | 
				
			||||||
| 
						 | 
					@ -841,170 +832,173 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.attribution-author {
 | 
					    .attribution-author {
 | 
				
			||||||
    display: inline-block;
 | 
					        display: inline-block;
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.license {
 | 
					    .license {
 | 
				
			||||||
    font-size: small;
 | 
					        font-size: small;
 | 
				
			||||||
    font-weight: lighter;
 | 
					        font-weight: lighter;
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.attribution a {
 | 
					    .attribution a {
 | 
				
			||||||
    color: white;
 | 
					        color: white;
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**************** Image upload flow ***************/
 | 
					    /**************** Image upload flow ***************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.imageflow {
 | 
					    .imageflow {
 | 
				
			||||||
    margin-top: 1em;
 | 
					        margin-top: 1em;
 | 
				
			||||||
    margin-bottom: 2em;
 | 
					        margin-bottom: 2em;
 | 
				
			||||||
    text-align: center;
 | 
					        text-align: center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.imageflow-file-input-wrapper {
 | 
					    .imageflow-file-input-wrapper {
 | 
				
			||||||
    display: flex;
 | 
					        display: flex;
 | 
				
			||||||
    flex-wrap: wrap;
 | 
					        flex-wrap: wrap;
 | 
				
			||||||
    padding: 0.5em;
 | 
					        padding: 0.5em;
 | 
				
			||||||
    border-radius: 1em;
 | 
					        border-radius: 1em;
 | 
				
			||||||
    border: 3px solid black;
 | 
					        border: 3px solid black;
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.imageflow-add-picture {
 | 
					    .imageflow-add-picture {
 | 
				
			||||||
    font-size: 28px;
 | 
					        font-size: 28px;
 | 
				
			||||||
    font-weight: bold;
 | 
					        font-weight: bold;
 | 
				
			||||||
    float: left;
 | 
					        float: left;
 | 
				
			||||||
    margin-top: 4px;
 | 
					        margin-top: 4px;
 | 
				
			||||||
    padding-top: 4px;
 | 
					        padding-top: 4px;
 | 
				
			||||||
    padding-bottom: 4px;
 | 
					        padding-bottom: 4px;
 | 
				
			||||||
    padding-left: 13px;
 | 
					        padding-left: 13px;
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.imageflow-file-input-wrapper img {
 | 
					    .imageflow-file-input-wrapper img {
 | 
				
			||||||
    width: 36px;
 | 
					        width: 36px;
 | 
				
			||||||
    height: 36px;
 | 
					        height: 36px;
 | 
				
			||||||
    padding: 0.1em;
 | 
					        padding: 0.1em;
 | 
				
			||||||
    margin-top: 5px;
 | 
					        margin-top: 5px;
 | 
				
			||||||
    border-radius: 0;
 | 
					        border-radius: 0;
 | 
				
			||||||
    float: left;
 | 
					        float: left;
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.license-picker {
 | 
					    .license-picker {
 | 
				
			||||||
    float: left;
 | 
					        float: left;
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.imageflow > input {
 | 
					    .imageflow > input {
 | 
				
			||||||
    display: none;
 | 
					        display: none;
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/***************** Info box (box containing features and questions ******************/
 | 
					    /***************** Info box (box containing features and questions ******************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.leaflet-popup-content {
 | 
					    .leaflet-popup-content {
 | 
				
			||||||
    width: 40em !important;
 | 
					        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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.featureinfoboxtitle {
 | 
					  
 | 
				
			||||||
    position: relative;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
.question .form-text-field > input{
 | 
					    #messagesboxmobile .featureinfobox {
 | 
				
			||||||
    width: 100%;
 | 
					        max-height: unset;
 | 
				
			||||||
    box-sizing: border-box;
 | 
					        overflow-y: unset;
 | 
				
			||||||
} 
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.osmlink {
 | 
					    #messagesboxmobile .featureinfobox > div {
 | 
				
			||||||
    position: absolute;
 | 
					        width: 100%;
 | 
				
			||||||
    right: 0;
 | 
					        max-width: unset;
 | 
				
			||||||
}
 | 
					        padding-left: unset;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.osm-logo path {
 | 
					    .featureinfobox {
 | 
				
			||||||
    fill: #7ebc6f;
 | 
					        max-height: 80vh;
 | 
				
			||||||
}
 | 
					        overflow-y: auto;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.featureinfoboxtitle .answer {
 | 
					    .featureinfobox > div {
 | 
				
			||||||
    display: inline;
 | 
					        width: calc(100% - 2em);
 | 
				
			||||||
    margin-right: 3em;
 | 
					        padding-left: 1em;
 | 
				
			||||||
}
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
.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 {
 | 
					    .featureinfoboxtitle {
 | 
				
			||||||
    width: 1.3em;
 | 
					        position: relative;
 | 
				
			||||||
    height: 1.3em;
 | 
					    }
 | 
				
			||||||
    padding: 0.5em;
 | 
					 | 
				
			||||||
    border-radius: 0.65em;
 | 
					 | 
				
			||||||
    border: solid black 1px;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    font-size: medium;
 | 
					    .question .form-text-field > input {
 | 
				
			||||||
    float: right;
 | 
					        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 {
 | 
					        font-size: medium;
 | 
				
			||||||
    position: absolute;
 | 
					        float: right;
 | 
				
			||||||
    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 {
 | 
					    .wikipedialink {
 | 
				
			||||||
    float: right;
 | 
					        position: absolute;
 | 
				
			||||||
    margin-left: 1em;
 | 
					        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;
 | 
					    padding: 0.5em;
 | 
				
			||||||
    word-break: break-all;
 | 
					    word-break: break-all;
 | 
				
			||||||
    color: black;
 | 
					    color: black;
 | 
				
			||||||
 | 
					    box-sizing: border-box;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.iframe-code-block {
 | 
					.iframe-code-block {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								index.html
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								index.html
									
										
									
									
									
								
							| 
						 | 
					@ -14,7 +14,7 @@
 | 
				
			||||||
    <!-- $$$OG-META -->
 | 
					    <!-- $$$OG-META -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <style>
 | 
					    <style>
 | 
				
			||||||
        .decoration-desktop img {
 | 
					        #decoration-desktop img {
 | 
				
			||||||
            width: 100%;
 | 
					            width: 100%;
 | 
				
			||||||
            height: 100%;
 | 
					            height: 100%;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -23,33 +23,16 @@
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body>
 | 
					<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 -->
 | 
					    <!-- A nice decoration while loading or on errors -->
 | 
				
			||||||
    <!-- DECORATION 0 START -->
 | 
					    <!-- DECORATION 0 START -->
 | 
				
			||||||
    <img src="./assets/add.svg"/>
 | 
					    <img src="./assets/add.svg"/>
 | 
				
			||||||
    <!-- DECORATION 0 END -->
 | 
					    <!-- DECORATION 0 END -->
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="messagesboxmobilewrapper">
 | 
					<div id="hidden-on-mobile">
 | 
				
			||||||
    <div id="decoration" style="position: absolute; left: 1em; top: 1em; z-index: 1; width: 15em; height: 15em">
 | 
					    <div id="messagesboxmobile">
 | 
				
			||||||
        <!-- 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>
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								index.ts
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								index.ts
									
										
									
									
									
								
							| 
						 | 
					@ -2,7 +2,6 @@ import {TagRendering} from "./Customizations/TagRendering";
 | 
				
			||||||
import {UserBadge} from "./UI/UserBadge";
 | 
					import {UserBadge} from "./UI/UserBadge";
 | 
				
			||||||
import {CenterMessageBox} from "./UI/CenterMessageBox";
 | 
					import {CenterMessageBox} from "./UI/CenterMessageBox";
 | 
				
			||||||
import {TagUtils} from "./Logic/Tags";
 | 
					import {TagUtils} from "./Logic/Tags";
 | 
				
			||||||
import {FullScreenMessageBoxHandler} from "./UI/FullScreenMessageBoxHandler";
 | 
					 | 
				
			||||||
import {FeatureInfoBox} from "./UI/FeatureInfoBox";
 | 
					import {FeatureInfoBox} from "./UI/FeatureInfoBox";
 | 
				
			||||||
import {SimpleAddUI} from "./UI/SimpleAddUI";
 | 
					import {SimpleAddUI} from "./UI/SimpleAddUI";
 | 
				
			||||||
import {SearchAndGo} from "./UI/SearchAndGo";
 | 
					import {SearchAndGo} from "./UI/SearchAndGo";
 | 
				
			||||||
| 
						 | 
					@ -17,6 +16,7 @@ import {QueryParameters} from "./Logic/Web/QueryParameters";
 | 
				
			||||||
import {LocalStorageSource} from "./Logic/Web/LocalStorageSource";
 | 
					import {LocalStorageSource} from "./Logic/Web/LocalStorageSource";
 | 
				
			||||||
import {PersonalLayout} from "./Logic/PersonalLayout";
 | 
					import {PersonalLayout} from "./Logic/PersonalLayout";
 | 
				
			||||||
import {FromJSON} from "./Customizations/JSON/FromJSON";
 | 
					import {FromJSON} from "./Customizations/JSON/FromJSON";
 | 
				
			||||||
 | 
					import {FullScreenMessageBox} from "./UI/FullScreenMessageBoxHandler";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TagRendering.injectFunction();
 | 
					TagRendering.injectFunction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,9 +28,9 @@ if (location.href.startsWith("http://buurtnatuur.be")) {
 | 
				
			||||||
    window.location.replace("https://buurtnatuur.be");
 | 
					    window.location.replace("https://buurtnatuur.be");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const testing = QueryParameters.GetQueryParameter("test", "true");
 | 
				
			||||||
if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
 | 
					if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
 | 
				
			||||||
    // Set to true if testing and changes should NOT be saved
 | 
					    // Set to true if testing and changes should NOT be saved
 | 
				
			||||||
    const testing = QueryParameters.GetQueryParameter("test", "true");
 | 
					 | 
				
			||||||
    testing.setData(testing.data ?? "true")
 | 
					    testing.setData(testing.data ?? "true")
 | 
				
			||||||
    // If you have a testfile somewhere, enable this to spoof overpass
 | 
					    // 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
 | 
					    // 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") {
 | 
					if (layoutFromBase64 !== "false") {
 | 
				
			||||||
    State.state.layoutDefinition = hash.substr(1);
 | 
					    State.state.layoutDefinition = hash.substr(1);
 | 
				
			||||||
    State.state.osmConnection.OnLoggedIn(() => {
 | 
					    if (!testing) {
 | 
				
			||||||
        State.state.osmConnection.GetLongPreference("installed-theme-" + layoutToUse.id).setData(State.state.layoutDefinition);
 | 
					        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();
 | 
					InitUiElements.InitBaseMap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
new FixedUiElement("").AttachTo("decoration"); // Remove the decoration
 | 
					new FixedUiElement("").AttachTo("decoration-desktop"); // Remove the decoration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function setupAllLayerElements() {
 | 
					function setupAllLayerElements() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,9 +236,12 @@ InitUiElements.OnlyIf((State.state.featureSwitchSearch), () => {
 | 
				
			||||||
    new SearchAndGo().AttachTo("searchbox");
 | 
					    new SearchAndGo().AttachTo("searchbox");
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
new FullScreenMessageBoxHandler(() => {
 | 
					
 | 
				
			||||||
 | 
					new FullScreenMessageBox(() => {
 | 
				
			||||||
    State.state.selectedElement.setData(undefined)
 | 
					    State.state.selectedElement.setData(undefined)
 | 
				
			||||||
}).update();
 | 
					}).AttachTo("messagesboxmobile");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
InitUiElements.OnlyIf(State.state.featureSwitchWelcomeMessage, () => {
 | 
					InitUiElements.OnlyIf(State.state.featureSwitchWelcomeMessage, () => {
 | 
				
			||||||
    InitUiElements.InitWelcomeMessage()
 | 
					    InitUiElements.InitWelcomeMessage()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue