Restructuring

This commit is contained in:
Pieter Vander Vennet 2020-07-30 00:59:08 +02:00
parent 1af27106f9
commit 5d5cf67820
27 changed files with 220 additions and 247 deletions

View file

@ -96,12 +96,12 @@ export class WelcomeMessage extends UIElement {
constructor(layout: Layout, constructor(layout: Layout,
languagePicker: UIElement, languagePicker: UIElement,
osmConnection: OsmConnection) { osmConnection: OsmConnection) {
super(osmConnection.userDetails); super(osmConnection?.userDetails);
this.languagePicker = languagePicker; this.languagePicker = languagePicker;
this.ListenTo(Locale.language); this.ListenTo(Locale.language);
this.osmConnection = osmConnection; this.osmConnection = osmConnection;
this.layout = layout; this.layout = layout;
this.userDetails = osmConnection.userDetails; this.userDetails = osmConnection?.userDetails;
this.description = layout.welcomeMessage; this.description = layout.welcomeMessage;
this.plzLogIn = layout.gettingStartedPlzLogin; this.plzLogIn = layout.gettingStartedPlzLogin;
@ -110,9 +110,15 @@ export class WelcomeMessage extends UIElement {
} }
InnerRender(): string { InnerRender(): string {
let loginStatus = "";
if (this.userDetails !== undefined) {
loginStatus = (this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render();
}
return "<span>" + return "<span>" +
this.description.Render() + this.description.Render() +
(this.userDetails.data.loggedIn ? this.welcomeBack : this.plzLogIn).Render() + loginStatus +
this.tail.Render() + this.tail.Render() +
"<br/>" + "<br/>" +
this.languagePicker.Render() + this.languagePicker.Render() +

View file

@ -1,6 +1,5 @@
import {OsmConnection} from "./Logic/OsmConnection";
import {Changes} from "./Logic/Changes";
import {UIEventSource} from "./UI/UIEventSource"; import {UIEventSource} from "./UI/UIEventSource";
import {Changes} from "./Logic/Osm/Changes";
export class Helpers { export class Helpers {

View file

@ -6,25 +6,30 @@ import {ShareScreen} from "./UI/ShareScreen";
import {FixedUiElement} from "./UI/Base/FixedUiElement"; import {FixedUiElement} from "./UI/Base/FixedUiElement";
import {CheckBox} from "./UI/Input/CheckBox"; import {CheckBox} from "./UI/Input/CheckBox";
import Combine from "./UI/Base/Combine"; import Combine from "./UI/Base/Combine";
import {OsmConnection} from "./Logic/OsmConnection";
import {Basemap} from "./Logic/Basemap";
import {UIEventSource} from "./UI/UIEventSource"; import {UIEventSource} from "./UI/UIEventSource";
import {UIElement} from "./UI/UIElement"; import {UIElement} from "./UI/UIElement";
import {MoreScreen} from "./UI/MoreScreen"; import {MoreScreen} from "./UI/MoreScreen";
import {Tag} from "./Logic/TagsFilter";
import {FilteredLayer} from "./Logic/FilteredLayer";
import {FeatureInfoBox} from "./UI/FeatureInfoBox";
import {ElementStorage} from "./Logic/ElementStorage";
import {Preset} from "./UI/SimpleAddUI";
import {Changes} from "./Logic/Osm/Changes";
import {OsmConnection} from "./Logic/Osm/OsmConnection";
import {Basemap} from "./Logic/Leaflet/Basemap";
export class InitUiElements { export class InitUiElements {
static OnlyIf(featureSwitch: UIEventSource<string>, callback: () => void) { static OnlyIf(featureSwitch: UIEventSource<boolean>, callback: () => void) {
featureSwitch.addCallback(() => { featureSwitch.addCallback(() => {
if (featureSwitch.data === "false") { if (featureSwitch.data) {
return; callback();
} }
callback();
}); });
if (featureSwitch.data !== "false") { if (featureSwitch.data) {
callback(); callback();
} }
@ -33,7 +38,9 @@ export class InitUiElements {
private static CreateWelcomePane(layoutToUse: Layout, osmConnection: OsmConnection, bm: Basemap) { private static CreateWelcomePane(layoutToUse: Layout, osmConnection: OsmConnection, bm: Basemap) {
const welcome = new WelcomeMessage(layoutToUse, Locale.CreateLanguagePicker(layoutToUse, Translations.t.general.pickLanguage), osmConnection) const welcome = new WelcomeMessage(layoutToUse,
Locale.CreateLanguagePicker(layoutToUse, Translations.t.general.pickLanguage),
osmConnection)
const fullOptions = new TabbedComponent([ const fullOptions = new TabbedComponent([
{header: `<img src='${layoutToUse.icon}'>`, content: welcome}, {header: `<img src='${layoutToUse.icon}'>`, content: welcome},
@ -77,8 +84,78 @@ export class InitUiElements {
new FixedUiElement(`<div class='collapse-button-img' class="shadow"><img src='assets/help.svg' alt='help'></div>`).onClick(() => { new FixedUiElement(`<div class='collapse-button-img' class="shadow"><img src='assets/help.svg' alt='help'></div>`).onClick(() => {
fullScreenMessage.setData(fullOptions2) fullScreenMessage.setData(fullOptions2)
}).AttachTo("help-button-mobile"); }).AttachTo("help-button-mobile");
} }
static InitLayers(layoutToUse: Layout, osmConnection: OsmConnection,
changes: Changes,
allElements: ElementStorage,
bm: Basemap,
fullScreenMessage: UIEventSource<UIElement>,
selectedElement: UIEventSource<any>): {
minZoom: number
flayers: FilteredLayer[],
presets: Preset[]
} {
const addButtons:Preset[]
= [];
const flayers: FilteredLayer[] = []
let minZoom = 0;
for (const layer of layoutToUse.layers) {
const generateInfo = (tagsES, feature) => {
return new FeatureInfoBox(
feature,
tagsES,
layer.title,
layer.elementsToShow,
changes,
osmConnection.userDetails
)
};
minZoom = Math.max(minZoom, layer.minzoom);
const flayer = FilteredLayer.fromDefinition(layer, bm, allElements, changes, osmConnection.userDetails, selectedElement, generateInfo);
for (const preset of layer.presets ?? []) {
if (preset.icon === undefined) {
const tags = {};
for (const tag of preset.tags) {
const k = tag.key;
if (typeof (k) === "string") {
tags[k] = tag.value;
}
}
preset.icon = layer.style(tags)?.icon?.iconUrl;
}
const addButton = {
name: preset.title,
description: preset.description,
icon: preset.icon,
tags: preset.tags,
layerToAddTo: flayer
}
addButtons.push(addButton);
}
flayers.push(flayer);
}
return {
minZoom: minZoom,
flayers: flayers,
presets: addButtons
}
}
} }

6
Logic/Bounds.ts Normal file
View file

@ -0,0 +1,6 @@
export interface Bounds {
north: number,
east: number,
south: number,
west: number
}

View file

@ -1,9 +1,9 @@
import {Basemap} from "./Basemap";
import {Overpass} from "./Overpass";
import {Or, TagsFilter} from "./TagsFilter"; import {Or, TagsFilter} from "./TagsFilter";
import {UIEventSource} from "../UI/UIEventSource"; import {UIEventSource} from "../UI/UIEventSource";
import {FilteredLayer} from "./FilteredLayer"; import {FilteredLayer} from "./FilteredLayer";
import {Bounds} from "./Bounds";
import {Overpass} from "./Osm/Overpass";
import {Basemap} from "./Leaflet/Basemap";
export class LayerUpdater { export class LayerUpdater {
private _map: Basemap; private _map: Basemap;
@ -14,7 +14,7 @@ export class LayerUpdater {
/** /**
* The previous bounds for which the query has been run * The previous bounds for which the query has been run
*/ */
private previousBounds: { north: number, east: number, south: number, west: number }; private previousBounds: Bounds;
private _overpass: Overpass; private _overpass: Overpass;
private _minzoom: number; private _minzoom: number;
@ -93,10 +93,21 @@ export class LayerUpdater {
if (this.runningQuery.data) { if (this.runningQuery.data) {
console.log("Still running a query, skip"); console.log("Still running a query, skip");
} }
var bbox = this.buildBboxFor();
const bounds = this._map.map.getBounds();
const diff =0.07;
const n = bounds.getNorth() + diff;
const e = bounds.getEast() + diff;
const s = bounds.getSouth() - diff;
const w = bounds.getWest() - diff;
this.previousBounds = {north: n, east: e, south: s, west: w};
this.runningQuery.setData(true); this.runningQuery.setData(true);
const self = this; const self = this;
this._overpass.queryGeoJson(bbox, this._overpass.queryGeoJson(this.previousBounds,
function (data) { function (data) {
self.handleData(data) self.handleData(data)
}, },
@ -107,19 +118,7 @@ export class LayerUpdater {
} }
private buildBboxFor(): string {
const b = this._map.map.getBounds();
const diff =0.07;
const n = b.getNorth() + diff;
const e = b.getEast() + diff;
const s = b.getSouth() - diff;
const w = b.getWest() - diff;
this.previousBounds = {north: n, east: e, south: s, west: w};
return "[bbox:" + s + "," + w + "," + n + "," + e + "]";
}
private IsInBounds(): boolean { private IsInBounds(): boolean {

View file

@ -1,6 +1,6 @@
import L from "leaflet" import L from "leaflet"
import {UIEventSource} from "../UI/UIEventSource"; import {UIEventSource} from "../../UI/UIEventSource";
import {UIElement} from "../UI/UIElement"; import {UIElement} from "../../UI/UIElement";
export class BaseLayers { export class BaseLayers {

View file

@ -1,8 +1,8 @@
import {Basemap} from "./Basemap"; import {Basemap} from "./Basemap";
import {UIEventSource} from "../UI/UIEventSource";
import {UIElement} from "../UI/UIElement";
import L from "leaflet"; import L from "leaflet";
import {Helpers} from "../Helpers"; import {UIEventSource} from "../../UI/UIEventSource";
import {UIElement} from "../../UI/UIElement";
import {Helpers} from "../../Helpers";
export class GeoLocationHandler extends UIElement { export class GeoLocationHandler extends UIElement {

View file

@ -1,7 +1,7 @@
import {Basemap} from "./Basemap"; import {Basemap} from "./Basemap";
import L from "leaflet"; import L from "leaflet";
import {UIEventSource} from "../UI/UIEventSource"; import {UIEventSource} from "../../UI/UIEventSource";
import {UIElement} from "../UI/UIElement"; import {UIElement} from "../../UI/UIElement";
/** /**
* The stray-click-hanlders adds a marker to the map if no feature was clicked. * The stray-click-hanlders adds a marker to the map if no feature was clicked.

View file

@ -2,11 +2,11 @@
* Handles all changes made to OSM. * Handles all changes made to OSM.
* Needs an authenticator via OsmConnection * Needs an authenticator via OsmConnection
*/ */
import {UIEventSource} from "../../UI/UIEventSource";
import {OsmConnection} from "./OsmConnection"; import {OsmConnection} from "./OsmConnection";
import {OsmNode, OsmObject} from "./OsmObject"; import {OsmNode, OsmObject} from "./OsmObject";
import {ElementStorage} from "./ElementStorage"; import {And, Tag, TagsFilter} from "../TagsFilter";
import {UIEventSource} from "../UI/UIEventSource"; import {ElementStorage} from "../ElementStorage";
import {And, Tag, TagsFilter} from "./TagsFilter";
export class Changes { export class Changes {
@ -261,11 +261,4 @@ console.log("Received change",key, value)
}); });
} }
public asQuestions(qs : QuestionDefinition[]){
let ls = [];
for (var i in qs){
ls.push(new Question(this, qs[i]));
}
return ls;
}
} }

View file

@ -1,7 +1,5 @@
import * as $ from "jquery" import {Basemap} from "../Leaflet/Basemap";
import {UIEventSource} from "../UI/UIEventSource"; import $ from "jquery"
import {Basemap} from "./Basemap";
export class Geocoding { export class Geocoding {
private static readonly host = "https://nominatim.openstreetmap.org/search?"; private static readonly host = "https://nominatim.openstreetmap.org/search?";

9
Logic/Osm/Notes.ts Normal file
View file

@ -0,0 +1,9 @@
import {Bounds} from "../Bounds";
export class Notes {
queryGeoJson(bounds: Bounds, continuation: ((any) => void), onFail: ((reason) => void)): void {
}
}

View file

@ -1,6 +1,6 @@
// @ts-ignore // @ts-ignore
import osmAuth from "osm-auth"; import osmAuth from "osm-auth";
import {UIEventSource} from "../UI/UIEventSource"; import {UIEventSource} from "../../UI/UIEventSource";
export class UserDetails { export class UserDetails {
@ -26,7 +26,6 @@ export class OsmConnection {
this.auth = new osmAuth({ this.auth = new osmAuth({
oauth_consumer_key: 'hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem', oauth_consumer_key: 'hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem',
oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI', oauth_secret: 'wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI',
oauth_token: oauth_token.data,
singlepage: true, singlepage: true,
landing: window.location.href, landing: window.location.href,
auto: true // show a login form if the user is not authenticated and auto: true // show a login form if the user is not authenticated and

View file

@ -1,11 +1,11 @@
/** /**
* Helps in uplaoding, by generating the rigth title, decription and by adding the tag to the changeset * Helps in uplaoding, by generating the rigth title, decription and by adding the tag to the changeset
*/ */
import {UIEventSource} from "../UI/UIEventSource";
import {ImageUploadFlow} from "../UI/ImageUploadFlow";
import {Changes} from "./Changes"; import {Changes} from "./Changes";
import {UIEventSource} from "../../UI/UIEventSource";
import {ImageUploadFlow} from "../../UI/ImageUploadFlow";
import {UserDetails} from "./OsmConnection"; import {UserDetails} from "./OsmConnection";
import {SlideShow} from "../UI/SlideShow"; import {SlideShow} from "../../UI/SlideShow";
export class OsmImageUploadHandler { export class OsmImageUploadHandler {
private _tags: UIEventSource<any>; private _tags: UIEventSource<any>;

View file

@ -1,11 +1,11 @@
import {TagsFilter} from "./TagsFilter";
import * as OsmToGeoJson from "osmtogeojson";
import * as $ from "jquery";
/** /**
* Interfaces overpass to get all the latest data * Interfaces overpass to get all the latest data
*/ */
import {Bounds} from "../Bounds";
import {TagsFilter} from "../TagsFilter";
import $ from "jquery"
import * as OsmToGeoJson from "osmtogeojson";
export class Overpass { export class Overpass {
private _filter: TagsFilter private _filter: TagsFilter
public static testUrl: string = null public static testUrl: string = null
@ -14,7 +14,8 @@ export class Overpass {
this._filter = filter this._filter = filter
} }
public buildQuery(bbox: string): string {
private buildQuery(bbox: string): string {
const filters = this._filter.asOverpass() const filters = this._filter.asOverpass()
let filter = "" let filter = ""
for (const filterOr of filters) { for (const filterOr of filters) {
@ -24,9 +25,10 @@ export class Overpass {
'[out:json][timeout:25]' + bbox + ';(' + filter + ');out body;>;out skel qt;' '[out:json][timeout:25]' + bbox + ';(' + filter + ');out body;>;out skel qt;'
return "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query) return "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query)
} }
queryGeoJson(bbox: string, continuation: ((any) => void), onFail: ((reason) => void)): void { queryGeoJson(bounds: Bounds, continuation: ((any) => void), onFail: ((reason) => void)): void {
let query = this.buildQuery(bbox)
let query = this.buildQuery( "[bbox:" + bounds.south + "," + bounds.west + "," + bounds.north + "," + bounds.east + "]")
if(Overpass.testUrl !== null){ if(Overpass.testUrl !== null){
console.log("Using testing URL") console.log("Using testing URL")

View file

@ -55,8 +55,8 @@ export class Regex extends TagsFilter {
export class Tag extends TagsFilter { export class Tag extends TagsFilter {
public key: string | RegExp public key: string
public value: string | RegExp public value: string
public invertValue: boolean public invertValue: boolean
constructor(key: string | RegExp, value: string | RegExp, invertValue = false) { constructor(key: string | RegExp, value: string | RegExp, invertValue = false) {
@ -69,7 +69,9 @@ export class Tag extends TagsFilter {
} }
super() super()
// @ts-ignore
this.key = key this.key = key
// @ts-ignore
this.value = value this.value = value
this.invertValue = invertValue this.invertValue = invertValue
} }
@ -107,10 +109,14 @@ export class Tag extends TagsFilter {
} }
asOverpass(): string[] { asOverpass(): string[] {
// @ts-ignore
const keyIsRegex = this.key instanceof RegExp const keyIsRegex = this.key instanceof RegExp
// @ts-ignore
const key = keyIsRegex ? (this.key as RegExp).source : this.key const key = keyIsRegex ? (this.key as RegExp).source : this.key
// @ts-ignore
const valIsRegex = this.value instanceof RegExp const valIsRegex = this.value instanceof RegExp
// @ts-ignore
const val = valIsRegex ? (this.value as RegExp).source : this.value const val = valIsRegex ? (this.value as RegExp).source : this.value
const regexKeyPrefix = keyIsRegex ? '~' : '' const regexKeyPrefix = keyIsRegex ? '~' : ''

View file

@ -1,10 +1,6 @@
import {UIElement} from "./UIElement"; import {UIElement} from "./UIElement";
import {UIEventSource} from "./UIEventSource"; import {UIEventSource} from "./UIEventSource";
import {QuestionPicker} from "./QuestionPicker";
import {OsmImageUploadHandler} from "../Logic/OsmImageUploadHandler";
import {ImageCarousel} from "./Image/ImageCarousel"; import {ImageCarousel} from "./Image/ImageCarousel";
import {Changes} from "../Logic/Changes";
import {UserDetails} from "../Logic/OsmConnection";
import {VerticalCombine} from "./Base/VerticalCombine"; import {VerticalCombine} from "./Base/VerticalCombine";
import {TagRenderingOptions} from "../Customizations/TagRendering"; import {TagRenderingOptions} from "../Customizations/TagRendering";
import {OsmLink} from "../Customizations/Questions/OsmLink"; import {OsmLink} from "../Customizations/Questions/OsmLink";
@ -12,6 +8,8 @@ import {WikipediaLink} from "../Customizations/Questions/WikipediaLink";
import {And} from "../Logic/TagsFilter"; import {And} from "../Logic/TagsFilter";
import {TagDependantUIElement, TagDependantUIElementConstructor} from "../Customizations/UIElementConstructor"; import {TagDependantUIElement, TagDependantUIElementConstructor} from "../Customizations/UIElementConstructor";
import Translations from "./i18n/Translations"; import Translations from "./i18n/Translations";
import {Changes} from "../Logic/Osm/Changes";
import {UserDetails} from "../Logic/Osm/OsmConnection";
export class FeatureInfoBox extends UIElement { export class FeatureInfoBox extends UIElement {
@ -33,7 +31,6 @@ export class FeatureInfoBox extends UIElement {
private _infoboxes: TagDependantUIElement[]; private _infoboxes: TagDependantUIElement[];
private _questions: QuestionPicker;
private _oneSkipped = Translations.t.general.oneSkippedQuestion.Clone(); private _oneSkipped = Translations.t.general.oneSkippedQuestion.Clone();
private _someSkipped = Translations.t.general.skippedQuestions.Clone(); private _someSkipped = Translations.t.general.skippedQuestions.Clone();

View file

@ -4,11 +4,11 @@ import {UIEventSource} from "../UIEventSource";
import {SlideShow} from "../SlideShow"; import {SlideShow} from "../SlideShow";
import {FixedUiElement} from "../Base/FixedUiElement"; import {FixedUiElement} from "../Base/FixedUiElement";
import {VerticalCombine} from "../Base/VerticalCombine"; import {VerticalCombine} from "../Base/VerticalCombine";
import {Changes} from "../../Logic/Changes";
import {VariableUiElement} from "../Base/VariableUIElement"; import {VariableUiElement} from "../Base/VariableUIElement";
import {ConfirmDialog} from "../ConfirmDialog"; import {ConfirmDialog} from "../ConfirmDialog";
import {UserDetails} from "../../Logic/OsmConnection";
import {TagDependantUIElement, TagDependantUIElementConstructor} from "../../Customizations/UIElementConstructor"; import {TagDependantUIElement, TagDependantUIElementConstructor} from "../../Customizations/UIElementConstructor";
import {Changes} from "../../Logic/Osm/Changes";
import {UserDetails} from "../../Logic/Osm/OsmConnection";
export class ImageCarouselConstructor implements TagDependantUIElementConstructor{ export class ImageCarouselConstructor implements TagDependantUIElementConstructor{
IsKnown(properties: any): boolean { IsKnown(properties: any): boolean {

View file

@ -1,10 +1,9 @@
import {TagDependantUIElement, TagDependantUIElementConstructor} from "../../Customizations/UIElementConstructor"; import {TagDependantUIElement, TagDependantUIElementConstructor} from "../../Customizations/UIElementConstructor";
import {ImageCarousel} from "./ImageCarousel"; import {ImageCarousel} from "./ImageCarousel";
import {OsmImageUploadHandler} from "../../Logic/OsmImageUploadHandler";
import {UIEventSource} from "../UIEventSource"; import {UIEventSource} from "../UIEventSource";
import {Changes} from "../../Logic/Changes";
import {UserDetails} from "../../Logic/OsmConnection";
import {ImageUploadFlow} from "../ImageUploadFlow"; import {ImageUploadFlow} from "../ImageUploadFlow";
import {Changes} from "../../Logic/Osm/Changes";
import {OsmImageUploadHandler} from "../../Logic/Osm/OsmImageUploadHandler";
export class ImageCarouselWithUploadConstructor implements TagDependantUIElementConstructor{ export class ImageCarouselWithUploadConstructor implements TagDependantUIElementConstructor{
IsKnown(properties: any): boolean { IsKnown(properties: any): boolean {

View file

@ -1,6 +1,6 @@
import {UIElement} from "./UIElement"; import {UIElement} from "./UIElement";
import {UIEventSource} from "./UIEventSource"; import {UIEventSource} from "./UIEventSource";
import {Changes} from "../Logic/Changes"; import {Changes} from "../Logic/Osm/Changes";
export class PendingChanges extends UIElement { export class PendingChanges extends UIElement {
private _pendingChangesCount: UIEventSource<number>; private _pendingChangesCount: UIEventSource<number>;

View file

@ -1,47 +0,0 @@
import {UIElement} from "./UIElement";
import {Question} from "../Logic/Question";
import {UIEventSource} from "./UIEventSource";
export class QuestionPicker extends UIElement {
private readonly _questions: Question[];
private readonly tags: any;
private source: UIEventSource<any>;
constructor(questions: Question[],
tags: UIEventSource<any>) {
super(tags);
this._questions = questions;
this.tags = tags.data;
this.source = tags;
}
protected InnerRender(): string {
let t = this.tags;
let highestPriority = Number.MIN_VALUE;
let highestQ: Question;
for (const q of this._questions) {
if (!q.Applicable(t)) {
continue;
}
const priority = q.question.severity;
if (priority > highestPriority) {
highestPriority = priority;
highestQ = q;
}
}
if (highestQ === undefined) {
return "Er zijn geen vragen meer!";
}
return "<div class='question'>" +
highestQ.CreateHtml(this.source).Render() +
"</div>";
}
}

View file

@ -1,13 +1,13 @@
import {UIElement} from "./UIElement";
import {TextField} from "./Input/TextField";
import {UIEventSource} from "./UIEventSource";
import {FixedUiElement} from "./Base/FixedUiElement";
import {Geocoding} from "../Logic/Geocoding";
import {Basemap} from "../Logic/Basemap";
import {VariableUiElement} from "./Base/VariableUIElement";
import Translation from "./i18n/Translation";
import Locale from "./i18n/Locale"; import Locale from "./i18n/Locale";
import {UIEventSource} from "./UIEventSource";
import {UIElement} from "./UIElement";
import Translation from "./i18n/Translation";
import {VariableUiElement} from "./Base/VariableUIElement";
import {FixedUiElement} from "./Base/FixedUiElement";
import {TextField} from "./Input/TextField";
import {Geocoding} from "../Logic/Osm/Geocoding";
import Translations from "./i18n/Translations"; import Translations from "./i18n/Translations";
import {Basemap} from "../Logic/Leaflet/Basemap";
export class SearchAndGo extends UIElement { export class SearchAndGo extends UIElement {

View file

@ -2,17 +2,17 @@ import {UIElement} from "./UIElement";
import {UIEventSource} from "./UIEventSource"; import {UIEventSource} from "./UIEventSource";
import {Tag} from "../Logic/TagsFilter"; import {Tag} from "../Logic/TagsFilter";
import {FilteredLayer} from "../Logic/FilteredLayer"; import {FilteredLayer} from "../Logic/FilteredLayer";
import {Changes} from "../Logic/Changes";
import {FixedUiElement} from "./Base/FixedUiElement"; import {FixedUiElement} from "./Base/FixedUiElement";
import {Button} from "./Base/Button"; import {Button} from "./Base/Button";
import {UserDetails} from "../Logic/OsmConnection";
import Translations from "./i18n/Translations"; import Translations from "./i18n/Translations";
import Combine from "./Base/Combine"; import Combine from "./Base/Combine";
import {SubtleButton} from "./Base/SubtleButton"; import {SubtleButton} from "./Base/SubtleButton";
import {VerticalCombine} from "./Base/VerticalCombine"; import {VerticalCombine} from "./Base/VerticalCombine";
import Locale from "./i18n/Locale"; import Locale from "./i18n/Locale";
import {Changes} from "../Logic/Osm/Changes";
import {UserDetails} from "../Logic/Osm/OsmConnection";
interface Preset { export interface Preset {
description: string | UIElement, description: string | UIElement,
name: string | UIElement, name: string | UIElement,
icon: string, icon: string,
@ -133,6 +133,11 @@ export class SimpleAddUI extends UIElement {
let header: UIElement = Translations.t.general.add.header; let header: UIElement = Translations.t.general.add.header;
if(this._userDetails === undefined){
return header.Render();
}
if (!this._userDetails.data.loggedIn) { if (!this._userDetails.data.loggedIn) {
return new Combine([header, Translations.t.general.add.pleaseLogin]).Render() return new Combine([header, Translations.t.general.add.pleaseLogin]).Render()
} }

View file

@ -1,11 +1,11 @@
import {UIElement} from "./UIElement"; import {UIElement} from "./UIElement";
import {UserDetails} from "../Logic/OsmConnection";
import {UIEventSource} from "./UIEventSource"; import {UIEventSource} from "./UIEventSource";
import {Basemap} from "../Logic/Basemap";
import L from "leaflet"; import L from "leaflet";
import {FixedUiElement} from "./Base/FixedUiElement"; import {FixedUiElement} from "./Base/FixedUiElement";
import {VariableUiElement} from "./Base/VariableUIElement"; import {VariableUiElement} from "./Base/VariableUIElement";
import Translations from "./i18n/Translations"; import Translations from "./i18n/Translations";
import {UserDetails} from "../Logic/Osm/OsmConnection";
import {Basemap} from "../Logic/Leaflet/Basemap";
/** /**
* Handles and updates the user badge * Handles and updates the user badge

View file

@ -136,12 +136,12 @@ export default class Translations {
}), }),
yes: new T({ yes: new T({
en: "This parking has room for cargo bikes", en: "This parking has room for cargo bikes",
nl: "Deze parking is overdekt (er is een afdak)", nl: "Deze parking heeft plaats voor bakfietsen",
fr: "TODO: fr" fr: "TODO: fr"
}), }),
designated: new T({ designated: new T({
en: "This parking has designated (official) spots for cargo bikes.", en: "This parking has designated (official) spots for cargo bikes.",
nl: "Deze parking is overdekt (er is een afdak)", nl: "Er zijn speciale plaatsen voorzien voor bakfietsen",
fr: "TODO: fr" fr: "TODO: fr"
}), }),
no: new T({ no: new T({

109
index.ts
View file

@ -1,20 +1,14 @@
import {OsmConnection} from "./Logic/OsmConnection";
import {Changes} from "./Logic/Changes";
import {ElementStorage} from "./Logic/ElementStorage"; import {ElementStorage} from "./Logic/ElementStorage";
import {UIEventSource} from "./UI/UIEventSource"; import {UIEventSource} from "./UI/UIEventSource";
import {UserBadge} from "./UI/UserBadge"; import {UserBadge} from "./UI/UserBadge";
import {Basemap, BaseLayers} from "./Logic/Basemap";
import {PendingChanges} from "./UI/PendingChanges"; import {PendingChanges} from "./UI/PendingChanges";
import {CenterMessageBox} from "./UI/CenterMessageBox"; import {CenterMessageBox} from "./UI/CenterMessageBox";
import {Helpers} from "./Helpers"; import {Helpers} from "./Helpers";
import {Tag, TagUtils} from "./Logic/TagsFilter"; import {TagUtils} from "./Logic/TagsFilter";
import {FilteredLayer} from "./Logic/FilteredLayer";
import {LayerUpdater} from "./Logic/LayerUpdater"; import {LayerUpdater} from "./Logic/LayerUpdater";
import {UIElement} from "./UI/UIElement"; import {UIElement} from "./UI/UIElement";
import {FullScreenMessageBoxHandler} from "./UI/FullScreenMessageBoxHandler"; import {FullScreenMessageBoxHandler} from "./UI/FullScreenMessageBoxHandler";
import {FeatureInfoBox} from "./UI/FeatureInfoBox"; import {FeatureInfoBox} from "./UI/FeatureInfoBox";
import {GeoLocationHandler} from "./Logic/GeoLocationHandler";
import {StrayClickHandler} from "./Logic/StrayClickHandler";
import {SimpleAddUI} from "./UI/SimpleAddUI"; import {SimpleAddUI} from "./UI/SimpleAddUI";
import {VariableUiElement} from "./UI/Base/VariableUIElement"; import {VariableUiElement} from "./UI/Base/VariableUIElement";
import {SearchAndGo} from "./UI/SearchAndGo"; import {SearchAndGo} from "./UI/SearchAndGo";
@ -22,7 +16,7 @@ import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
import {CheckBox} from "./UI/Input/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} from "./Customizations/Layout";
import {DropDown} from "./UI/Input/DropDown"; import {DropDown} from "./UI/Input/DropDown";
import {FixedUiElement} from "./UI/Base/FixedUiElement"; import {FixedUiElement} from "./UI/Base/FixedUiElement";
import {LayerSelection} from "./UI/LayerSelection"; import {LayerSelection} from "./UI/LayerSelection";
@ -31,10 +25,12 @@ import {Img} from "./UI/Img";
import {QueryParameters} from "./Logic/QueryParameters"; import {QueryParameters} from "./Logic/QueryParameters";
import {Utils} from "./Utils"; import {Utils} from "./Utils";
import {LocalStorageSource} from "./Logic/LocalStorageSource"; import {LocalStorageSource} from "./Logic/LocalStorageSource";
import {Button} from "./UI/Base/Button";
import {TabbedComponent} from "./UI/Base/TabbedComponent";
import {ShareScreen} from "./UI/ShareScreen";
import {InitUiElements} from "./InitUiElements"; import {InitUiElements} from "./InitUiElements";
import {StrayClickHandler} from "./Logic/Leaflet/StrayClickHandler";
import {BaseLayers, Basemap} from "./Logic/Leaflet/Basemap";
import {GeoLocationHandler} from "./Logic/Leaflet/GeoLocationHandler";
import {OsmConnection} from "./Logic/Osm/OsmConnection";
import {Changes} from "./Logic/Osm/Changes";
// --------------------- Special actions based on the parameters ----------------- // --------------------- Special actions based on the parameters -----------------
@ -112,12 +108,18 @@ const lat = QueryParameters.GetQueryParameter("lat", undefined)
const lon = QueryParameters.GetQueryParameter("lon", undefined) const lon = QueryParameters.GetQueryParameter("lon", undefined)
.syncWith(LocalStorageSource.Get("lon")); .syncWith(LocalStorageSource.Get("lon"));
const featureSwitchUserbadge = QueryParameters.GetQueryParameter("fs-userbadge", ""+layoutToUse.enableUserBadge); function featSw(key: string, deflt: boolean): UIEventSource<boolean> {
const featureSwitchSearch = QueryParameters.GetQueryParameter("fs-search", ""+layoutToUse.enableSearch); return QueryParameters.GetQueryParameter("fs-userbadge", "" + deflt).map((str) => {
const featureSwitchWelcomeMessage = QueryParameters.GetQueryParameter("fs-welcome-message", "true"); return str !== "false";
const featureSwitchLayers = QueryParameters.GetQueryParameter("fs-layers", ""+layoutToUse.enableLayers); });
const featureSwitchAddNew = QueryParameters.GetQueryParameter("fs-add-new", ""+layoutToUse.enableAdd); }
const featureSwitchIframe = QueryParameters.GetQueryParameter("fs-iframe", "false");
const featureSwitchUserbadge = featSw("fs-userbadge", layoutToUse.enableUserBadge);
const featureSwitchSearch = featSw("fs-search", layoutToUse.enableSearch);
const featureSwitchLayers = featSw("fs-layers", layoutToUse.enableLayers);
const featureSwitchAddNew = featSw("fs-add-new", layoutToUse.enableAdd);
const featureSwitchWelcomeMessage = featSw("fs-welcome-message", true);
const featureSwitchIframe = featSw("fs-iframe", false);
const locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({ const locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({
@ -148,8 +150,8 @@ window.setLanguage = function (language: string) {
} }
Locale.language.addCallback((currentLanguage) => { Locale.language.addCallback((currentLanguage) => {
console.log("REsetting languate to", layoutToUse.supportedLanguages[0])
if (layoutToUse.supportedLanguages.indexOf(currentLanguage) < 0) { if (layoutToUse.supportedLanguages.indexOf(currentLanguage) < 0) {
console.log("Resetting languate to", layoutToUse.supportedLanguages[0], "as", currentLanguage, " is unsupported")
// The current language is not supported -> switch to a supported one // The current language is not supported -> switch to a supported one
Locale.language.setData(layoutToUse.supportedLanguages[0]); Locale.language.setData(layoutToUse.supportedLanguages[0]);
} }
@ -181,63 +183,10 @@ const bm = new Basemap("leafletDiv", locationControl, new VariableUiElement(
// ------------- Setup the layers ------------------------------- // ------------- Setup the layers -------------------------------
const addButtons: {
name: string | UIElement,
description: string | UIElement,
icon: string,
tags: Tag[],
layerToAddTo: FilteredLayer
}[]
= [];
const flayers: FilteredLayer[] = [] const layerSetup = InitUiElements.InitLayers(layoutToUse, osmConnection, changes, allElements, bm, fullScreenMessage, selectedElement);
let minZoom = 0; const layerUpdater = new LayerUpdater(bm, layerSetup.minZoom, layerSetup.flayers);
for (const layer of layoutToUse.layers) {
const generateInfo = (tagsES, feature) => {
return new FeatureInfoBox(
feature,
tagsES,
layer.title,
layer.elementsToShow,
changes,
osmConnection.userDetails
)
};
minZoom = Math.max(minZoom, layer.minzoom);
const flayer = FilteredLayer.fromDefinition(layer, bm, allElements, changes, osmConnection.userDetails, selectedElement, generateInfo);
for (const preset of layer.presets ?? []) {
if (preset.icon === undefined) {
const tags = {};
for (const tag of preset.tags) {
const k = tag.key;
if (typeof (k) === "string") {
tags[k] = tag.value;
}
}
preset.icon = layer.style(tags)?.icon?.iconUrl;
}
const addButton = {
name: preset.title,
description: preset.description,
icon: preset.icon,
tags: preset.tags,
layerToAddTo: flayer
}
addButtons.push(addButton);
}
flayers.push(flayer);
}
const layerUpdater = new LayerUpdater(bm, minZoom, flayers);
// --------------- Setting up layer selection ui -------- // --------------- Setting up layer selection ui --------
@ -249,9 +198,9 @@ const openFilterButton = `
let baseLayerOptions = BaseLayers.baseLayers.map((layer) => {return {value: layer, shown: layer.name}}); let baseLayerOptions = BaseLayers.baseLayers.map((layer) => {return {value: layer, shown: layer.name}});
const backgroundMapPicker = new Combine([new DropDown(`Background map`, baseLayerOptions, bm.CurrentLayer), openFilterButton]); const backgroundMapPicker = new Combine([new DropDown(`Background map`, baseLayerOptions, bm.CurrentLayer), openFilterButton]);
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(layerSetup.flayers)]);
let layerControl = backgroundMapPicker; let layerControl = backgroundMapPicker;
if (flayers.length > 1) { if (layerSetup.flayers.length > 1) {
layerControl = new Combine([layerSelection, backgroundMapPicker]); layerControl = new Combine([layerSelection, backgroundMapPicker]);
} }
@ -283,7 +232,7 @@ InitUiElements.OnlyIf(featureSwitchAddNew, () => {
selectedElement, selectedElement,
layerUpdater.runningQuery, layerUpdater.runningQuery,
osmConnection.userDetails, osmConnection.userDetails,
addButtons); layerSetup.presets);
} }
); );
}); });
@ -342,17 +291,17 @@ new FullScreenMessageBoxHandler(fullScreenMessage, () => {
}).update(); }).update();
InitUiElements.OnlyIf(featureSwitchWelcomeMessage, () => { InitUiElements.OnlyIf(featureSwitchWelcomeMessage, () => {
InitUiElements.InitWelcomeMessage(layoutToUse, osmConnection, bm, fullScreenMessage) InitUiElements.InitWelcomeMessage(layoutToUse,
featureSwitchUserbadge.data ? osmConnection : undefined, bm, fullScreenMessage)
}); });
if ((window != window.top && featureSwitchWelcomeMessage.data === "false") || featureSwitchIframe.data !== "false") { if ((window != window.top && !featureSwitchWelcomeMessage.data) || featureSwitchIframe.data) {
console.log("WELCOME? ",featureSwitchWelcomeMessage.data)
new FixedUiElement(`<a href='${window.location}' target='_blank'><span class='iframe-escape'><img src='assets/pop-out.svg'></span></a>`).AttachTo("top-right") new FixedUiElement(`<a href='${window.location}' target='_blank'><span class='iframe-escape'><img src='assets/pop-out.svg'></span></a>`).AttachTo("top-right")
} }
new CenterMessageBox( new CenterMessageBox(
minZoom, layerSetup.minZoom,
centerMessage, centerMessage,
osmConnection, osmConnection,
locationControl, locationControl,

24
test.ts
View file

@ -1,24 +0,0 @@
import {FeatureInfoBox} from "./UI/FeatureInfoBox";
import {TagRenderingOptions} from "./Customizations/TagRendering";
import {Changes} from "./Logic/Changes";
import {UIEventSource} from "./UI/UIEventSource";
import {OsmConnection} from "./Logic/OsmConnection";
import {ElementStorage} from "./Logic/ElementStorage";
import {Tag} from "./Logic/TagsFilter";
import FixedText from "./Customizations/Questions/FixedText";
import {FixedUiElement} from "./UI/Base/FixedUiElement";
const osm = new OsmConnection(true);
const changes = new Changes("test", osm, new ElementStorage());
const tags = new UIEventSource<any>({name: "<b>ESCAPEE <h3>"});
const x = new TagRenderingOptions(
{
mappings: [
{k: null, txt: "Test: {name}"}
]
}
);
new FeatureInfoBox(undefined, tags, new FixedText(new FixedUiElement("{name}")), [x], changes, osm.userDetails)
.AttachTo("maindiv");