Merge branch 'bike-pumps' into feature/framework-improvements

This commit is contained in:
Pieter Vander Vennet 2020-07-20 21:52:22 +02:00
commit 615bbec05d
10 changed files with 101 additions and 25 deletions

View file

@ -14,9 +14,9 @@ import {NatureReserves} from "./Layers/NatureReserves";
import {Natuurpunt} from "./Layouts/Natuurpunt"; import {Natuurpunt} from "./Layouts/Natuurpunt";
export class AllKnownLayouts { export class AllKnownLayouts {
public static allSets: any = AllKnownLayouts.AllLayouts(); public static allSets = AllKnownLayouts.AllLayouts();
private static AllLayouts(): any { private static AllLayouts(): Map<string, Layout> {
const all = new All(); const all = new All();
const layouts: Layout[] = [ const layouts: Layout[] = [
new Groen(), new Groen(),
@ -32,7 +32,7 @@ export class AllKnownLayouts {
new Statues(), new Statues(),
*/ */
]; ];
const allSets = {}; const allSets: Map<string, Layout> = new Map();
for (const layout of layouts) { for (const layout of layouts) {
allSets[layout.name] = layout; allSets[layout.name] = layout;
all.layers = all.layers.concat(layout.layers); all.layers = all.layers.concat(layout.layers);

View file

@ -1,13 +1,15 @@
import {LayerDefinition} from "./LayerDefinition"; import {LayerDefinition} from "./LayerDefinition";
import { UIElement } from "../UI/UIElement";
import { FixedUiElement } from "../UI/Base/FixedUiElement";
/** /**
* A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers). * A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers).
*/ */
export class Layout { export class Layout {
public name: string; public name: string;
public title: string; public title: UIElement;
public layers: LayerDefinition[]; public layers: LayerDefinition[];
public welcomeMessage: string; public welcomeMessage: UIElement;
public gettingStartedPlzLogin: string; public gettingStartedPlzLogin: string;
public welcomeBackMessage: string; public welcomeBackMessage: string;
@ -33,23 +35,23 @@ export class Layout {
*/ */
constructor( constructor(
name: string, name: string,
title: string, title: UIElement | string,
layers: LayerDefinition[], layers: LayerDefinition[],
startzoom: number, startzoom: number,
startLat: number, startLat: number,
startLon: number, startLon: number,
welcomeMessage: string, welcomeMessage: UIElement | string,
gettingStartedPlzLogin: string = "Please login to get started", gettingStartedPlzLogin: string = "Please login to get started",
welcomeBackMessage: string = "You are logged in. Welcome back!", welcomeBackMessage: string = "You are logged in. Welcome back!",
welcomeTail: string = "" welcomeTail: string = ""
) { ) {
this.title = title; this.title = typeof(title) === 'string' ? new FixedUiElement(title) : title;
this.startLon = startLon; this.startLon = startLon;
this.startLat = startLat; this.startLat = startLat;
this.startzoom = startzoom; this.startzoom = startzoom;
this.name = name; this.name = name;
this.layers = layers; this.layers = layers;
this.welcomeMessage = welcomeMessage; this.welcomeMessage = typeof(welcomeMessage) === 'string' ? new FixedUiElement(welcomeMessage) : welcomeMessage;
this.gettingStartedPlzLogin = gettingStartedPlzLogin; this.gettingStartedPlzLogin = gettingStartedPlzLogin;
this.welcomeBackMessage = welcomeBackMessage; this.welcomeBackMessage = welcomeBackMessage;
this.welcomeTail = welcomeTail; this.welcomeTail = welcomeTail;

View file

@ -2,6 +2,7 @@ import {Layout} from "../Layout";
import BikeParkings from "../Layers/BikeParkings"; import BikeParkings from "../Layers/BikeParkings";
import BikeServices from "../Layers/BikeStations"; import BikeServices from "../Layers/BikeStations";
import {GhostBike} from "../Layers/GhostBike"; import {GhostBike} from "../Layers/GhostBike";
import Translations from "../../UI/i18n/Translations";
import {DrinkingWater} from "../Layers/DrinkingWater"; import {DrinkingWater} from "../Layers/DrinkingWater";
import {BikeShop} from "../Layers/BikeShop"; import {BikeShop} from "../Layers/BikeShop";
@ -10,21 +11,14 @@ export default class Cyclofix extends Layout {
constructor() { constructor() {
super( super(
"pomp", "pomp",
"Cyclofix bicycle infrastructure", Translations.t.cylofix.title,
[new BikeServices(), new BikeShop(), new DrinkingWater(), new BikeParkings()], [new BikeServices(), new BikeShop(), new DrinkingWater(), new BikeParkings()],
16, 16,
50.8465573, 50.8465573,
4.3516970, 4.3516970,
"<h3>" + Translations.t.cylofix.title.Render() + "</h3>\n" +
"<h3>Cyclofix bicycle infrastructure</h3>\n" +
"\n" + "\n" +
"<p><b>EN&gt;</b> On this map we want to collect data about the whereabouts of bicycle pumps and public racks in Brussels." + `<p>${Translations.t.cylofix.description.Render()}</p>`
"As a result, cyclists will be able to quickly find the nearest infrastructure for their needs.</p>" +
"<p><b>NL&gt;</b> Op deze kaart willen we gegevens verzamelen over de locatie van fietspompen en openbare stelplaatsen in Brussel." +
"Hierdoor kunnen fietsers snel de dichtstbijzijnde infrastructuur vinden die voldoet aan hun behoeften.</p>" +
"<p><b>FR&gt;</b> Sur cette carte, nous voulons collecter des données sur la localisation des pompes à vélo et des supports publics à Bruxelles." +
"Les cyclistes pourront ainsi trouver rapidement l'infrastructure la plus proche de leurs besoins.</p>"
, ,
"", ""); "", "");
} }

View file

@ -36,7 +36,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
* If 'question' is undefined, then the question is never asked at all * If 'question' is undefined, then the question is never asked at all
* If the question is "" (empty string) then the question is * If the question is "" (empty string) then the question is
*/ */
question?: string, question?: UIElement | string,
/** /**
* What is the priority of the question. * What is the priority of the question.
@ -57,7 +57,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
* *
* *
*/ */
mappings?: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[], mappings?: { k: TagsFilter, txt: UIElement | string, priority?: number, substitute?: boolean }[],
/** /**

18
UI/i18n/Locale.ts Normal file
View file

@ -0,0 +1,18 @@
import { UIEventSource } from "../UIEventSource";
const LANGUAGE_KEY = 'language'
export default class Locale {
public static language: UIEventSource<string> = new UIEventSource(Locale.getInitialLanguage())
public static init() {
Locale.language.addCallback(data => {
localStorage.setItem(LANGUAGE_KEY, data)
})
}
private static getInitialLanguage() {
return localStorage.getItem(LANGUAGE_KEY)
}
}

16
UI/i18n/Translation.ts Normal file
View file

@ -0,0 +1,16 @@
import { UIElement } from "../UIElement"
import Locale from "./Locale"
export default class Translation extends UIElement{
protected InnerRender(): string {
return this.translations[Locale.language.data]
}
public readonly translations: object
constructor(translations: object) {
super(Locale.language)
this.translations = translations
}
}

18
UI/i18n/Translations.ts Normal file
View file

@ -0,0 +1,18 @@
import Translation from "./Translation";
export default class Translations {
static t = {
cylofix: {
title: new Translation({en: 'Cyclofix bicycle infrastructure', nl: 'Cyclofix fietsinfrastructuur', fr: 'TODO: FRENCH TRANSLATION'}),
description: new Translation({
en: "On this map we want to collect data about the whereabouts of bicycle pumps and public racks in Brussels." +
"As a result, cyclists will be able to quickly find the nearest infrastructure for their needs.",
nl: "Op deze kaart willen we gegevens verzamelen over de locatie van fietspompen en openbare stelplaatsen in Brussel." +
"Hierdoor kunnen fietsers snel de dichtstbijzijnde infrastructuur vinden die voldoet aan hun behoeften.",
fr: "Sur cette carte, nous voulons collecter des données sur la localisation des pompes à vélo et des supports publics à Bruxelles." +
"Les cyclistes pourront ainsi trouver rapidement l'infrastructure la plus proche de leurs besoins."
})
}
}
}

View file

@ -238,6 +238,10 @@ form {
height: 1em; height: 1em;
} }
#language-select {
pointer-events: all;
cursor: pointer;
}
#messagesbox-wrapper { #messagesbox-wrapper {
} }

View file

@ -34,6 +34,11 @@
<br/> <br/>
<div id="messagesbox-wrapper"> <div id="messagesbox-wrapper">
<div id="collapseButton"></div> <div id="collapseButton"></div>
<select id="language-select">
<option>EN</option>
<option>NL</option>
<option>FR</option>
</select>
<div id="messagesbox"></div> <div id="messagesbox"></div>
</div> </div>
</div> </div>

View file

@ -22,6 +22,10 @@ import {SearchAndGo} from "./UI/SearchAndGo";
import {CollapseButton} from "./UI/Base/CollapseButton"; import {CollapseButton} from "./UI/Base/CollapseButton";
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
import {All} from "./Customizations/Layouts/All"; 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";
// --------------------- Read the URL parameters ----------------- // --------------------- Read the URL parameters -----------------
@ -83,10 +87,13 @@ if (paramDict.test) {
dryRun = paramDict.test === "true"; dryRun = paramDict.test === "true";
} }
const layoutToUse = AllKnownLayouts.allSets[defaultLayout]; const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout];
console.log("Using layout: ", layoutToUse.name); console.log("Using layout: ", layoutToUse.name);
document.title = layoutToUse.title; document.title = layoutToUse.title.Render();
Locale.language.addCallback(e => {
document.title = layoutToUse.title.Render();
})
// ----------------- Setup a few event sources ------------- // ----------------- Setup a few event sources -------------
@ -240,7 +247,7 @@ var welcomeMessage = () => {
login = layoutToUse.welcomeBackMessage; login = layoutToUse.welcomeBackMessage;
} }
return "<div id='welcomeMessage'>" + return "<div id='welcomeMessage'>" +
layoutToUse.welcomeMessage + login + layoutToUse.welcomeTail + layoutToUse.welcomeMessage.Render() + login + layoutToUse.welcomeTail +
"</div>"; "</div>";
}), }),
function () { function () {
@ -277,3 +284,15 @@ new GeoLocationHandler(bm).AttachTo("geolocate-button");
locationControl.ping(); locationControl.ping();
messageBox.update(); messageBox.update();
// --- Locale ---
Locale.init()
window.setLanguage = function(language:string) {
Locale.language.setData(language)
}
// const eLanguageSelect = document.getElementById('language-select') as HTMLOptionElement
// eLanguageSelect.addEventListener('selectionchange')