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{
" of door je " +
" aan te melden.
",
"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." +
""
);
+
+ 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+"? " +
"Je hoeft niet te herhalen wat je net hebt aangeduid. " +
+ "Een naam wordt in de volgende stap gevraagd. " +
"Voel je vrij om dit veld over te slaan.",
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;
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 "" +
- "" + html + "" + this._editButton.Render() +
+ "" + html + "" +
+ editButton +
"";
}
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({});
+ public preferenceSources : any = {}
+
+ public GetPreference(key: string) : UIEventSource{
+ 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(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;
+ private _changes: Changes;
+ private _userDetails: UIEventSource;
private _title: UIElement;
private _osmLink: UIElement;
-
-
- private _questions: QuestionPicker;
-
- private _changes: Changes;
- private _userDetails: UIEventSource;
- private _imageElement: ImageCarousel;
- private _pictureUploader: UIElement;
private _wikipedialink: UIElement;
- private _infoboxes: TagDependantUIElement[];
+
+ private _infoboxes: TagDependantUIElement[];
+ private _questions: QuestionPicker;
+
constructor(
tagsES: UIEventSource,
title: TagRenderingOptions,
elementsToShow: TagRenderingOptions[],
changes: Changes,
- userDetails: UIEventSource,
- preferedPictureLicense: UIEventSource
+ userDetails: UIEventSource
) {
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 {
"" +
"
" +
"Je klikte ergens waar er nog geen gezochte data is. ";
+ if (!this._userDetails.data.loggedIn) {
+ return header + "Gelieve je aan te melden om een nieuw punt toe te voegen"
+ }
+
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 + "Gelieve je aan te melden om een nieuw punt toe te voegen"
- }
-
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 @@
+
+
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 @@
-
-
-
-
-
-
-
-
-
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(undefined);
-const preferedPictureLicense = new UIEventSource(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 "
";
}),
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("Some text");
+
+const uielement = new VariableUiElement(html);
+uielement.AttachTo("maindiv")
+
+window.setTimeout(() => {html.setData("Different text")}, 1000)
\ No newline at end of file