diff --git a/Customizations/AllKnownLayouts.ts b/Customizations/AllKnownLayouts.ts index 68173c8..9a8728e 100644 --- a/Customizations/AllKnownLayouts.ts +++ b/Customizations/AllKnownLayouts.ts @@ -5,13 +5,14 @@ import {Statues} from "./Layouts/Statues"; import {Bookcases} from "./Layouts/Bookcases"; import Cyclofix from "./Layouts/Cyclofix"; import {All} from "./Layouts/All"; +import {Layout} from "./Layout"; export class AllKnownLayouts { public static allSets: any = AllKnownLayouts.AllLayouts(); - private static AllLayouts() { + private static AllLayouts() : any{ const all = new All(); - const layouts = [ + const layouts : Layout[] = [ new Groen(), new GRB(), new Cyclofix(), diff --git a/Customizations/LayerDefinition.ts b/Customizations/LayerDefinition.ts index 03822e3..14f9b40 100644 --- a/Customizations/LayerDefinition.ts +++ b/Customizations/LayerDefinition.ts @@ -16,9 +16,35 @@ export class LayerDefinition { * This name is shown in the 'add XXX button' */ name: string; + /** + * These tags are added whenever a new point is added by the user on the map. + * This is the ideal place to add extra info, such as "fixme=added by MapComplete, geometry should be checked" + */ newElementTags: Tag[] + /** + * Not really used anymore + * This is meant to serve as icon in the buttons + */ icon: string; + /** + * Only show this layer starting at this zoom level + */ minzoom: number; + + /** + * This tagfilter is used to query overpass. + * Examples are: + * + * new Tag("amenity","drinking_water") + * + * or a query for bicycle pumps which have two tagging schemes: + * new Or([ + * new Tag("service:bicycle:pump","yes") , + * new And([ + * new Tag("amenity","compressed_air"), + * new Tag("bicycle","yes")]) + * ]) + */ overpassFilter: TagsFilter; /** diff --git a/Customizations/Layers/BikeParkings.ts b/Customizations/Layers/BikeParkings.ts index 205ca33..edc6a26 100644 --- a/Customizations/Layers/BikeParkings.ts +++ b/Customizations/Layers/BikeParkings.ts @@ -2,8 +2,9 @@ import {LayerDefinition} from "../LayerDefinition"; import {And, Or, Tag} from "../../Logic/TagsFilter"; import {OperatorTag} from "../Questions/OperatorTag"; import * as L from "leaflet"; -import FixedName from "../Questions/FixedName"; +import FixedText from "../Questions/FixedText"; import { BikeParkingType } from "../Questions/BikeParkingType"; +import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload"; export class BikeParkings extends LayerDefinition { @@ -19,8 +20,9 @@ export class BikeParkings extends LayerDefinition { this.minzoom = 13; this.style = this.generateStyleFunction(); - this.title = new FixedName("Fietsparking"); + this.title = new FixedText("Fietsparking"); this.elementsToShow = [ + new ImageCarouselWithUploadConstructor(), new OperatorTag(), new BikeParkingType() ]; diff --git a/Customizations/Layers/BikeServices.ts b/Customizations/Layers/BikeServices.ts index 8c14ea5..590e249 100644 --- a/Customizations/Layers/BikeServices.ts +++ b/Customizations/Layers/BikeServices.ts @@ -1,13 +1,15 @@ import {LayerDefinition} from "../LayerDefinition"; import {And, Tag} from "../../Logic/TagsFilter"; import * as L from "leaflet"; -import FixedName from "../Questions/FixedName"; import BikeStationChain from "../Questions/BikeStationChain"; import BikeStationPumpTools from "../Questions/BikeStationPumpTools"; import BikeStationStand from "../Questions/BikeStationStand"; import PumpManual from "../Questions/PumpManual"; import BikeStationOperator from "../Questions/BikeStationOperator"; import BikeStationBrand from "../Questions/BikeStationBrand"; +import FixedText from "../Questions/FixedText"; +import {BikePumpManometer} from "../Questions/BikePumpManometer"; +import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload"; export default class BikeServices extends LayerDefinition { constructor() { @@ -27,12 +29,22 @@ export default class BikeServices extends LayerDefinition { this.minzoom = 13; this.style = this.generateStyleFunction(); - this.title = new FixedName("Bike station"); + this.title = new FixedText("Bike station"); + + const pump = new Tag("service:bicycle:pump", "yes"); + this.elementsToShow = [ + + new ImageCarouselWithUploadConstructor(), + + new BikeStationPumpTools(), new BikeStationChain().OnlyShowIf(new Tag("service:bicycle:tools", "yes")), new BikeStationStand().OnlyShowIf(new Tag("service:bicycle:tools", "yes")), - new PumpManual().OnlyShowIf(new Tag("service:bicycle:pump", "yes")), + + new PumpManual().OnlyShowIf(pump), + new BikePumpManometer().OnlyShowIf(pump), + new BikeStationOperator(), new BikeStationBrand() ]; diff --git a/Customizations/Layers/Bookcases.ts b/Customizations/Layers/Bookcases.ts index acc9d65..52e0b86 100644 --- a/Customizations/Layers/Bookcases.ts +++ b/Customizations/Layers/Bookcases.ts @@ -145,7 +145,7 @@ export class Bookcases extends LayerDefinition { new TagRenderingOptions({ freeform: { key: "description", - renderTemplate: "Beschrijving door de uitbater
{description}", + renderTemplate: "Beschrijving door de uitbater:
{description}", template: "$$$", } }) diff --git a/Customizations/Layers/Bos.ts b/Customizations/Layers/Bos.ts index b9b809c..a396550 100644 --- a/Customizations/Layers/Bos.ts +++ b/Customizations/Layers/Bos.ts @@ -7,6 +7,7 @@ import {TagRenderingOptions} from "../TagRendering"; import {NameQuestion} from "../Questions/NameQuestion"; import {NameInline} from "../Questions/NameInline"; import {DescriptionQuestion} from "../Questions/DescriptionQuestion"; +import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload"; export class Bos extends LayerDefinition { @@ -33,6 +34,7 @@ export class Bos extends LayerDefinition { this.style = this.generateStyleFunction(); this.title = new NameInline("bos"); this.elementsToShow = [ + new ImageCarouselWithUploadConstructor(), new NameQuestion(), new AccessTag(), new OperatorTag(), diff --git a/Customizations/Layers/GhostBike.ts b/Customizations/Layers/GhostBike.ts new file mode 100644 index 0000000..83a4455 --- /dev/null +++ b/Customizations/Layers/GhostBike.ts @@ -0,0 +1,69 @@ +import {LayerDefinition} from "../LayerDefinition"; +import {Tag} from "../../Logic/TagsFilter"; +import {FixedUiElement} from "../../UI/Base/FixedUiElement"; +import {TagRenderingOptions} from "../TagRendering"; +import FixedText from "../Questions/FixedText"; +import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload"; +import L from "leaflet"; + +export class GhostBike extends LayerDefinition { + constructor() { + super(); + this.name = "ghost bike"; + this.overpassFilter = new Tag("memorial", "ghost_bike") + this.title = new FixedText("Ghost bike"); + + this.elementsToShow = [ + new FixedText("A ghost bike is a memorial for a cyclist who died in a traffic accident," + + " in the form of a white bicycle placed permanently near the accident location."), + new ImageCarouselWithUploadConstructor(), + + new TagRenderingOptions({ + question: "Whom is remembered by this ghost bike?" + + "" + + "
" + + "Please respect privacy - only fill out the name if it is widely published or marked on the cycle." + + "
", + mappings: [{k: new Tag("noname", "yes"), txt: "There is no name marked on the bike"},], + freeform: { + key: "name", + extraTags: new Tag("noname", ""), + template: "$$$", + renderTemplate: "In the remembrance of {name}", + } + }), + new TagRenderingOptions({ + question: "When was the ghost bike installed?", + freeform: { + key: "start_date", + template: "The ghost bike was placed on $$$", // TODO create a date picker + renderTemplate: "The ghost bike was placed on {start_date}", + } + }), + new TagRenderingOptions({ + question: "On what URL can more information be found?" + + "If available, add a link to a news report about the accident or about the placing of the ghost bike", + freeform: { + key: "source", + template: "More information available on $$$", + renderTemplate: "More information", + } + }), + + + + ]; + + this.style = (tags: any) => { + return { + color: "#000000", + icon: L.icon({ + iconUrl: 'assets/ghost_bike.svg', + iconSize: [40, 40], + iconAnchor: [20, 20], + }) + } + }; + + } +} \ No newline at end of file diff --git a/Customizations/Layers/NatureReserves.ts b/Customizations/Layers/NatureReserves.ts index f6b1abf..5d49292 100644 --- a/Customizations/Layers/NatureReserves.ts +++ b/Customizations/Layers/NatureReserves.ts @@ -6,6 +6,7 @@ import {OperatorTag} from "../Questions/OperatorTag"; import {NameQuestion} from "../Questions/NameQuestion"; import {NameInline} from "../Questions/NameInline"; import {DescriptionQuestion} from "../Questions/DescriptionQuestion"; +import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload"; export class NatureReserves extends LayerDefinition { @@ -23,6 +24,7 @@ export class NatureReserves extends LayerDefinition { this.title = new NameInline("natuurreservaat"); this.style = this.generateStyleFunction(); this.elementsToShow = [ + new ImageCarouselWithUploadConstructor(), new NameQuestion(), new AccessTag(), new OperatorTag(), diff --git a/Customizations/Layers/Park.ts b/Customizations/Layers/Park.ts index aee1a23..e2814a7 100644 --- a/Customizations/Layers/Park.ts +++ b/Customizations/Layers/Park.ts @@ -7,6 +7,7 @@ import {TagRenderingOptions} from "../TagRendering"; import {NameQuestion} from "../Questions/NameQuestion"; import {NameInline} from "../Questions/NameInline"; import {DescriptionQuestion} from "../Questions/DescriptionQuestion"; +import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload"; export class Park extends LayerDefinition { @@ -58,6 +59,7 @@ export class Park extends LayerDefinition { this.style = this.generateStyleFunction(); this.title = new NameInline("park"); this.elementsToShow = [ + new ImageCarouselWithUploadConstructor(), new NameQuestion(), this.accessByDefault, this.operatorByDefault, diff --git a/Customizations/Layout.ts b/Customizations/Layout.ts index 9ff0e4c..7c72927 100644 --- a/Customizations/Layout.ts +++ b/Customizations/Layout.ts @@ -16,7 +16,21 @@ export class Layout { public startLat: number; public welcomeTail: string; - + public locationContains: string[]; + + /** + * + * @param name: The name used in the query string. If in the query "quests=" is defined, it will select this layout + * @param title: Will be used in the of the page + * @param layers: The layers to show, a list of LayerDefinitions + * @param startzoom: The initial starting zoom of the map + * @param startLat:The initial starting latitude of the map + * @param startLon: the initial starting longitude of the map + * @param welcomeMessage: This message is shown in the collapsable box on the left + * @param gettingStartedPlzLogin: This is shown below the welcomemessage and wrapped in a login link. + * @param welcomeBackMessage: This is shown when the user is logged in + * @param welcomeTail: This text is shown below the login message. It is ideal for extra help + */ constructor( name: string, title: string, @@ -25,8 +39,8 @@ export class Layout { startLat: number, startLon: number, welcomeMessage: string, - gettingStartedPlzLogin: string, - welcomeBackMessage: string, + gettingStartedPlzLogin: string = "Please login to get started", + welcomeBackMessage: string = "You are logged in. Welcome back!", welcomeTail: string = "" ) { this.title = title; @@ -41,13 +55,5 @@ export class Layout { this.welcomeTail = welcomeTail; } -/* - - - static statues = new Layout( - - ); - -*/ } diff --git a/Customizations/Layouts/Bookcases.ts b/Customizations/Layouts/Bookcases.ts index 7d02aab..833150b 100644 --- a/Customizations/Layouts/Bookcases.ts +++ b/Customizations/Layouts/Bookcases.ts @@ -23,5 +23,6 @@ export class Bookcases extends Layout{ " </a> of door je " + " <span onclick=\"authOsm()\" class=\"activate-osm-authentication\">aan te melden</span>.</p>", "Klik op een boekenruilkastje om vragen te beantwoorden"); + this.locationContains= ["Bookcases.html", "Bookcase.html","bookcase"] } } \ No newline at end of file diff --git a/Customizations/Layouts/Cyclofix.ts b/Customizations/Layouts/Cyclofix.ts index a3b0a2d..26b4588 100644 --- a/Customizations/Layouts/Cyclofix.ts +++ b/Customizations/Layouts/Cyclofix.ts @@ -2,13 +2,15 @@ import {Layout} from "../Layout"; import {GrbToFix} from "../Layers/GrbToFix"; import { BikeParkings } from "../Layers/BikeParkings"; import BikeServices from "../Layers/BikeServices"; +import {GhostBike} from "../Layers/GhostBike"; export default class Cyclofix extends Layout { constructor() { super( "pomp", "Cyclofix bicycle infrastructure", - [new BikeParkings(), new BikeServices()], + // [new BikePumps()], + [new GhostBike(), new BikeParkings(), new BikeServices()], 16, 50.8465573, 4.3516970, diff --git a/Customizations/Layouts/Groen.ts b/Customizations/Layouts/Groen.ts index 8e7f047..7f3d0f9 100644 --- a/Customizations/Layouts/Groen.ts +++ b/Customizations/Layouts/Groen.ts @@ -47,5 +47,7 @@ export class Groen extends Layout { "Als je inlogt, komt er een tweede cookie bij met je inloggegevens." + "</small>" ); + + this.locationContains = ["buurtnatuur.be"] } } \ No newline at end of file diff --git a/Customizations/Questions/BikePumpManometer.ts b/Customizations/Questions/BikePumpManometer.ts new file mode 100644 index 0000000..919bd5a --- /dev/null +++ b/Customizations/Questions/BikePumpManometer.ts @@ -0,0 +1,20 @@ +import {TagRenderingOptions} from "../TagRendering"; +import {Tag} from "../../Logic/TagsFilter"; + +export class BikePumpManometer extends TagRenderingOptions{ + + constructor() { + super({ + question: "Does the pump have a pressure indicator or manometer?", + mappings: [ + {k: new Tag("manometer", "yes"), txt: "Yes, there is a manometer"}, + {k: new Tag("manometer","broken"), txt: "Yes, but it is broken"}, + {k: new Tag("manometer", "yes"), txt: "No"} + ] + + }); + + } + + +} \ No newline at end of file diff --git a/Customizations/Questions/BikePumpValves.ts b/Customizations/Questions/BikePumpValves.ts new file mode 100644 index 0000000..662978a --- /dev/null +++ b/Customizations/Questions/BikePumpValves.ts @@ -0,0 +1,24 @@ +import {TagRenderingOptions} from "../TagRendering"; +import {Tag} from "../../Logic/TagsFilter"; + +export class BikePumpValves extends TagRenderingOptions{ + constructor() { + super({ + question: "What valves are supported?", + mappings: [ + { + k: new Tag("valves", " sclaverand;schrader;dunlop"), + txt: "There is a default head, so Presta, Dunlop and Auto" + }, + {k: new Tag("valves", "dunlop"), txt: "Only dunlop"}, + {k: new Tag("valves", "sclaverand"), txt: "Only Sclaverand (also known as Dunlop)"}, + {k: new Tag("valves", "auto"), txt: "Only auto"}, + ], + freeform: { + key: "valves", + template: "Supported valves are $$$", + renderTemplate: "Supported valves are {valves}" + } + }); + } +} \ No newline at end of file diff --git a/Customizations/Questions/BikeStationOperator.ts b/Customizations/Questions/BikeStationOperator.ts index a5731d6..ab205f8 100644 --- a/Customizations/Questions/BikeStationOperator.ts +++ b/Customizations/Questions/BikeStationOperator.ts @@ -15,6 +15,7 @@ export default class BikeStationOperator extends TagRenderingOptions { {k: new Tag("operator", "KU Leuven"), txt: "KU Leuven"}, {k: new Tag("operator", "Stad Halle"), txt: "Stad Halle"}, {k: new Tag("operator", "Saint Gilles - Sint Gillis"), txt: "Saint Gilles - Sint Gillis"}, + {k: new Tag("operator", "Jette"), txt: "Jette"}, {k: new Tag("operator", "private"), txt: "Beheer door een privépersoon"} ] } diff --git a/Customizations/Questions/DescriptionQuestion.ts b/Customizations/Questions/DescriptionQuestion.ts index df6f0ba..46f7263 100644 --- a/Customizations/Questions/DescriptionQuestion.ts +++ b/Customizations/Questions/DescriptionQuestion.ts @@ -7,6 +7,7 @@ export class DescriptionQuestion extends TagRenderingOptions{ super({ question: "Zijn er bijzonderheden die we moeten weten over dit "+category+"?<br>" + "<span class='question-subtext'>Je hoeft niet te herhalen wat je net hebt aangeduid.<br/>" + + "Een <i>naam</i> wordt in de volgende stap gevraagd.<br/>" + "Voel je vrij om dit veld over te slaan.</span>", freeform:{ key:"description:0", diff --git a/Customizations/Questions/FixedName.ts b/Customizations/Questions/FixedText.ts similarity index 79% rename from Customizations/Questions/FixedName.ts rename to Customizations/Questions/FixedText.ts index 0210f9c..178fb53 100644 --- a/Customizations/Questions/FixedName.ts +++ b/Customizations/Questions/FixedText.ts @@ -1,6 +1,6 @@ import { TagRenderingOptions } from "../TagRendering"; -export default class FixedName extends TagRenderingOptions { +export default class FixedText extends TagRenderingOptions { constructor(category: string) { super({ mappings: [ diff --git a/Customizations/TagRendering.ts b/Customizations/TagRendering.ts index bd99ed4..c5f8d63 100644 --- a/Customizations/TagRendering.ts +++ b/Customizations/TagRendering.ts @@ -11,6 +11,7 @@ import {UIRadioButtonWithOther} from "../UI/Base/UIRadioButtonWithOther"; import {VariableUiElement} from "../UI/Base/VariableUIElement"; import {TagDependantUIElement, TagDependantUIElementConstructor} from "./UIElementConstructor"; import {OnlyShowIfConstructor} from "./OnlyShowIf"; +import {UserDetails} from "../Logic/OsmConnection"; export class TagRenderingOptions implements TagDependantUIElementConstructor { @@ -26,11 +27,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor { constructor(options: { - /** - * What is the priority of the question. - * By default, in the popup of a feature, only one question is shown at the same time. If multiple questions are unanswered, the question with the highest priority is asked first - */ - priority?: number + /** * This is the string that is shown in the popup if this tag is missing. @@ -41,17 +38,12 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor { question?: string, /** - * Optional: - * if defined, this a common piece of tag that is shown in front of every mapping (except freeform) + * What is the priority of the question. + * By default, in the popup of a feature, only one question is shown at the same time. If multiple questions are unanswered, the question with the highest priority is asked first */ - primer?: string, - tagsPreprocessor?: ((tags: any) => any), - freeform?: { - key: string, template: string, - renderTemplate: string - placeholder?: string, - extraTags?: TagsFilter, - }, + priority?: number, + + /** * Mappings convert a well-known tag combination into a user friendly text. * It converts e.g. 'access=yes' into 'this area can be accessed' @@ -64,7 +56,33 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor { * * */ - mappings?: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[] + mappings?: { k: TagsFilter, txt: string, priority?: number, substitute?: boolean }[], + + + /** + * If one wants to render a freeform tag (thus no predefined key/values) or if there are a few well-known tags with a freeform object, + * use this. + * In the question, it'll offer a textfield + */ + freeform?: { + key: string, template: string, + renderTemplate: string + placeholder?: string, + extraTags?: TagsFilter, + }, + + + /** + * Optional: + * if defined, this a common piece of tag that is shown in front of every mapping (except freeform) + */ + primer?: string, + + /** + * In some very rare cases, tags have to be rewritten before displaying + * This function adds this + */ + tagsPreprocessor?: ((tags: any) => any) }) { this.options = options; } @@ -111,6 +129,7 @@ class TagRendering extends UIElement implements TagDependantUIElement { private _priority: number; + private _userDetails: UIEventSource<UserDetails>; Priority(): number { return this._priority; @@ -162,6 +181,9 @@ class TagRendering extends UIElement implements TagDependantUIElement { this.ListenTo(this._questionSkipped); this.ListenTo(this._editMode); + this._userDetails = changes.login.userDetails; + this.ListenTo(this._userDetails); + this._question = options.question; this._priority = options.priority ?? 0; this._primer = options.primer ?? ""; @@ -397,8 +419,14 @@ class TagRendering extends UIElement implements TagDependantUIElement { if (html == "") { return ""; } + let editButton = ""; + if(this._userDetails.data.loggedIn){ + editButton = this._editButton.Render(); + } + return "<span class='answer'>" + - "<span class='answer-text'>" + html + "</span>" + this._editButton.Render() + + "<span class='answer-text'>" + html + "</span>" + + editButton + "</span>"; } diff --git a/Logic/Changes.ts b/Logic/Changes.ts index b93e1f0..de58a76 100644 --- a/Logic/Changes.ts +++ b/Logic/Changes.ts @@ -13,7 +13,7 @@ export class Changes { private static _nextId = -1; // New assined ID's are negative - private readonly login: OsmConnection; + public readonly login: OsmConnection; public readonly _allElements: ElementStorage; private _pendingChanges: { elementId: string, key: string, value: string }[] = []; // Gets reset on uploadAll diff --git a/Logic/OsmConnection.ts b/Logic/OsmConnection.ts index 45d5bce..66a4719 100644 --- a/Logic/OsmConnection.ts +++ b/Logic/OsmConnection.ts @@ -13,7 +13,6 @@ export class UserDetails { public osmConnection: OsmConnection; public dryRun: boolean; home: { lon: number; lat: number }; - } export class OsmConnection { @@ -121,6 +120,29 @@ export class OsmConnection { } public preferences = new UIEventSource<any>({}); + public preferenceSources : any = {} + + public GetPreference(key: string) : UIEventSource<string>{ + if(this.preferenceSources[key] !== undefined){ + return this.preferenceSources[key]; + } + this.UpdatePreferences(); + console.log("Getting preference object", key, "currently upstreamed as ",this.preferences.data[key] ); + const pref = new UIEventSource<string>(this.preferences.data[key]); + pref.addCallback((v) => { + this.SetPreference(key, v); + }); + + this.preferences.addCallback((prefs) => { + if (prefs[key] !== undefined) { + pref.setData(prefs[key]); + } + }); + + this.preferenceSources[key] = pref; + return pref; + } + private UpdatePreferences() { const self = this; this.auth.xhr({ @@ -142,13 +164,14 @@ export class OsmConnection { }); } - public SetPreference(k:string, v:string) { + private SetPreference(k:string, v:string) { if(!this.userDetails.data.loggedIn){ console.log("Not saving preference: user not logged in"); return; } if (this.preferences.data[k] === v) { + console.log("Not updating preference", k, " to ", v, "not changed"); return; } console.log("Updating preference", k, " to ", v); @@ -166,7 +189,7 @@ export class OsmConnection { return; } - console.log("Preference written!", result); + console.log("Preference written!", result == "" ? "OK" : result); }); } diff --git a/README.md b/README.md index 594264c..9994bee 100644 --- a/README.md +++ b/README.md @@ -94,3 +94,6 @@ Trash icon by Dave Gandy, CC-BY-SA https://commons.wikimedia.org/wiki/File:Home-icon.svg Home icon by Timothy Miller, CC-BY-SA 3.0 + +https://commons.wikimedia.org/wiki/File:Map_icons_by_Scott_de_Jonge_-_bicycle-store.svg +Bicycle logo, Scott de Jonge \ No newline at end of file diff --git a/UI/Base/DropDownUI.ts b/UI/Base/DropDownUI.ts index 521068a..208ea85 100644 --- a/UI/Base/DropDownUI.ts +++ b/UI/Base/DropDownUI.ts @@ -41,6 +41,9 @@ export class DropDownUI extends UIElement { InnerUpdate() { const self = this; const e = document.getElementById("dropdown-" + this.id); + if(e === null){ + return; + } // @ts-ignore if (this.selectedElement.data !== e.value) { // @ts-ignore diff --git a/UI/FeatureInfoBox.ts b/UI/FeatureInfoBox.ts index b358417..2c7832c 100644 --- a/UI/FeatureInfoBox.ts +++ b/UI/FeatureInfoBox.ts @@ -15,29 +15,25 @@ import {TagDependantUIElement} from "../Customizations/UIElementConstructor"; export class FeatureInfoBox extends UIElement { private _tagsES: UIEventSource<any>; + private _changes: Changes; + private _userDetails: UIEventSource<UserDetails>; private _title: UIElement; private _osmLink: UIElement; - - - private _questions: QuestionPicker; - - private _changes: Changes; - private _userDetails: UIEventSource<UserDetails>; - private _imageElement: ImageCarousel; - private _pictureUploader: UIElement; private _wikipedialink: UIElement; - private _infoboxes: TagDependantUIElement[]; + + private _infoboxes: TagDependantUIElement[]; + private _questions: QuestionPicker; + constructor( tagsES: UIEventSource<any>, title: TagRenderingOptions, elementsToShow: TagRenderingOptions[], changes: Changes, - userDetails: UIEventSource<UserDetails>, - preferedPictureLicense: UIEventSource<string> + userDetails: UIEventSource<UserDetails> ) { super(tagsES); this._tagsES = tagsES; @@ -45,9 +41,9 @@ export class FeatureInfoBox extends UIElement { this._userDetails = userDetails; this.ListenTo(userDetails); - this._imageElement = new ImageCarousel(this._tagsES, changes); - + this._infoboxes = []; + elementsToShow = elementsToShow ?? [] for (const tagRenderingOption of elementsToShow) { this._infoboxes.push( tagRenderingOption.construct(this._tagsES, this._changes)); @@ -60,11 +56,9 @@ export class FeatureInfoBox extends UIElement { ) this._title = new TagRenderingOptions(title.options).construct(this._tagsES, this._changes); - this._osmLink =new OsmLink().construct(this._tagsES, this._changes); this._wikipedialink = new WikipediaLink().construct(this._tagsES, this._changes); - this._pictureUploader = new OsmImageUploadHandler(tagsES, userDetails, preferedPictureLicense, - changes, this._imageElement.slideshow).getUI(); + } @@ -110,10 +104,6 @@ export class FeatureInfoBox extends UIElement { "</div>" + "<div class='infoboxcontents'>" + - - this._imageElement.Render() + - this._pictureUploader.Render() + - new VerticalCombine(info, "infobox-information ").Render() + questionsHtml + @@ -126,8 +116,6 @@ export class FeatureInfoBox extends UIElement { Activate() { super.Activate(); - this._imageElement.Activate(); - this._pictureUploader.Activate(); for (const infobox of this._infoboxes) { infobox.Activate(); } @@ -135,8 +123,6 @@ export class FeatureInfoBox extends UIElement { Update() { super.Update(); - this._imageElement.Update(); - this._pictureUploader.Update(); this._title.Update(); for (const infobox of this._infoboxes) { infobox.Update(); diff --git a/UI/Image/ImageCarousel.ts b/UI/Image/ImageCarousel.ts index 82627f1..9d4e1fd 100644 --- a/UI/Image/ImageCarousel.ts +++ b/UI/Image/ImageCarousel.ts @@ -7,8 +7,30 @@ import {VerticalCombine} from "../Base/VerticalCombine"; import {Changes} from "../../Logic/Changes"; import {VariableUiElement} from "../Base/VariableUIElement"; import {ConfirmDialog} from "../ConfirmDialog"; +import {UserDetails} from "../../Logic/OsmConnection"; +import {TagDependantUIElement, TagDependantUIElementConstructor} from "../../Customizations/UIElementConstructor"; + +export class ImageCarouselConstructor implements TagDependantUIElementConstructor{ + IsKnown(properties: any): boolean { + return true; + } + + IsQuestioning(properties: any): boolean { + return false; + } + + Priority(): number { + return 0; + } + + construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement { + return new ImageCarousel(tags, changes); + } + +} + +export class ImageCarousel extends TagDependantUIElement { -export class ImageCarousel extends UIElement { private readonly searcher: ImageSearcher; @@ -18,10 +40,13 @@ export class ImageCarousel extends UIElement { private readonly _deleteButton: UIElement; private readonly _isDeleted: UIElement; + + private readonly _userDetails : UIEventSource<UserDetails>; constructor(tags: UIEventSource<any>, changes: Changes) { super(tags); - + this._userDetails = changes.login.userDetails; + const self = this; this.searcher = new ImageSearcher(tags, changes); @@ -40,8 +65,11 @@ export class ImageCarousel extends UIElement { const showDeleteButton = this.slideshow._currentSlide.map((i) => { + if(!self._userDetails.data.loggedIn){ + return false; + } return self.searcher.IsDeletable(self.searcher.data[i]); - }, [this.searcher]); + }, [this.searcher, this._userDetails]); this.slideshow._currentSlide.addCallback(() => { showDeleteButton.ping(); // This pings the showDeleteButton, which indicates that it has to hide it's subbuttons }) @@ -57,8 +85,7 @@ export class ImageCarousel extends UIElement { "<span>Afbeelding verwijderen</span>", "<span>Terug</span>", deleteCurrent, - () => { - }, + () => { }, 'delete-image-confirm', 'delete-image-cancel'); @@ -75,7 +102,6 @@ export class ImageCarousel extends UIElement { this._isDeleted = new VariableUiElement( mapping ) - // .HideOnEmpty(true); this.searcher._deletedImages.addCallback(() => { this.slideshow._currentSlide.ping(); @@ -93,6 +119,18 @@ export class ImageCarousel extends UIElement { "</span>"; } + IsKnown(): boolean { + return true; + } + + IsQuestioning(): boolean { + return false; + } + + Priority(): number { + return 0; + } + InnerUpdate(htmlElement: HTMLElement) { super.InnerUpdate(htmlElement); this._deleteButton.Update(); diff --git a/UI/Image/ImageCarouselWithUpload.ts b/UI/Image/ImageCarouselWithUpload.ts new file mode 100644 index 0000000..231044a --- /dev/null +++ b/UI/Image/ImageCarouselWithUpload.ts @@ -0,0 +1,71 @@ +import {TagDependantUIElement, TagDependantUIElementConstructor} from "../../Customizations/UIElementConstructor"; +import {ImageCarousel} from "./ImageCarousel"; +import {OsmImageUploadHandler} from "../../Logic/OsmImageUploadHandler"; +import {UIEventSource} from "../UIEventSource"; +import {Changes} from "../../Logic/Changes"; +import {UserDetails} from "../../Logic/OsmConnection"; +import {ImageUploadFlow} from "../ImageUploadFlow"; + +export class ImageCarouselWithUploadConstructor implements TagDependantUIElementConstructor{ + IsKnown(properties: any): boolean { + return true; + } + + IsQuestioning(properties: any): boolean { + return false; + } + + Priority(): number { + return 0; + } + + construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement { + return new ImageCarouselWithUpload(tags, changes); + } +} + +class ImageCarouselWithUpload extends TagDependantUIElement { + private _imageElement: ImageCarousel; + private _pictureUploader: ImageUploadFlow; + + constructor(tags: UIEventSource<any>, changes: Changes) { + super(tags); + this._imageElement = new ImageCarousel(tags, changes); + const userDetails = changes.login.userDetails; + const license = changes.login.GetPreference( "mapcomplete-pictures-license"); + this._pictureUploader = new OsmImageUploadHandler(tags, + userDetails, license, + changes, this._imageElement.slideshow).getUI(); + + } + + protected InnerRender(): string { + return this._imageElement.Render() + + this._pictureUploader.Render(); + } + + Activate() { + super.Activate(); + this._imageElement.Activate(); + this._pictureUploader.Activate(); + } + + Update() { + super.Update(); + this._imageElement.Update(); + this._pictureUploader.Update(); + } + + IsKnown(): boolean { + return true; + } + + IsQuestioning(): boolean { + return false; + } + + Priority(): number { + return 0; + } + +} \ No newline at end of file diff --git a/UI/SimpleAddUI.ts b/UI/SimpleAddUI.ts index 4deb4b3..b235437 100644 --- a/UI/SimpleAddUI.ts +++ b/UI/SimpleAddUI.ts @@ -63,6 +63,10 @@ export class SimpleAddUI extends UIElement { protected InnerRender(): string { const header = "<h2>Geen selectie</h2>" + "Je klikte ergens waar er nog geen gezochte data is.<br/>"; + if (!this._userDetails.data.loggedIn) { + return header + "<a class='activate-osm-authentication'>Gelieve je aan te melden om een nieuw punt toe te voegen</a>" + } + if (this._zoomlevel.data.zoom < 19) { return header + "Zoom verder in om een element toe te voegen."; } @@ -71,10 +75,6 @@ export class SimpleAddUI extends UIElement { return header + "De data is nog aan het laden. Nog even geduld, dan kan je een punt toevoegen"; } - if (!this._userDetails.data.loggedIn) { - return header + "<a class='activate-osm-authentication'>Gelieve je aan te melden om een nieuw punt toe te voegen</a>" - } - var html = ""; for (const button of this._addButtons) { html += button.Render(); diff --git a/assets/Buurtnatuur-Welkom.txt b/assets/Buurtnatuur-Welkom.txt new file mode 100644 index 0000000..febd369 --- /dev/null +++ b/assets/Buurtnatuur-Welkom.txt @@ -0,0 +1,20 @@ +Hallo, + +Je maakte een bijdrage aan OpenStreetMap met BuurtNatuur! Proficiat en welkom bij de community. + +Je antwoorden en toevoegingen gaan rechtsstreeks naar OpenStreetMap. OpenStreetMap is een kaart die werkt zoals Wikipedia: +het is vrij en gratis om er zelf data aan toe te voegen; in het geval van buurtnatuur.be informatie over natuur en bossen. +De data van OpenStreetMap is ook vrij en gratis te gebruiken door iedereen die dit wilt - applicaties zoals Maps.me, OsmAnd, Pokemon Go, Facebook, SnapChat, RouteYou, de Natuurpunt-app,... gebruiken OpenStreetMap. Maar ook toeristische diensten (zoals Westtoer) gebruiken steeds vaker OpenStreetMap. + +Kortom, omdat je via buurtnatuur.be info gaf over natuur en bos, wordt dit zichtbaar op ál deze kaarten. + +Heb je verdere vragen over OpenStreetMap? Wil je weten welke data we allemaal hebben en verzamelen? + +- Je kan meer lezen op [onze wiki-website](https://wiki.openstreetmap.org/wiki/NL:Hoofdpagina). +- Je kan mij een berichtje terug sturen (dit kan door een email terug te sturen) +- Je kan terecht op [online chat](https://riot.im/app/#/room/#osmbe:matrix.org) +- Je kan naar onze [bijeenkomsten komen](https://www.meetup.com/OpenStreetMap-Belgium/) + +Happy Mapping! +Pieter Vander Vennet +OpenStreetMap België diff --git a/assets/ghost_bike.svg b/assets/ghost_bike.svg new file mode 100644 index 0000000..1befcb7 --- /dev/null +++ b/assets/ghost_bike.svg @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<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="2" + width="50" + height="50" + viewBox="0 0 50 50" + id="svg4" + sodipodi:docname="ghost_bike.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> + <defs + id="defs8" /> + <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="namedview6" + showgrid="false" + inkscape:zoom="4.72" + inkscape:cx="-40.53625" + inkscape:cy="33.532739" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="background" + sodipodi:insensitive="true"> + <ellipse + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:50;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" + id="path839" + cx="25" + cy="24.894068" + rx="25" + ry="25.105932" /> + </g> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="bicycle"> + <path + d="m 37.198846,28.51624 c -0.865699,0 -1.688316,0.177789 -2.435717,0.497127 l -2.103385,-3.60434 1.58506,-2.71676 c 0.215399,-0.370622 0.09027,-0.846552 -0.279675,-1.063319 -0.162747,-0.09437 -0.343955,-0.265316 -0.515591,-0.237279 l -0.134709,-0.158644 h -3.109265 c -0.428746,0 -0.776803,0.596963 -0.776803,1.02571 0,0.429429 0.348057,1.025708 0.776803,1.025708 h 2.015176 l -0.90741,1.367611 h -9.079572 l 1.813452,-3.419029 h 0.718681 c 0.428746,0 0.776802,-0.254375 0.776802,-0.683806 0,-0.42943 -0.348056,-0.683806 -0.776802,-0.683806 h -3.886069 c -0.428061,0 -0.776803,0.254376 -0.776803,0.683806 0,0.429431 0.348057,0.683806 0.776803,0.683806 h 1.366929 l -4.368835,7.634691 c -0.748084,-0.319337 -1.572071,-0.423959 -2.437085,-0.423959 -3.432704,0 -6.2157926,2.820014 -6.2157926,6.252718 0,3.433389 2.7830886,6.234257 6.2164776,6.234257 3.433388,0 6.216478,-2.774199 6.216478,-6.207588 0,-2.010389 -0.958697,-3.788967 -2.441187,-4.926136 l 1.663699,-2.848735 4.768861,8.17558 0.01847,0.02598 0.02051,0.03077 0.01572,0.02325 0.06154,0.07111 0.0076,0.0089 0.0212,0.01915 0.02188,0.01777 0.06017,0.04787 0.0253,0.01641 0.01983,0.01298 0.0082,0.0048 0.0027,0.0027 0.06564,0.03214 0.0076,0.0033 0.01573,0.0082 0.0054,0.0014 0.04992,0.01778 0.0465,0.01505 0.0095,0.0027 0.01709,0.0027 0.03008,0.0062 0.139496,0.01436 6.84e-4,0.04239 0.0027,0.04034 h 4.712106 c 0.384299,2.735223 2.9937,5.398646 6.16314,5.398646 3.433388,0 6.216478,-2.804288 6.216478,-6.237676 6.83e-4,-3.432704 -2.782407,-6.236991 -6.215794,-6.236991 z m -17.095143,6.216477 c 0,2.575896 -2.086974,4.662872 -4.662187,4.662872 -2.575213,0 -4.662188,-2.087659 -4.662188,-4.662872 0,-2.574528 2.086975,-4.661503 4.662188,-4.661503 0.579183,0 1.131698,0.110088 1.643185,0.30361 l -2.314683,3.96744 c -0.216082,0.369938 -0.09027,0.845868 0.280362,1.063319 0.123084,0.07111 0.257794,0.10531 0.390451,0.10531 0.267369,0 0.527215,-0.13813 0.672182,-0.384984 l 2.315367,-3.970175 c 1.022972,0.855441 1.675323,2.140312 1.675323,3.576987 z m 6.216477,-1.708146 -4.086422,-7.004905 h 8.173529 z m 5.438991,-5.938853 1.664383,2.918483 c -1.286923,0.987416 -2.17587,2.169715 -2.38785,4.221133 h -3.362956 z m 2.452811,4.338747 1.634979,2.800869 H 32.60709 c 0.187363,-1.367612 0.769965,-2.102702 1.604892,-2.800869 z m 2.986864,8.01352 c -2.309212,0 -4.222501,-1.793624 -4.592439,-3.84504 h 4.590387 l 0.0033,-0.04035 0.138811,-0.03624 0.03145,-0.01572 0.129239,-0.04513 0.01436,-0.01089 0.07727,-0.03966 0.01847,-0.01436 0.06907,-0.04992 0.05334,-0.04513 0.05197,-0.05675 0.0465,-0.05813 0.03898,-0.06292 0.03556,-0.06496 0.02667,-0.07111 0.0212,-0.07111 0.01164,-0.07111 0.0089,-0.08411 0.002,-0.02394 -0.0033,-0.04377 -0.0095,-0.0848 -0.01573,-0.07248 -0.02257,-0.07111 -0.03556,-0.07726 -0.01847,-0.04035 -2.314683,-3.96744 c 0.512856,-0.193517 1.064686,-0.30361 1.643186,-0.30361 2.575896,0 4.662871,2.108172 4.662871,4.682701 6.83e-4,2.575896 -2.086975,4.684753 -4.662871,4.684753 z" + id="path2" + style="fill:#ffffff;fill-opacity:1;stroke-width:0.6838057" + inkscape:connector-curvature="0" /> + <g + id="g861" + transform="translate(-10.037321,-26.552854)"> + <path + inkscape:connector-curvature="0" + id="path842" + d="M 25.018397,35.018924 V 47.003785" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + inkscape:connector-curvature="0" + id="path842-3" + d="M 28.86857,39.213625 H 20.748791" + style="fill:none;stroke:#ffffff;stroke-width:1.64621139;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + </g> + <g + inkscape:groupmode="layer" + id="layer3" + inkscape:label="cross" /> +</svg> diff --git a/index.css b/index.css index 07cf49b..c86b574 100644 --- a/index.css +++ b/index.css @@ -573,7 +573,7 @@ form { /***************** Info box (box containing features and questions ******************/ .leaflet-popup-content { - width: 25vw !important; + width: 40em !important; } .featureinfobox { @@ -669,7 +669,6 @@ form { background-color: #e5f5ff; padding: 1em; border-radius: 1em; - margin-right: 1em; font-size: larger; } diff --git a/index.html b/index.html index e340617..16c5387 100644 --- a/index.html +++ b/index.html @@ -48,15 +48,6 @@ <script src="./index.ts"></script> <script src="vendor/Leaflet.AccuratePosition.js"></script> -<!-- 3 dagen eerste protoype --> -<!-- 19 juni: eerste feedbackronde, foto's --> -<!-- 23 juni: wikimedia foto's laden --> -<!-- 24 juni: foto's via imgur --> - -<!-- 26 restylen infobox --> -<!-- 27 restylen infobox, flow UI verbeteren, mobile, locate-me --> - -<!-- 28: user testing, fixing issues and faults, lots of small useless features, add button vs 2.0 --> <script data-goatcounter="https://pietervdvn.goatcounter.com/count" async src="//gc.zgo.at/count.js"></script> diff --git a/index.ts b/index.ts index 45fd058..6696d39 100644 --- a/index.ts +++ b/index.ts @@ -21,6 +21,7 @@ import {VariableUiElement} from "./UI/Base/VariableUIElement"; import {SearchAndGo} from "./UI/SearchAndGo"; import {CollapseButton} from "./UI/Base/CollapseButton"; import {AllKnownLayouts} from "./Customizations/AllKnownLayouts"; +import {All} from "./Customizations/Layouts/All"; @@ -49,26 +50,47 @@ if (location.hostname === "localhost" || location.hostname === "127.0.0.1") { // ----------------- SELECT THE RIGHT QUESTSET ----------------- -let defaultQuest = "buurtnatuur" +let defaultLayout = "buurtnatuur" + + +// Run over all questsets. If a part of the URL matches a searched-for part in the layout, it'll take that as the default +for (const k in AllKnownLayouts.allSets) { + const layout = AllKnownLayouts.allSets[k]; + const possibleParts = layout.locationContains ?? []; + for (const locationMatch of possibleParts) { + if (locationMatch === "") { + continue + } + if (window.location.href.toLowerCase().indexOf(locationMatch.toLowerCase()) >= 0) { + defaultLayout = layout.name; + } + } +} + +// Read the query string to grap settings +let paramDict: any = {}; if (window.location.search) { const params = window.location.search.substr(1).split("&"); - const paramDict: any = {}; for (const param of params) { var kv = param.split("="); paramDict[kv[0]] = kv[1]; } - if (paramDict.quests) { - defaultQuest = paramDict.quests - } - if(paramDict.test){ - dryRun = true; - } + + } -const questSetToRender = AllKnownLayouts.allSets[defaultQuest]; -console.log("Using quests: ", questSetToRender.name); +if (paramDict.layout) { + defaultLayout = paramDict.layout +} -document.title = questSetToRender.title; +if (paramDict.test) { + dryRun = true; +} + +const layoutToUse = AllKnownLayouts.allSets[defaultLayout]; +console.log("Using layout: ", layoutToUse.name); + +document.title = layoutToUse.title; // ----------------- Setup a few event sources ------------- @@ -84,12 +106,11 @@ const leftMessage = new UIEventSource<() => UIElement>(undefined); const selectedElement = new UIEventSource<any>(undefined); -const preferedPictureLicense = new UIEventSource<string>(undefined); const locationControl = new UIEventSource<{ lat: number, lon: number, zoom: number }>({ - zoom: questSetToRender.startzoom, - lat: questSetToRender.startLat, - lon: questSetToRender.startLon + zoom: layoutToUse.startzoom, + lat: layoutToUse.startLat, + lon: layoutToUse.startLon }); @@ -99,7 +120,7 @@ const saveTimeout = 30000; // After this many milliseconds without changes, save const allElements = new ElementStorage(); const osmConnection = new OsmConnection(dryRun); const changes = new Changes( - "Beantwoorden van vragen met #MapComplete voor vragenset #" + questSetToRender.name, + "Beantwoorden van vragen met #MapComplete voor vragenset #" + layoutToUse.name, osmConnection, allElements); const bm = new Basemap("leafletDiv", locationControl, new VariableUiElement( locationControl.map((location) => { @@ -119,21 +140,6 @@ const bm = new Basemap("leafletDiv", locationControl, new VariableUiElement( )); -// ------------- Tie together user settings and UI ----------- - - -const picturesPrefName = "mapcomplete-pictures-license"; -preferedPictureLicense.addCallback((license) => { - osmConnection.SetPreference(picturesPrefName, license); -}); - -osmConnection.preferences.addCallback((prefs) => { - if (prefs[picturesPrefName] !== undefined) { - preferedPictureLicense.setData(prefs[picturesPrefName]); - } -}) - - // ------------- Setup the layers ------------------------------- const addButtons: { @@ -148,7 +154,7 @@ const flayers: FilteredLayer[] = [] let minZoom = 0; -for (const layer of questSetToRender.layers) { +for (const layer of layoutToUse.layers) { const generateInfo = (tagsES) => { @@ -157,15 +163,13 @@ for (const layer of questSetToRender.layers) { layer.title, layer.elementsToShow, changes, - osmConnection.userDetails, - preferedPictureLicense + osmConnection.userDetails ) }; minZoom = Math.max(minZoom, layer.minzoom); - - const flayer = layer.asLayer(bm, allElements, changes, osmConnection.userDetails, selectedElement, - generateInfo); + + const flayer = layer.asLayer(bm, allElements, changes, osmConnection.userDetails, selectedElement, generateInfo); const addButton = { name: layer.name, @@ -199,7 +203,7 @@ new StrayClickHandler(bm, selectedElement, leftMessage, () => { */ selectedElement.addCallback((data) => { // Which is the applicable set? - for (const layer of questSetToRender.layers) { + for (const layer of layoutToUse.layers) { const applicable = layer.overpassFilter.matches(TagUtils.proprtiesToKV(data)); if (applicable) { @@ -210,8 +214,7 @@ selectedElement.addCallback((data) => { layer.title, layer.elementsToShow, changes, - osmConnection.userDetails, - preferedPictureLicense + osmConnection.userDetails )); break; } @@ -234,12 +237,12 @@ new CollapseButton("messagesbox") var welcomeMessage = () => { return new VariableUiElement( osmConnection.userDetails.map((userdetails) => { - var login = questSetToRender.gettingStartedPlzLogin; + var login = layoutToUse.gettingStartedPlzLogin; if (userdetails.loggedIn) { - login = questSetToRender.welcomeBackMessage; + login = layoutToUse.welcomeBackMessage; } return "<div id='welcomeMessage'>" + - questSetToRender.welcomeMessage + login + questSetToRender.welcomeTail+ + layoutToUse.welcomeMessage + login + layoutToUse.welcomeTail + "</div>"; }), function () { diff --git a/test.ts b/test.ts index d4b510f..b7e9bd3 100644 --- a/test.ts +++ b/test.ts @@ -6,4 +6,12 @@ import {WikipediaLink} from "./Customizations/Questions/WikipediaLink"; import {OsmLink} from "./Customizations/Questions/OsmLink"; import {ConfirmDialog} from "./UI/ConfirmDialog"; import {Imgur} from "./Logic/Imgur"; +import {VariableUiElement} from "./UI/Base/VariableUIElement"; + +const html = new UIEventSource<string>("Some text"); + +const uielement = new VariableUiElement(html); +uielement.AttachTo("maindiv") + +window.setTimeout(() => {html.setData("Different text")}, 1000) \ No newline at end of file