Cleanup of code
This commit is contained in:
parent
dd91e11bd0
commit
e0f9a93468
12 changed files with 193 additions and 369 deletions
|
@ -96,13 +96,11 @@ export class WelcomeMessage extends UIElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
InnerRender(): string {
|
InnerRender(): string {
|
||||||
return "<div id='welcomeMessage'>" +
|
return "<span id='welcomeMessage'>" +
|
||||||
this.description.Render() +
|
this.description.Render() +
|
||||||
"<br/>"+
|
|
||||||
(this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render() +
|
(this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render() +
|
||||||
"<br/>"+
|
|
||||||
this.tail.Render() +
|
this.tail.Render() +
|
||||||
"</div>"
|
"</span>"
|
||||||
|
|
||||||
;
|
;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -41,6 +41,7 @@ export class LayerUpdater {
|
||||||
map.Location.addCallback(function () {
|
map.Location.addCallback(function () {
|
||||||
self.update();
|
self.update();
|
||||||
});
|
});
|
||||||
|
self.update();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
76
Quests.ts
76
Quests.ts
|
@ -1,76 +0,0 @@
|
||||||
import {QuestionDefinition} from "./Logic/Question";
|
|
||||||
|
|
||||||
|
|
||||||
export class Quests {
|
|
||||||
|
|
||||||
|
|
||||||
static hasFee = QuestionDefinition.radioQuestionSimple("Moet men betalen om deze toiletten te gebruiken?", 10,
|
|
||||||
"fee",
|
|
||||||
[{text: "ja", value: "yes"}, {text: "nee", value: "no"}]
|
|
||||||
);
|
|
||||||
|
|
||||||
static toiletsWheelChairs = QuestionDefinition.radioQuestionSimple("Zijn deze toiletten rolstoeltoegankelijk?", 20,
|
|
||||||
"wheelchair",
|
|
||||||
[{text: "ja", value: "yes"}, {text: "nee", value: "no"}]
|
|
||||||
).addUnrequiredTag("toilets:position", "urinals");
|
|
||||||
|
|
||||||
static toiletsChangingTable = QuestionDefinition.radioQuestionSimple("Is er een luiertafel beschikbaar?", 20,
|
|
||||||
"changing_table",
|
|
||||||
[{text: "ja", value: "yes"}, {text: "nee", value: "no"}]
|
|
||||||
)
|
|
||||||
// Urinals are often a pitlatrine/something very poor where no changing table is
|
|
||||||
.addUnrequiredTag("toilets:position", "urinals").addUnrequiredTag("toilets:position", "urinal");
|
|
||||||
|
|
||||||
static toiletsChangingTableLocation = QuestionDefinition.radioAndTextQuestion("Waar bevindt de luiertafel zich?", 5,
|
|
||||||
"changing_table",
|
|
||||||
[{text: "In de vrouwentoiletten", value: "female_toilet"},
|
|
||||||
{text: "In de mannentoiletten", value: "male_toilet"},
|
|
||||||
{text: "In de rolstoeltoegangkelijke toiletten", value: "wheelchair_toilet"},
|
|
||||||
{text: "In de aparte, speciaal voorziene ruimte", value: "dedicated_room"},
|
|
||||||
{text: "In de genderneutrale toiletten", value: "unisex_toilet"}]
|
|
||||||
)
|
|
||||||
.addRequiredTag("changing_table", "yes");
|
|
||||||
|
|
||||||
|
|
||||||
static toiletsPosition = QuestionDefinition.radioQuestionSimple("Wat voor toiletten zijn dit?", 1,
|
|
||||||
"toilets:position",
|
|
||||||
[{text: "Enkel urinoirs", value: "urinals"},
|
|
||||||
{text: "Enkel 'gewone' toiletten waar men op gaat zitten", value: "seated"},
|
|
||||||
{text: "Er zijn zowel urinoirs als zittoiletten", value: "seated;urinals"}]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static accessNatureReserve = QuestionDefinition.radioQuestionSimple(
|
|
||||||
"Is dit gebied toegankelijk voor het publiek?",
|
|
||||||
10,
|
|
||||||
"access",
|
|
||||||
[
|
|
||||||
{text: "Nee, dit is afgesloten", value: "no"},
|
|
||||||
{text: "Nee, dit is een privaat terrein", value: "no"},
|
|
||||||
{text: "Hoewel het een privebos is, kan men er toch in", value: "permissive"},
|
|
||||||
{text: "Enkel tijdens activiteiten of met een gids", value: "guided"},
|
|
||||||
{text: "Ja, het is gewoon toegankelijk", value: "yes"}
|
|
||||||
]
|
|
||||||
).addUnrequiredTag("seamark:type", "restricted_area");
|
|
||||||
|
|
||||||
static nameOf(name: string) : QuestionDefinition {
|
|
||||||
return QuestionDefinition.noNameOrNameQuestion("<b>Wat is de <i>officiële</i> naam van dit " + name + "?</b><br />" +
|
|
||||||
"Veel gebieden hebben geen naam. Duid dit dan ook zo aan.",
|
|
||||||
"Dit " + name + " heeft geen naam", 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
static operator =
|
|
||||||
QuestionDefinition.radioAndTextQuestion(
|
|
||||||
"Wie is de beheerder van dit gebied?",
|
|
||||||
1,
|
|
||||||
"operator",
|
|
||||||
[{text: "Natuurpunt", value: "Natuurpunt"},
|
|
||||||
{text: "Het Agenschap voor Natuur en Bos", value: "Agentschap Natuur en Bos"},
|
|
||||||
{text: "Een prive-eigenaar", value: "private"}
|
|
||||||
]
|
|
||||||
).addUnrequiredTag("access", "private")
|
|
||||||
.addUnrequiredTag("access", "no");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
148
UI/AddButton.ts
148
UI/AddButton.ts
|
@ -1,148 +0,0 @@
|
||||||
import {UIEventSource} from "./UIEventSource";
|
|
||||||
import {UIElement} from "./UIElement";
|
|
||||||
import {Basemap} from "../Logic/Basemap";
|
|
||||||
import {Changes} from "../Logic/Changes";
|
|
||||||
import L from "leaflet";
|
|
||||||
import {Tag} from "../Logic/TagsFilter";
|
|
||||||
import {FilteredLayer} from "../Logic/FilteredLayer";
|
|
||||||
|
|
||||||
export class AddButton extends UIElement {
|
|
||||||
|
|
||||||
public curentAddSelection: UIEventSource<string> = new UIEventSource<string>("");
|
|
||||||
private zoomlevel: UIEventSource<{ zoom: number }>;
|
|
||||||
|
|
||||||
private readonly SELECTING_POI = "selecting_POI";
|
|
||||||
private readonly PLACING_POI = "placing_POI";
|
|
||||||
|
|
||||||
private changes: Changes;
|
|
||||||
|
|
||||||
/*State is one of:
|
|
||||||
* "": the default stated
|
|
||||||
* "select_POI": show a 'select which POI to add' query (skipped if only one option exists)
|
|
||||||
* "placing_point": shown while adding a point
|
|
||||||
* ""
|
|
||||||
*/
|
|
||||||
private state: UIEventSource<string> = new UIEventSource<string>("");
|
|
||||||
private _options: { name: string; icon: string; tags: Tag[]; layerToAddTo: FilteredLayer }[];
|
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
basemap: Basemap,
|
|
||||||
changes: Changes,
|
|
||||||
options: {
|
|
||||||
name: string,
|
|
||||||
icon: string,
|
|
||||||
tags: Tag[],
|
|
||||||
layerToAddTo: FilteredLayer
|
|
||||||
}[]) {
|
|
||||||
super(undefined);
|
|
||||||
|
|
||||||
this.zoomlevel = basemap.Location;
|
|
||||||
this.ListenTo(this.zoomlevel);
|
|
||||||
this._options = options;
|
|
||||||
this.ListenTo(this.curentAddSelection);
|
|
||||||
this.ListenTo(this.state);
|
|
||||||
this.state.setData(this.SELECTING_POI);
|
|
||||||
this.changes = changes;
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
|
|
||||||
basemap.map.on("click", function (e) {
|
|
||||||
const location = e.latlng;
|
|
||||||
console.log("Clicked at ", location)
|
|
||||||
self.HandleClick(location.lat, location.lng)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
basemap.map.on("mousemove", function(){
|
|
||||||
if (self.state.data === self.PLACING_POI) {
|
|
||||||
|
|
||||||
let icon = "crosshair";
|
|
||||||
for (const option of self._options) {
|
|
||||||
if (option.name === self.curentAddSelection.data && option.icon !== undefined) {
|
|
||||||
icon = 'url("' + option.icon + '") 32 32 ,crosshair';
|
|
||||||
console.log("Cursor icon: ", icon)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.getElementById('leafletDiv').style.cursor = icon;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// @ts-ignore
|
|
||||||
document.getElementById('leafletDiv').style.cursor = '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private HandleClick(lat: number, lon: number): void {
|
|
||||||
this.state.setData(this.SELECTING_POI);
|
|
||||||
console.log("Handling click", lat, lon, this.curentAddSelection.data);
|
|
||||||
for (const option of this._options) {
|
|
||||||
if (this.curentAddSelection.data === option.name) {
|
|
||||||
console.log("PLACING a ", option);
|
|
||||||
|
|
||||||
let feature = this.changes.createElement(option.tags, lat, lon);
|
|
||||||
option.layerToAddTo.AddNewElement(feature);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected InnerRender(): string {
|
|
||||||
|
|
||||||
if (this.zoomlevel.data.zoom < 19) {
|
|
||||||
return "Zoom in om een punt toe te voegen"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.data === this.SELECTING_POI) {
|
|
||||||
var html = "<form>";
|
|
||||||
for (const option of this._options) {
|
|
||||||
// <button type='button'> looks SO retarded
|
|
||||||
// the default type of button is 'submit', which performs a POST and page reload
|
|
||||||
html += "<button type='button' class='addPOIoption' value='" + option.name + "'>Voeg een " + option.name + " toe</button><br/>";
|
|
||||||
}
|
|
||||||
html += "</form>";
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.data === this.PLACING_POI) {
|
|
||||||
return "<div id='clickOnMapInstruction'>Klik op de kaart om een nieuw punt toe te voegen<div>" +
|
|
||||||
"<div id='cancelInstruction'>Klik hier om toevoegen te annuleren</div>"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.curentAddSelection.data === "") {
|
|
||||||
return "<span onclick>Voeg een punt toe...</span>"
|
|
||||||
}
|
|
||||||
return "Annuleer";
|
|
||||||
}
|
|
||||||
|
|
||||||
InnerUpdate(htmlElement: HTMLElement) {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
htmlElement.onclick = function (event) {
|
|
||||||
// @ts-ignore
|
|
||||||
if(event.consumed){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (self.state.data === self.PLACING_POI) {
|
|
||||||
self.state.setData(self.SELECTING_POI);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const buttons = htmlElement.getElementsByClassName('addPOIoption');
|
|
||||||
// @ts-ignore
|
|
||||||
for (const button of buttons) {
|
|
||||||
button.onclick = function (event) {
|
|
||||||
self.curentAddSelection.setData(button.value);
|
|
||||||
self.state.setData(self.PLACING_POI);
|
|
||||||
event.consumed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
import {UIElement} from "../UIElement";
|
|
||||||
import {UIEventSource} from "../UIEventSource";
|
|
||||||
|
|
||||||
|
|
||||||
export class CollapseButton extends UIElement {
|
|
||||||
public isCollapsed = new UIEventSource(false);
|
|
||||||
|
|
||||||
constructor(idToCollapse: string) {
|
|
||||||
super(undefined);
|
|
||||||
this.ListenTo(this.isCollapsed);
|
|
||||||
this.isCollapsed.addCallback((collapse) => {
|
|
||||||
const el = document.getElementById(idToCollapse);
|
|
||||||
if (el === undefined || el === null) {
|
|
||||||
console.log("Element not found")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (collapse) {
|
|
||||||
el.style.height = "3.5em";
|
|
||||||
el.style.width = "15em";
|
|
||||||
} else {
|
|
||||||
el.style.height = "auto";
|
|
||||||
el.style.width = "auto";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
this.onClick(() => {
|
|
||||||
self.isCollapsed.setData(!self.isCollapsed.data);
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected InnerRender(): string {
|
|
||||||
const up = './assets/arrow-up.svg';
|
|
||||||
const down = './assets/arrow-down.svg';
|
|
||||||
let arrow = up;
|
|
||||||
if (this.isCollapsed.data) {
|
|
||||||
arrow = down;
|
|
||||||
}
|
|
||||||
return `<img class='collapse-button' src='${arrow}' alt='collapse'>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -2,6 +2,7 @@ import {UIElement} from "../UIElement";
|
||||||
import {UIEventSource} from "../UIEventSource";
|
import {UIEventSource} from "../UIEventSource";
|
||||||
import { FilteredLayer } from "../../Logic/FilteredLayer";
|
import { FilteredLayer } from "../../Logic/FilteredLayer";
|
||||||
import Translations from "../../UI/i18n/Translations";
|
import Translations from "../../UI/i18n/Translations";
|
||||||
|
import instantiate = WebAssembly.instantiate;
|
||||||
|
|
||||||
|
|
||||||
export class CheckBox extends UIElement{
|
export class CheckBox extends UIElement{
|
||||||
|
@ -11,9 +12,10 @@ export class CheckBox extends UIElement{
|
||||||
private readonly _showEnabled: string|UIElement;
|
private readonly _showEnabled: string|UIElement;
|
||||||
private readonly _showDisabled: string|UIElement;
|
private readonly _showDisabled: string|UIElement;
|
||||||
|
|
||||||
constructor(showEnabled: string|UIElement, showDisabled: string|UIElement, data: UIEventSource<boolean> = undefined) {
|
constructor(showEnabled: string | UIElement, showDisabled: string | UIElement, data: UIEventSource<boolean> | boolean = false) {
|
||||||
super(undefined);
|
super(undefined);
|
||||||
this._data = data ?? new UIEventSource<boolean>(false);
|
this._data =
|
||||||
|
data instanceof UIEventSource ? data : new UIEventSource(data ?? false);
|
||||||
this.ListenTo(this._data);
|
this.ListenTo(this._data);
|
||||||
this._showEnabled = showEnabled;
|
this._showEnabled = showEnabled;
|
||||||
this._showDisabled = showDisabled;
|
this._showDisabled = showDisabled;
|
|
@ -1,6 +1,6 @@
|
||||||
import { UIElement } from "./UIElement";
|
import { UIElement } from "./UIElement";
|
||||||
import { FilteredLayer } from "../Logic/FilteredLayer";
|
import { FilteredLayer } from "../Logic/FilteredLayer";
|
||||||
import { CheckBox } from "./Base/CheckBox";
|
import { CheckBox } from "./Input/CheckBox";
|
||||||
import Combine from "./Base/Combine";
|
import Combine from "./Base/Combine";
|
||||||
|
|
||||||
export class LayerSelection extends UIElement{
|
export class LayerSelection extends UIElement{
|
||||||
|
|
17
Utils.ts
Normal file
17
Utils.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
export class Utils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives a clean float, or undefined if parsing fails
|
||||||
|
* @param str
|
||||||
|
*/
|
||||||
|
static asFloat(str): number {
|
||||||
|
if (str) {
|
||||||
|
const i = parseFloat(str);
|
||||||
|
if (isNaN(i)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
71
assets/help.svg
Normal file
71
assets/help.svg
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<?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"
|
||||||
|
version="1.0"
|
||||||
|
width="900"
|
||||||
|
height="900"
|
||||||
|
id="svg11382"
|
||||||
|
sodipodi:docname="help.svg"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||||
|
<metadata
|
||||||
|
id="metadata10">
|
||||||
|
<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>
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
id="namedview8"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
inkscape:zoom="0.26767309"
|
||||||
|
inkscape:cx="339.73914"
|
||||||
|
inkscape:cy="440.83624"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg11382" />
|
||||||
|
<defs
|
||||||
|
id="defs11384" />
|
||||||
|
<g
|
||||||
|
transform="matrix(0.90103258,0,0,0.90103258,112.84058,-1.9060177)"
|
||||||
|
id="layer1">
|
||||||
|
<g
|
||||||
|
id="g11476">
|
||||||
|
<path
|
||||||
|
d="M 474.50888,718.22841 H 303.49547 v -22.30134 c -2.4e-4,-37.95108 4.30352,-68.76211 12.9113,-92.43319 8.60728,-23.67032 23.63352,-45.28695 40.65324,-64.84996 17.01914,-19.56211 41.98734,-26.33264 101.45793,-75.63085 31.69095,-25.82203 55.2813,-77.1523 55.28175,-98.67174 2.21232,-56.92245 -13.93983,-79.3422 -34.56287,-99.96524 -22.67355,-19.67717 -60.67027,-30.06998 -90.99892,-30.06998 -27.77921,6.9e-4 -68.46735,8.08871 -87.7666,25.37047 -25.93817,17.28308 -65.23747,73.70611 -57.04687,130.54577 l -194.516943,1.70222 c 0,-157.21399 29.393699,-198.69465 99.004113,-263.03032 67.39739,-54.376643 126.53128,-73.268365 243.84757,-73.268365 89.71791,0 161.89728,17.80281 214.32552,53.405855 71.20714,48.12472 122.30105,111.18354 122.30105,230.11281 -6.9e-4,44.32081 -19.15253,90.78638 -43.0726,128.33299 -18.38947,30.90938 -60.37511,66.45236 -118.21237,104.41628 -42.83607,25.7686 -66.67196,53.11926 -77.03964,72.0946 -10.36863,18.97603 -15.55271,43.72267 -15.55225,74.23999 z"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:1201.92492676px;font-family:'Bitstream Vera Sans';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
id="path11472"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
d="m 482.38298,869.80902 a 94.042557,73.021278 0 1 1 -188.08511,0 94.042557,73.021278 0 1 1 188.08511,0 z"
|
||||||
|
transform="translate(1.106383,-5.5319149)"
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path11474"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
74
index.css
74
index.css
|
@ -101,7 +101,7 @@ form {
|
||||||
|
|
||||||
|
|
||||||
#usertext {
|
#usertext {
|
||||||
width: auto;
|
width: max-content;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
padding: 0.9em;
|
padding: 0.9em;
|
||||||
|
@ -225,7 +225,7 @@ form {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-height: 600px) {
|
@media only screen and (max-height: 300px) {
|
||||||
/* Landscape */
|
/* Landscape */
|
||||||
#userbadge-and-search {
|
#userbadge-and-search {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -267,44 +267,58 @@ form {
|
||||||
display: none; /*Only shown on small screens*/
|
display: none; /*Only shown on small screens*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#welcomeMessage {
|
.collapse-button {
|
||||||
max-width: 35em;
|
|
||||||
padding: 0;
|
|
||||||
padding-top: 1em;
|
|
||||||
padding-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#collapseButton {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 1em;
|
background-color: #e5f5ff;
|
||||||
background-color: white;
|
width: 3.5em;
|
||||||
margin: 1.5em;
|
border-top-left-radius: 2em;
|
||||||
border: 2px solid black;
|
border-bottom-left-radius: 2em;
|
||||||
border-radius: 2em;
|
|
||||||
padding: 0.5em;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 1em;
|
height:calc(100% - 8em);
|
||||||
height: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#collapseButton img {
|
.collapse-button .collapse-button-img{
|
||||||
width: 1em;
|
background-color: #e5f5ff;
|
||||||
height: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e
|
.open-button {
|
||||||
#messagesbox-wrapper {
|
width: 2em;
|
||||||
|
border-top-left-radius: 2em;
|
||||||
|
border-bottom-left-radius: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collapse-button-img {
|
||||||
|
border-radius: 50%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 1em;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse-button-img img{
|
||||||
|
width: 1.5em;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcomeMessage {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: white;
|
||||||
|
padding: 1em;
|
||||||
|
margin-left: 3.5em;
|
||||||
|
padding-left: 1em;
|
||||||
|
padding-bottom: 2em;
|
||||||
|
border-radius: 2em;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 25vw;
|
||||||
|
}
|
||||||
|
|
||||||
#messagesbox {
|
#messagesbox {
|
||||||
/*Only shown on big screens*/
|
/*Only shown on big screens*/
|
||||||
padding: 2em;
|
padding: 0;
|
||||||
padding-top: 1em;
|
|
||||||
padding-bottom: 1em;
|
|
||||||
z-index: 5000;
|
|
||||||
background-color: white;
|
|
||||||
border-radius: 2em;
|
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +419,7 @@ e
|
||||||
border-radius: 15px 15px 0 0;
|
border-radius: 15px 15px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@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: 300px) {
|
||||||
#messagesbox-wrapper {
|
#messagesbox-wrapper {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,8 @@
|
||||||
<div id="searchbox"></div>
|
<div id="searchbox"></div>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
<div id="messagesbox-wrapper">
|
|
||||||
<div id="collapseButton"></div>
|
|
||||||
<div id="messagesbox"></div>
|
<div id="messagesbox"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="filter__popup" class="filter__popup">
|
<div id="filter__popup" class="filter__popup">
|
||||||
<div id="filter__selection"></div>
|
<div id="filter__selection"></div>
|
||||||
|
|
93
index.ts
93
index.ts
|
@ -20,7 +20,7 @@ import {VariableUiElement} from "./UI/Base/VariableUIElement";
|
||||||
import {SearchAndGo} from "./UI/SearchAndGo";
|
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 {CheckBox} from "./UI/Base/CheckBox";
|
import {CheckBox} from "./UI/Input/CheckBox";
|
||||||
import Translations from "./UI/i18n/Translations";
|
import Translations from "./UI/i18n/Translations";
|
||||||
import Locale from "./UI/i18n/Locale";
|
import Locale from "./UI/i18n/Locale";
|
||||||
import {Layout, WelcomeMessage} from "./Customizations/Layout";
|
import {Layout, WelcomeMessage} from "./Customizations/Layout";
|
||||||
|
@ -30,9 +30,10 @@ import {LayerSelection} from "./UI/LayerSelection";
|
||||||
import Combine from "./UI/Base/Combine";
|
import Combine from "./UI/Base/Combine";
|
||||||
import {Img} from "./UI/Img";
|
import {Img} from "./UI/Img";
|
||||||
import {QueryParameters} from "./Logic/QueryParameters";
|
import {QueryParameters} from "./Logic/QueryParameters";
|
||||||
|
import {Utils} from "./Utils";
|
||||||
|
|
||||||
|
|
||||||
// --------------------- Read the URL parameters -----------------
|
// --------------------- Special actions based on the parameters -----------------
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (location.href.startsWith("http://buurtnatuur.be")) {
|
if (location.href.startsWith("http://buurtnatuur.be")) {
|
||||||
|
@ -40,13 +41,11 @@ if (location.href.startsWith("http://buurtnatuur.be")) {
|
||||||
window.location.replace("https://buurtnatuur.be");
|
window.location.replace("https://buurtnatuur.be");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let dryRun = false;
|
|
||||||
|
|
||||||
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
|
||||||
dryRun = true;
|
const testing = QueryParameters.GetQueryParameter("test");
|
||||||
|
testing.setData((testing.data === undefined) + "")
|
||||||
// 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
|
||||||
//Overpass.testUrl = "http://127.0.0.1:8080/streetwidths.geojson";
|
//Overpass.testUrl = "http://127.0.0.1:8080/streetwidths.geojson";
|
||||||
|
@ -55,7 +54,6 @@ if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
|
||||||
|
|
||||||
// ----------------- SELECT THE RIGHT QUESTSET -----------------
|
// ----------------- SELECT THE RIGHT QUESTSET -----------------
|
||||||
|
|
||||||
|
|
||||||
let defaultLayout = "walkbybrussels"
|
let defaultLayout = "walkbybrussels"
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,16 +72,10 @@ for (const k in AllKnownLayouts.allSets) {
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultLayout = QueryParameters.GetQueryParameter("layout").data ?? defaultLayout;
|
defaultLayout = QueryParameters.GetQueryParameter("layout").data ?? defaultLayout;
|
||||||
dryRun = QueryParameters.GetQueryParameter("test").data === "true";
|
|
||||||
|
|
||||||
const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout];
|
const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout] ?? AllKnownLayouts["all"];
|
||||||
console.log("Using layout: ", layoutToUse.name);
|
console.log("Using layout: ", layoutToUse.name);
|
||||||
|
|
||||||
document.title = layoutToUse.title.InnerRender();
|
|
||||||
Locale.language.addCallback(e => {
|
|
||||||
document.title = layoutToUse.title.InnerRender();
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------- Setup a few event sources -------------
|
// ----------------- Setup a few event sources -------------
|
||||||
|
|
||||||
|
@ -102,31 +94,19 @@ const fullScreenMessage = new UIEventSource<UIElement>(undefined);
|
||||||
// The latest element that was selected - used to generate the right UI at the right place
|
// The latest element that was selected - used to generate the right UI at the right place
|
||||||
const selectedElement = new UIEventSource<{ feature: any }>(undefined);
|
const selectedElement = new UIEventSource<{ feature: any }>(undefined);
|
||||||
|
|
||||||
|
|
||||||
function clean(str) : number{
|
|
||||||
if (str) {
|
|
||||||
const i = parseFloat(str);
|
|
||||||
if (isNaN(i)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const zoom = QueryParameters.GetQueryParameter("z");
|
const zoom = QueryParameters.GetQueryParameter("z");
|
||||||
const lat = QueryParameters.GetQueryParameter("lat");
|
const lat = QueryParameters.GetQueryParameter("lat");
|
||||||
const lon = QueryParameters.GetQueryParameter("lon");
|
const lon = QueryParameters.GetQueryParameter("lon");
|
||||||
|
|
||||||
|
|
||||||
const locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({
|
const locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({
|
||||||
zoom: clean(zoom.data) ?? layoutToUse.startzoom,
|
zoom: Utils.asFloat(zoom.data) ?? layoutToUse.startzoom,
|
||||||
lat: clean(lat.data) ?? layoutToUse.startLat,
|
lat: Utils.asFloat(lat.data) ?? layoutToUse.startLat,
|
||||||
lon: clean(lon.data) ?? layoutToUse.startLon
|
lon: Utils.asFloat(lon.data) ?? layoutToUse.startLon
|
||||||
});
|
});
|
||||||
|
|
||||||
locationControl.addCallback((latlonz) => {
|
locationControl.addCallback((latlonz) => {
|
||||||
zoom.setData(latlonz.zoom.toString());
|
zoom.setData(latlonz.zoom.toString());
|
||||||
|
|
||||||
lat.setData(latlonz.lat.toString().substr(0,6));
|
lat.setData(latlonz.lat.toString().substr(0,6));
|
||||||
lon.setData(latlonz.lon.toString().substr(0,6));
|
lon.setData(latlonz.lon.toString().substr(0,6));
|
||||||
})
|
})
|
||||||
|
@ -134,7 +114,9 @@ locationControl.addCallback((latlonz) => {
|
||||||
|
|
||||||
// ----------------- Prepare the important objects -----------------
|
// ----------------- Prepare the important objects -----------------
|
||||||
|
|
||||||
const osmConnection = new OsmConnection(dryRun);
|
const osmConnection = new OsmConnection(
|
||||||
|
QueryParameters.GetQueryParameter("test").data === "true"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
Locale.language.syncWith(osmConnection.GetPreference("language"));
|
Locale.language.syncWith(osmConnection.GetPreference("language"));
|
||||||
|
@ -212,7 +194,7 @@ for (const layer of layoutToUse.layers) {
|
||||||
const layerUpdater = new LayerUpdater(bm, minZoom, flayers);
|
const layerUpdater = new LayerUpdater(bm, minZoom, flayers);
|
||||||
|
|
||||||
|
|
||||||
// --------------- Setting up filter ui --------
|
// --------------- Setting up layer selection ui --------
|
||||||
|
|
||||||
const closedFilterButton = `<button id="filter__button" class="filter__button filter__button--shadow">${Img.closedFilterButton}</button>`;
|
const closedFilterButton = `<button id="filter__button" class="filter__button filter__button--shadow">${Img.closedFilterButton}</button>`;
|
||||||
|
|
||||||
|
@ -229,13 +211,23 @@ const backgroundMapPicker = new Combine([new DropDown(`Background map`, baseLaye
|
||||||
const layerSelection = new Combine([`<p class="filter__label">Maplayers</p>`, new LayerSelection(flayers)]);
|
const layerSelection = new Combine([`<p class="filter__label">Maplayers</p>`, new LayerSelection(flayers)]);
|
||||||
let layerControl = backgroundMapPicker;
|
let layerControl = backgroundMapPicker;
|
||||||
if (flayers.length > 1) {
|
if (flayers.length > 1) {
|
||||||
layerControl = new Combine([layerSelection, backgroundMapPicker);
|
layerControl = new Combine([layerSelection, backgroundMapPicker]);
|
||||||
}
|
}
|
||||||
|
|
||||||
new CheckBox(layerControl, closedFilterButton).AttachTo("filter__selection");
|
new CheckBox(layerControl, closedFilterButton).AttachTo("filter__selection");
|
||||||
|
|
||||||
|
|
||||||
// ------------------ Setup various UI elements ------------
|
// ------------------ Setup various other UI elements ------------
|
||||||
|
|
||||||
|
document.title = layoutToUse.title.InnerRender();
|
||||||
|
|
||||||
|
Locale.language.addCallback(e => {
|
||||||
|
document.title = layoutToUse.title.InnerRender();
|
||||||
|
})
|
||||||
|
let languagePicker = new DropDown("", layoutToUse.supportedLanguages.map(lang => {
|
||||||
|
return {value: lang, shown: lang}
|
||||||
|
}
|
||||||
|
), Locale.language);
|
||||||
|
|
||||||
|
|
||||||
new StrayClickHandler(bm, selectedElement, fullScreenMessage, () => {
|
new StrayClickHandler(bm, selectedElement, fullScreenMessage, () => {
|
||||||
|
@ -250,7 +242,8 @@ new StrayClickHandler(bm, selectedElement, fullScreenMessage, () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the questions and information for the selected element on the fullScreen
|
* Show the questions and information for the selected element
|
||||||
|
* This is given to the div which renders fullscreen on mobile devices
|
||||||
*/
|
*/
|
||||||
selectedElement.addCallback((feature) => {
|
selectedElement.addCallback((feature) => {
|
||||||
const data = feature.feature.properties;
|
const data = feature.feature.properties;
|
||||||
|
@ -278,13 +271,7 @@ selectedElement.addCallback((feature) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const pendingChanges = new PendingChanges(
|
const pendingChanges = new PendingChanges(changes, secondsTillChangesAreSaved,);
|
||||||
changes, secondsTillChangesAreSaved,);
|
|
||||||
|
|
||||||
let languagePicker = new DropDown("", layoutToUse.supportedLanguages.map(lang => {
|
|
||||||
return {value: lang, shown: lang}
|
|
||||||
}
|
|
||||||
), Locale.language);
|
|
||||||
|
|
||||||
new UserBadge(osmConnection.userDetails,
|
new UserBadge(osmConnection.userDetails,
|
||||||
pendingChanges,
|
pendingChanges,
|
||||||
|
@ -294,12 +281,20 @@ new UserBadge(osmConnection.userDetails,
|
||||||
|
|
||||||
new SearchAndGo(bm).AttachTo("searchbox");
|
new SearchAndGo(bm).AttachTo("searchbox");
|
||||||
|
|
||||||
|
/*
|
||||||
new CollapseButton("messagesbox")
|
new CollapseButton("messagesbox")
|
||||||
.AttachTo("collapseButton");
|
.AttachTo("collapseButton");*/
|
||||||
new WelcomeMessage(layoutToUse, osmConnection).AttachTo("messagesbox");
|
const welcome = new WelcomeMessage(layoutToUse, osmConnection).onClick(() => {
|
||||||
fullScreenMessage.setData(
|
});
|
||||||
new WelcomeMessage(layoutToUse, osmConnection)
|
|
||||||
);
|
const help = new FixedUiElement(`<div class='collapse-button-img'><img src='assets/help.svg' alt='collapse'></div>`);
|
||||||
|
new CheckBox(
|
||||||
|
new Combine([
|
||||||
|
new Combine(["<span class='collapse-button'>", help, "</span>"]),
|
||||||
|
welcome]),
|
||||||
|
new Combine(["<span class='open-button'>", help, "</span>"])
|
||||||
|
, true
|
||||||
|
).AttachTo("messagesbox")
|
||||||
|
|
||||||
|
|
||||||
new FullScreenMessageBoxHandler(fullScreenMessage, () => {
|
new FullScreenMessageBoxHandler(fullScreenMessage, () => {
|
||||||
|
@ -324,9 +319,5 @@ osmConnection.registerActivateOsmAUthenticationClass();
|
||||||
new GeoLocationHandler(bm).AttachTo("geolocate-button");
|
new GeoLocationHandler(bm).AttachTo("geolocate-button");
|
||||||
|
|
||||||
|
|
||||||
// --------------- Send a ping to start various action --------
|
|
||||||
|
|
||||||
locationControl.ping();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue