diff --git a/Customizations/LayerDefinition.ts b/Customizations/LayerDefinition.ts index f294ac4..138102c 100644 --- a/Customizations/LayerDefinition.ts +++ b/Customizations/LayerDefinition.ts @@ -50,7 +50,7 @@ export class LayerDefinition { /** * This UIElement is rendered as title element in the popup */ - title: TagRenderingOptions | UIElement; + title: TagRenderingOptions; /** * These are the questions/shown attributes in the popup */ diff --git a/Customizations/Layout.ts b/Customizations/Layout.ts index 4645c4d..eb13be3 100644 --- a/Customizations/Layout.ts +++ b/Customizations/Layout.ts @@ -1,13 +1,18 @@ import {LayerDefinition} from "./LayerDefinition"; -import { UIElement } from "../UI/UIElement"; +import {UIElement} from "../UI/UIElement"; import {FixedUiElement} from "../UI/Base/FixedUiElement"; import Translation from "../UI/i18n/Translation"; import Translations from "../UI/i18n/Translations"; +import Locale from "../UI/i18n/Locale"; +import {VariableUiElement} from "../UI/Base/VariableUIElement"; +import {OsmConnection, UserDetails} from "../Logic/OsmConnection"; +import {UIEventSource} from "../UI/UIEventSource"; /** * A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers). */ export class Layout { + public name: string; public title: UIElement; public layers: LayerDefinition[]; @@ -45,8 +50,8 @@ export class Layout { startLat: number, startLon: number, welcomeMessage: UIElement | string, - gettingStartedPlzLogin: UIElement | string = "Please login to get started", - welcomeBackMessage: UIElement | string = "You are logged in. Welcome back!", + gettingStartedPlzLogin: UIElement | string = Translations.t.general.getStarted, + welcomeBackMessage: UIElement | string = Translations.t.general.welcomeBack, welcomeTail: UIElement | string = "" ) { this.supportedLanguages = supportedLanguages; @@ -56,11 +61,62 @@ export class Layout { this.startzoom = startzoom; this.name = name; this.layers = layers; - this.welcomeMessage =Translations.W(welcomeMessage) + this.welcomeMessage = Translations.W(welcomeMessage) this.gettingStartedPlzLogin = Translations.W(gettingStartedPlzLogin); this.welcomeBackMessage = Translations.W(welcomeBackMessage); this.welcomeTail = Translations.W(welcomeTail); } + +} + +export class WelcomeMessage extends UIElement { + private readonly layout: Layout; + private readonly userDetails: UIEventSource; + private osmConnection: OsmConnection; + + private readonly description: UIElement; + private readonly plzLogIn: UIElement; + private readonly welcomeBack: UIElement; + private readonly tail: UIElement; + + + constructor(layout: Layout, osmConnection: OsmConnection) { + super(osmConnection.userDetails); + this.ListenTo(Locale.language); + this.osmConnection = osmConnection; + this.layout = layout; + this.userDetails = osmConnection.userDetails; + + this.description = layout.welcomeMessage; + console.log(" >>>>",this.description, "DESCR ") + this.plzLogIn = layout.gettingStartedPlzLogin; + this.welcomeBack = layout.welcomeBackMessage; + this.tail = layout.welcomeTail; + } + + InnerRender(): string { + return "
" + + this.description.Render() + + "
"+ + (this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render() + + "
"+ + this.tail.Render() + + "
" + + ; + /* + return new VariableUiElement( + this.userDetails.map((userdetails) => { + }), + function () { + + }).ListenTo(Locale.language);*/ + } + + protected InnerUpdate(htmlElement: HTMLElement) { + this.osmConnection.registerActivateOsmAUthenticationClass() + } + } diff --git a/Customizations/Layouts/Cyclofix.ts b/Customizations/Layouts/Cyclofix.ts index 32a7ad5..87753c0 100644 --- a/Customizations/Layouts/Cyclofix.ts +++ b/Customizations/Layouts/Cyclofix.ts @@ -19,13 +19,14 @@ export default class Cyclofix extends Layout { 16, 50.8465573, 4.3516970, + /* Translations.t.cyclofix.title/*/ new Combine([ "

", Translations.t.cyclofix.title, "


", Translations.t.cyclofix.description, "

" - ]), - "", ""); + ])//*/ + ); } } diff --git a/Customizations/Questions/bike/ParkingType.ts b/Customizations/Questions/bike/ParkingType.ts index 5b1cbf8..fa8ab50 100644 --- a/Customizations/Questions/bike/ParkingType.ts +++ b/Customizations/Questions/bike/ParkingType.ts @@ -1,38 +1,61 @@ import {TagRenderingOptions} from "../../TagRendering"; import {Tag} from "../../../Logic/TagsFilter"; import Translations from "../../../UI/i18n/Translations"; +import Combine from "../../../UI/Base/Combine"; +class ParkingTypeHelper { + static GenerateMappings() { + const images = { + stands: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Bike_racks_at_north-west_of_Westfield_-_geograph.org.uk_-_1041057.jpg/100px-Bike_racks_at_north-west_of_Westfield_-_geograph.org.uk_-_1041057.jpg", + wall_loops: "https://wiki.openstreetmap.org/w/images/thumb/c/c2/Bike-parking-wheelbender.jpg/100px-Bike-parking-wheelbender.jpg", + handlebar_holder: "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Bicycle_parking_handlebar_holder.jpg/100px-Bicycle_parking_handlebar_holder.jpg", + shed: "https://wiki.openstreetmap.org/w/images/thumb/b/b2/Bike-shelter.jpg/100px-Bike-shelter.jpg", + rack: "https://wiki.openstreetmap.org/w/images/thumb/4/41/Triton_Bike_Rack.png/100px-Triton_Bike_Rack.png", + "two-tier": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Bicis_a_l%27estaci%C3%B3_de_Leiden.JPG/100px-Bicis_a_l%27estaci%C3%B3_de_Leiden.JPG" + }; + + + const toImg = (url) => `` + const mappings = []; + const to = Translations.t.cyclofix.parking.type + + for (const imagesKey in images) { + const mapping = + { + k: new Tag("bicycle_parking", imagesKey), + txt: new Combine([ + to[imagesKey], + to.eg, + toImg(images[imagesKey]) + ]) + }; + + mappings.push(mapping); + + } + + return mappings; + } +} export default class ParkingType extends TagRenderingOptions { constructor() { - const images = { - stands: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Bike_racks_at_north-west_of_Westfield_-_geograph.org.uk_-_1041057.jpg/100px-Bike_racks_at_north-west_of_Westfield_-_geograph.org.uk_-_1041057.jpg", - loops: "https://wiki.openstreetmap.org/w/images/thumb/c/c2/Bike-parking-wheelbender.jpg/100px-Bike-parking-wheelbender.jpg", - handlebar: "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Bicycle_parking_handlebar_holder.jpg/100px-Bicycle_parking_handlebar_holder.jpg", - shed: "https://wiki.openstreetmap.org/w/images/thumb/b/b2/Bike-shelter.jpg/100px-Bike-shelter.jpg", - rack: "https://wiki.openstreetmap.org/w/images/thumb/4/41/Triton_Bike_Rack.png/100px-Triton_Bike_Rack.png", - double: "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Bicis_a_l%27estaci%C3%B3_de_Leiden.JPG/100px-Bicis_a_l%27estaci%C3%B3_de_Leiden.JPG" - } - const toImg = (url) => `` + const to = Translations.t.cyclofix.parking.type + + super({ priority: 5, - question: to.question.Render(), + question: to.question, freeform: { key: "bicycle_parking", extraTags: new Tag("fixme", "Freeform bicycle_parking= tag used: possibly a wrong value"), template: to.template.txt, renderTemplate: to.render.txt, - placeholder: Translations.t.cyclofix.freeFormPlaceholder.txt, + placeholder: Translations.t.cyclofix.freeFormPlaceholder, }, - mappings: [ - {k: new Tag("bicycle_parking", "stands"), txt: `${to.stands.Render()}, bijvoorbeeld: ${toImg(images.stands)}`}, - {k: new Tag("bicycle_parking", "wall_loops"), txt: `${to.loops.Render()}, bijvoorbeeld: ${toImg(images.loops)}`}, - {k: new Tag("bicycle_parking", "handlebar_holder"), txt: `${to.handlebar.Render()}, bijvoorbeeld: ${toImg(images.handlebar)}`}, - {k: new Tag("bicycle_parking", "shed"), txt: `${to.shed.Render()}, bijvoorbeeld: ${toImg(images.shed)}`}, - {k: new Tag("bicycle_parking", "rack"), txt: `${to.rack.Render()}, bijvoorbeeld: ${toImg(images.rack)}`}, - {k: new Tag("bicycle_parking", "two-tier"), txt: `${to.double.Render()}, bijvoorbeeld: ${toImg(images.double)}`} - ] + mappings: ParkingTypeHelper.GenerateMappings() + }); } } diff --git a/Customizations/Questions/bike/PumpManometer.ts b/Customizations/Questions/bike/PumpManometer.ts index 83380b1..1ae416e 100644 --- a/Customizations/Questions/bike/PumpManometer.ts +++ b/Customizations/Questions/bike/PumpManometer.ts @@ -7,11 +7,11 @@ export default class PumpManometer extends TagRenderingOptions { constructor() { const to = Translations.t.cyclofix.station.manometer super({ - question: to.question.Render(), + question: to.question, mappings: [ - {k: new Tag("manometer", "yes"), txt: to.yes.Render()}, - {k: new Tag("manometer", "no"), txt: to.no.Render()}, - {k: new Tag("manometer", "broken"), txt: to.broken.Render()} + {k: new Tag("manometer", "yes"), txt: to.yes}, + {k: new Tag("manometer", "no"), txt: to.no}, + {k: new Tag("manometer", "broken"), txt: to.broken} ] }); } diff --git a/Customizations/TagRendering.ts b/Customizations/TagRendering.ts index 6c8eb39..dad40bf 100644 --- a/Customizations/TagRendering.ts +++ b/Customizations/TagRendering.ts @@ -14,6 +14,7 @@ import {InputElementWrapper} from "../UI/Input/InputElementWrapper"; import {FixedInputElement} from "../UI/Input/FixedInputElement"; import {RadioButton} from "../UI/Input/RadioButton"; import Translations from "../UI/i18n/Translations"; +import Locale from "../UI/i18n/Locale"; export class TagRenderingOptions implements TagDependantUIElementConstructor { @@ -29,7 +30,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor { tagsPreprocessor?: (tags: any) => any; template: string; renderTemplate: string; - placeholder?: string; + placeholder?: string | UIElement; extraTags?: TagsFilter }; mappings?: { k: TagsFilter; txt: string | UIElement; priority?: number, substitute?: boolean }[] @@ -78,7 +79,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor { freeform?: { key: string, template: string, renderTemplate: string - placeholder?: string, + placeholder?: string | UIElement, extraTags?: TagsFilter, }, @@ -148,7 +149,7 @@ class TagRendering extends UIElement implements TagDependantUIElement { key: string, template: string, renderTemplate: string, - placeholder?: string, + placeholder?: string | UIElement, extraTags?: TagsFilter }; @@ -172,13 +173,14 @@ class TagRendering extends UIElement implements TagDependantUIElement { freeform?: { key: string, template: string, renderTemplate: string - placeholder?: string, + placeholder?: string | UIElement, extraTags?: TagsFilter, }, tagsPreprocessor?: ((tags: any) => any), mappings?: { k: TagsFilter, txt: string | UIElement, priority?: number, substitute?: boolean }[] }) { super(tags); + this.ListenTo(Locale.language); const self = this; this.ListenTo(this._questionSkipped); this.ListenTo(this._editMode); @@ -264,13 +266,13 @@ class TagRendering extends UIElement implements TagDependantUIElement { const cancelContents = this._editMode.map((isEditing) => { if (isEditing) { - return "Cancel"; + return ""+Translations.t.general.cancel.R()+""; } else { - return "Skip this question"; + return ""+Translations.t.general.skip.R()+""; } }); // And at last, set up the skip button - this._skipButton = new VariableUiElement(cancelContents).onClick(cancel); + this._skipButton = new VariableUiElement(cancelContents).onClick(cancel) ; } @@ -278,7 +280,7 @@ class TagRendering extends UIElement implements TagDependantUIElement { freeform?: { key: string, template: string, renderTemplate: string - placeholder?: string, + placeholder?: string | UIElement, extraTags?: TagsFilter, }, mappings?: { k: TagsFilter, txt: string | UIElement, priority?: number, substitute?: boolean }[] diff --git a/UI/Base/Combine.ts b/UI/Base/Combine.ts index 83f1033..12b4338 100644 --- a/UI/Base/Combine.ts +++ b/UI/Base/Combine.ts @@ -2,18 +2,30 @@ import {UIElement} from "../UIElement"; import Translations from "../i18n/Translations"; export default class Combine extends UIElement { - private uiElements: UIElement[]; + private uiElements: (string | UIElement)[]; constructor(uiElements: (string | UIElement)[]) { super(undefined); - this.uiElements = uiElements.map(Translations.W); + this.uiElements = uiElements; } InnerRender(): string { let elements = ""; for (const element of this.uiElements) { - elements += element.Render(); + if (element instanceof UIElement) { + elements += element.Render(); + } else { + elements += element; + } } return elements; } + + protected InnerUpdate(htmlElement: HTMLElement) { + for (const element of this.uiElements) { + if (element instanceof UIElement) { + element.Update(); + } + } + } } \ No newline at end of file diff --git a/UI/MessageBoxHandler.ts b/UI/FullScreenMessageBoxHandler.ts similarity index 85% rename from UI/MessageBoxHandler.ts rename to UI/FullScreenMessageBoxHandler.ts index a06a25a..88f6871 100644 --- a/UI/MessageBoxHandler.ts +++ b/UI/FullScreenMessageBoxHandler.ts @@ -1,11 +1,13 @@ -/** - * Keeps 'messagebox' and 'messageboxmobile' in sync, shows a 'close' button on the latter one - */ import {UIEventSource} from "./UIEventSource"; import {UIElement} from "./UIElement"; import {VariableUiElement} from "./Base/VariableUIElement"; +import Translations from "./i18n/Translations"; -export class MessageBoxHandler { +/** + * Handles the full screen popup on mobile + */ +export class FullScreenMessageBoxHandler { + private _uielement: UIEventSource; constructor(uielement: UIEventSource, @@ -22,13 +24,13 @@ export class MessageBoxHandler { } } - new VariableUiElement(new UIEventSource("

Return to the map

")) + Translations.t.general.returnToTheMap .onClick(() => { console.log("Clicked 'return to the map'") uielement.setData(undefined); onClear(); }) - .AttachTo("to-the-map"); + .AttachTo("to-the-map-h2"); } diff --git a/UI/SaveButton.ts b/UI/SaveButton.ts index 23065ff..a2728c4 100644 --- a/UI/SaveButton.ts +++ b/UI/SaveButton.ts @@ -1,5 +1,6 @@ import {UIEventSource} from "./UIEventSource"; import {UIElement} from "./UIElement"; +import Translations from "./i18n/Translations"; export class SaveButton extends UIElement { private _value: UIEventSource; @@ -17,9 +18,9 @@ export class SaveButton extends UIElement { this._value.data === null || this._value.data === "" ) { - return "Opslaan" + return ""+Translations.t.general.save.Render()+"" } - return "Save"; + return ""+Translations.t.general.save.Render()+""; } } \ No newline at end of file diff --git a/UI/UIElement.ts b/UI/UIElement.ts index 6d7b7fc..a060e27 100644 --- a/UI/UIElement.ts +++ b/UI/UIElement.ts @@ -13,10 +13,6 @@ export abstract class UIElement { this.id = "ui-element-" + UIElement.nextId; this._source = source; UIElement.nextId++; - if (UIElement.nextId % 100 == 0) { - - console.log(UIElement.nextId) - } this.ListenTo(source); } @@ -97,8 +93,7 @@ export abstract class UIElement { AttachTo(divId: string) { let element = document.getElementById(divId); if (element === null) { - console.log("SEVERE: could not attach UIElement to ", divId); - return; + throw "SEVERE: could not attach UIElement to " + divId; } element.innerHTML = this.Render(); this.Update(); diff --git a/UI/i18n/Translation.ts b/UI/i18n/Translation.ts index c2d3a04..911bec4 100644 --- a/UI/i18n/Translation.ts +++ b/UI/i18n/Translation.ts @@ -30,6 +30,4 @@ export default class Translation extends UIElement { return new Translation(this.translations).Render(); } - - } diff --git a/UI/i18n/Translations.ts b/UI/i18n/Translations.ts index f67f504..79e5cbc 100644 --- a/UI/i18n/Translations.ts +++ b/UI/i18n/Translations.ts @@ -36,13 +36,15 @@ export default class Translations { nl: 'Van welk type is deze fietsenparking?', fr: 'TODO: fr' }), + eg: new T({en: ", for example", nl: ", bijvoorbeeld"}), stands: new T({en: 'Staple racks', nl: 'Nietjes', fr: 'TODO: fr'}), - loops: new T({en: 'Wheel rack/loops', nl: 'Wielrek/lussen', fr: 'TODO: fr'}), - handlebar: new T({en: 'Handlebar holder', nl: 'Stuurhouder', fr: 'TODO: fr'}), + wall_loops: new T({en: 'Wheel rack/loops', nl: 'Wielrek/lussen', fr: 'TODO: fr'}), + handlebar_holder: new T({en: 'Handlebar holder', nl: 'Stuurhouder', fr: 'TODO: fr'}), shed: new T({en: 'Shed', nl: 'Schuur', fr: 'TODO: fr'}), rack: new T({en: 'Rack', nl: 'Rek', fr: 'TODO: fr'}), - double: new T({en: 'Two-tiered', nl: 'Dubbel (twee verdiepingen)', fr: 'TODO: fr'}), + "two-tier": new T({en: 'Two-tiered', nl: 'Dubbel (twee verdiepingen)', fr: 'TODO: fr'}), }, + operator: { render: new T({ en: 'This bike parking is operated by {operator}', @@ -293,9 +295,15 @@ export default class Translations { ready: new T({en: 'Done!', nl: 'Klaar!', fr: 'TODO: fr'}), }, general: { - loginWithOpenStreetMap: new T({en: "Login with OpenStreetMap", nl: "Aanmelden met OpenStreetMap"}) - - , + loginWithOpenStreetMap: new T({en: "Login with OpenStreetMap", nl: "Aanmelden met OpenStreetMap"}), + getStarted: new T({ + en: "Login with OpenStreetMap or make a free account to get started", + nl: "Meld je aan met je OpenStreetMap-account of maak snel en gratis een account om te beginnen/a>", + }), + welcomeBack: new T({ + en: "You are logged in, welcome back!", + nl: "Je bent aangemeld. Welkom terug!" + }), search: { search: new Translation({ en: "Search a location", @@ -314,7 +322,23 @@ export default class Translations { nl: "Niet gelukt..." }) - } + }, + returnToTheMap: new T({ + en: "Return to the map", + nl: "Naar de kaart" + }), + save: new T({ + en: "Save", + nl: "Opslaan" + }), + cancel: new T({ + en: "Cancel", + nl: "Annuleren" + }), + skip: new T({ + en: "Skip this question", + nl: "Vraag overslaan" + }) } } diff --git a/index.html b/index.html index b48ae01..36e8dc1 100644 --- a/index.html +++ b/index.html @@ -17,9 +17,14 @@
-
+
+
+
+

+ Loading... If this message persists, check if javascript is enabled and if no extension (uMatrix) is + blocking it. +

-
Loading... If this message persists, check if javascript is enabled and if no extension (uMatrix) is blocking it.
diff --git a/index.ts b/index.ts index cdca924..58a8b2a 100644 --- a/index.ts +++ b/index.ts @@ -11,7 +11,7 @@ import {Tag, TagUtils} from "./Logic/TagsFilter"; import {FilteredLayer} from "./Logic/FilteredLayer"; import {LayerUpdater} from "./Logic/LayerUpdater"; import {UIElement} from "./UI/UIElement"; -import {MessageBoxHandler} from "./UI/MessageBoxHandler"; +import {FullScreenMessageBoxHandler} from "./UI/FullScreenMessageBoxHandler"; import {Overpass} from "./Logic/Overpass"; import {FeatureInfoBox} from "./UI/FeatureInfoBox"; import {GeoLocationHandler} from "./Logic/GeoLocationHandler"; @@ -25,7 +25,7 @@ import {All} from "./Customizations/Layouts/All"; import Translations from "./UI/i18n/Translations"; import Translation from "./UI/i18n/Translation"; import Locale from "./UI/i18n/Locale"; -import {Layout} from "./Customizations/Layout"; +import {Layout, WelcomeMessage} from "./Customizations/Layout"; import {DropDown} from "./UI/Input/DropDown"; import {FixedInputElement} from "./UI/Input/FixedInputElement"; import {FixedUiElement} from "./UI/Base/FixedUiElement"; @@ -135,6 +135,7 @@ const osmConnection = new OsmConnection(dryRun); Locale.language.syncWith(osmConnection.GetPreference("language")); +// @ts-ignore window.setLanguage = function (language: string) { Locale.language.setData(language) } @@ -265,29 +266,18 @@ new SearchAndGo(bm).AttachTo("searchbox"); new CollapseButton("messagesbox") .AttachTo("collapseButton"); - -var generateWelcomeMessage = () => { - return new VariableUiElement( - osmConnection.userDetails.map((userdetails) => { - var login = layoutToUse.gettingStartedPlzLogin.Render(); - if (userdetails.loggedIn) { - login = layoutToUse.welcomeBackMessage.Render(); - } - return "
" + - layoutToUse.welcomeMessage.Render() + login + layoutToUse.welcomeTail.Render() + - "
"; - }), - function () { - osmConnection.registerActivateOsmAUthenticationClass() - }).ListenTo(Locale.language); -} -generateWelcomeMessage().AttachTo("messagesbox"); -fullScreenMessage.setData(generateWelcomeMessage()); +new WelcomeMessage(layoutToUse, osmConnection).AttachTo("messagesbox"); +fullScreenMessage.setData( + new WelcomeMessage(layoutToUse, osmConnection) +); -var messageBox = new MessageBoxHandler(fullScreenMessage, () => { +new FullScreenMessageBoxHandler(fullScreenMessage, () => { selectedElement.setData(undefined) -}); +}).update(); + +// fullScreenMessage.setData(generateWelcomeMessage()); + new CenterMessageBox( minZoom, @@ -310,4 +300,6 @@ new GeoLocationHandler(bm).AttachTo("geolocate-button"); // --------------- Send a ping to start various action -------- locationControl.ping(); -messageBox.update(); + + +window.setTimeout(() => {Locale.language.setData("nl")}, 5000) \ No newline at end of file diff --git a/test.ts b/test.ts index b2a2271..71276c8 100644 --- a/test.ts +++ b/test.ts @@ -1,9 +1,13 @@ import {DropDown} from "./UI/Input/DropDown"; import Locale from "./UI/i18n/Locale"; +import Combine from "./UI/Base/Combine"; +import Translations from "./UI/i18n/Translations"; console.log("Hello world") let languagePicker = new DropDown("", ["en", "nl"].map(lang => { return {value: lang, shown: lang} } -), Locale.language).AttachTo("maindiv"); \ No newline at end of file +), Locale.language).AttachTo("maindiv"); + +new Combine(["abc",Translations.t.cyclofix.title, Translations.t.cyclofix.title]).AttachTo("extradiv"); \ No newline at end of file