Various small fixes

This commit is contained in:
Pieter Vander Vennet 2020-09-17 13:13:02 +02:00
parent 1ea285d303
commit 2dd428497e
45 changed files with 776 additions and 587 deletions

View file

@ -1,10 +1,7 @@
import {LayerDefinition} from "./LayerDefinition"; import {LayerDefinition} from "./LayerDefinition";
import {Layout} from "./Layout"; import {Layout} from "./Layout";
import {Groen} from "./Layouts/Groen";
import Cyclofix from "./Layouts/Cyclofix";
import {StreetWidth} from "./Layouts/StreetWidth"; import {StreetWidth} from "./Layouts/StreetWidth";
import {MetaMap} from "./Layouts/MetaMap"; import {MetaMap} from "./Layouts/MetaMap";
import {Natuurpunt} from "./Layouts/Natuurpunt";
import {FromJSON} from "./JSON/FromJSON"; import {FromJSON} from "./JSON/FromJSON";
import * as bookcases from "../assets/themes/bookcases/Bookcases.json"; import * as bookcases from "../assets/themes/bookcases/Bookcases.json";
import * as aed from "../assets/themes/aed/aed.json"; import * as aed from "../assets/themes/aed/aed.json";
@ -12,27 +9,53 @@ import * as toilets from "../assets/themes/toilets/toilets.json";
import * as artworks from "../assets/themes/artwork/artwork.json"; import * as artworks from "../assets/themes/artwork/artwork.json";
import * as cyclestreets from "../assets/themes/cyclestreets/cyclestreets.json"; import * as cyclestreets from "../assets/themes/cyclestreets/cyclestreets.json";
import * as ghostbikes from "../assets/themes/ghostbikes/ghostbikes.json" import * as ghostbikes from "../assets/themes/ghostbikes/ghostbikes.json"
import * as cyclofix from "../assets/themes/cyclofix/cyclofix.json"
import * as buurtnatuur from "../assets/themes/buurtnatuur/buurtnatuur.json"
import {PersonalLayout} from "../Logic/PersonalLayout"; import {PersonalLayout} from "../Logic/PersonalLayout";
export class AllKnownLayouts { export class AllKnownLayouts {
public static allLayers: Map<string, LayerDefinition> = undefined; public static allLayers: Map<string, LayerDefinition> = undefined;
private static GenerateCycloFix(): Layout {
const layout = FromJSON.LayoutFromJSON(cyclofix)
const now = new Date();
const m = now.getMonth() + 1;
const day = new Date().getDay() + 1;
const date = day + "/" + m;
if (date === "31/10" || date === "1/11" || date === "2/11") {
// Around Halloween/Fiesta de muerte/Allerzielen, we remember the dead
layout.layers.push(
FromJSON.sharedLayers.get("ghost_bike")
);
}
return layout;
}
private static GenerateBuurtNatuur(): Layout {
const layout = FromJSON.LayoutFromJSON(buurtnatuur);
layout.enableMoreQuests = false;
layout.enableShareScreen = false;
return layout;
}
public static layoutsList: Layout[] = [ public static layoutsList: Layout[] = [
new PersonalLayout(), new PersonalLayout(),
new Natuurpunt(), // new Natuurpunt(),
new Cyclofix(), AllKnownLayouts.GenerateBuurtNatuur(),
FromJSON.LayoutFromJSON(bookcases), FromJSON.LayoutFromJSON(bookcases),
FromJSON.LayoutFromJSON(aed), FromJSON.LayoutFromJSON(aed),
FromJSON.LayoutFromJSON(toilets), FromJSON.LayoutFromJSON(toilets),
FromJSON.LayoutFromJSON(artworks), FromJSON.LayoutFromJSON(artworks),
FromJSON.LayoutFromJSON(cyclestreets), FromJSON.LayoutFromJSON(cyclestreets),
FromJSON.LayoutFromJSON(ghostbikes), FromJSON.LayoutFromJSON(ghostbikes),
AllKnownLayouts.GenerateCycloFix(),
new MetaMap(), new MetaMap(),
new StreetWidth(), new StreetWidth(),
new Groen(),
]; ];
@ -51,7 +74,6 @@ export class AllKnownLayouts {
} }
} }
if (this.allLayers[layer.id] !== undefined) { if (this.allLayers[layer.id] !== undefined) {
continue; continue;
} }

View file

@ -32,7 +32,7 @@ export default class HelpText extends UIElement {
return "<h1>Welcome to the Custom Theme Builder</h1>" + return "<h1>Welcome to the Custom Theme Builder</h1>" +
"Here, one can make their own custom mapcomplete themes.<br/>" + "Here, one can make their own custom mapcomplete themes.<br/>" +
"Fill out the fields to get a working mapcomplete theme. More information on the selected field will appear here when you click it.<br/>" + "Fill out the fields to get a working mapcomplete theme. More information on the selected field will appear here when you click it.<br/>" +
"Want to see how the quests are doing in number of visits? All the stats are open on <a href='pietervdvn.goatcounter.com' target='_blank'>goatcounter</a>"; "Want to see how the quests are doing in number of visits? All the stats are open on <a href='https://pietervdvn.goatcounter.com' target='_blank'>goatcounter</a>";
} }
return new Combine(["<h1>", setting._name, "</h1>", setting._description.Render()]).Render(); return new Combine(["<h1>", setting._name, "</h1>", setting._description.Render()]).Render();

View file

@ -85,6 +85,7 @@ export class FromJSON {
layout.maintainer = json.maintainer; layout.maintainer = json.maintainer;
layout.version = json.version; layout.version = json.version;
layout.socialImage = json.socialImage; layout.socialImage = json.socialImage;
layout.description = tr(json.shortDescription) ?? tr(json.description)?.FirstSentence();
layout.changesetMessage = json.changesetmessage; layout.changesetMessage = json.changesetmessage;
return layout; return layout;
} }

View file

@ -37,6 +37,12 @@ export interface LayoutConfigJson {
* The title, as shown in the welcome message and the more-screen * The title, as shown in the welcome message and the more-screen
*/ */
title: string | any; title: string | any;
/**
* A short description, showed as social description and in the 'more theme'-buttons
*/
shortDescription?: string | any;
/** /**
* The description, as shown in the welcome message and the more-screen * The description, as shown in the welcome message and the more-screen
*/ */

View file

@ -1,84 +0,0 @@
import {LayerDefinition} from "../LayerDefinition";
import {Or, Tag} from "../../Logic/Tags";
import {AccessTag} from "../Questions/AccessTag";
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 Bos extends LayerDefinition {
constructor() {
super("bos");
this.name = "Bos";
this.icon = "";
this.overpassFilter = new Or([
new Tag("natural", "wood"),
new Tag("landuse", "forest"),
new Tag("natural", "scrub")
]
);
this.presets = [{
title: "Bos",
description: "Voeg een ontbrekend bos toe aan de kaart",
icon: undefined,
tags: [
new Tag("landuse", "forest"),
new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")
]
}];
this.maxAllowedOverlapPercentage = 10;
this.minzoom = 13;
this.style = this.generateStyleFunction();
this.title = new NameInline("Bos");
this.elementsToShow = [
new ImageCarouselWithUploadConstructor(),
new NameQuestion(),
new AccessTag(),
new OperatorTag(),
new DescriptionQuestion("bos")
];
}
private generateStyleFunction() {
const self = this;
return function (properties: any) {
let questionSeverity = 0;
for (const qd of self.elementsToShow) {
if(qd instanceof DescriptionQuestion){
continue;
}
if (qd.IsQuestioning(properties)) {
questionSeverity = Math.max(questionSeverity, qd.Priority());
}
}
let colormapping = {
0: "#00bb00",
1: "#00ff00",
10: "#dddd00",
20: "#ff0000"
};
let colour = colormapping[questionSeverity];
while (colour == undefined) {
questionSeverity--;
colour = colormapping[questionSeverity];
}
return {
color: colour,
icon: undefined
};
};
}
}

View file

@ -1,11 +1,6 @@
import {LayerDefinition} from "../LayerDefinition"; import {LayerDefinition} from "../LayerDefinition";
import {Or, Tag} from "../../Logic/Tags"; import {Or, Tag} from "../../Logic/Tags";
import {AccessTag} from "../Questions/AccessTag";
import {OperatorTag} from "../Questions/OperatorTag";
import {NameQuestion} from "../Questions/NameQuestion";
import {NameInline} from "../Questions/NameInline"; import {NameInline} from "../Questions/NameInline";
import {DescriptionQuestion} from "../Questions/DescriptionQuestion";
import ImageCarouselWithUploadConstructor from "../../UI/Image/ImageCarouselWithUpload";
import {TagRenderingOptions} from "../TagRenderingOptions"; import {TagRenderingOptions} from "../TagRenderingOptions";
export class NatureReserves extends LayerDefinition { export class NatureReserves extends LayerDefinition {
@ -27,13 +22,13 @@ export class NatureReserves extends LayerDefinition {
]; ];
this.minzoom = 13; this.minzoom = 13;
this.title = new NameInline("Natuurreservaat"); this.title = new NameInline("Natuurreservaat");
this.style = this.generateStyleFunction(); this.style = function () {
return {
color: "#00bb00",
icon: undefined
};
};
this.elementsToShow = [ this.elementsToShow = [
new ImageCarouselWithUploadConstructor(),
new NameQuestion(),
new AccessTag(),
new OperatorTag(),
new DescriptionQuestion("natuurgebied")
]; ];
@ -97,38 +92,4 @@ export class NatureReserves extends LayerDefinition {
} }
private generateStyleFunction() {
const self = this;
return function (properties: any) {
let questionSeverity = 0;
for (const qd of self.elementsToShow) {
//if(qd instanceof DescriptionQuestion){
// continue;
//}
if (qd.IsQuestioning(properties)) {
questionSeverity = Math.max(questionSeverity, qd.Priority() ?? 0);
}
}
let colormapping = {
0: "#00bb00",
10: "#dddd00",
20: "#ff0000"
};
let colour = colormapping[questionSeverity];
while (colour == undefined) {
questionSeverity--;
colour = colormapping[questionSeverity];
}
return {
color: colour,
icon: undefined
};
};
}
} }

View file

@ -1,110 +0,0 @@
import {LayerDefinition} from "../LayerDefinition";
import {Or, Tag} from "../../Logic/Tags";
import {NameQuestion} from "../Questions/NameQuestion";
import {NameInline} from "../Questions/NameInline";
import {DescriptionQuestion} from "../Questions/DescriptionQuestion";
import ImageCarouselWithUploadConstructor from "../../UI/Image/ImageCarouselWithUpload";
import {TagRenderingOptions} from "../TagRenderingOptions";
export class Park extends LayerDefinition {
private accessByDefault = new TagRenderingOptions({
question: "Is dit park publiek toegankelijk?",
mappings: [
{k: new Tag("access", "yes"), txt: "Publiek toegankelijk"},
{k: new Tag("access", ""), txt: "Publiek toegankelijk", hideInAnswer: true},
{k: new Tag("access", "no"), txt: "Niet publiek toegankelijk"},
{k: new Tag("access", "private"), txt: "Niet publiek toegankelijk, want privaat"},
{k: new Tag("access", "guided"), txt: "Enkel toegankelijk met een gids of op een activiteit"},
],
freeform: {
key: "access",
renderTemplate: "Dit park is niet toegankelijk: {access}",
template: "De toegankelijkheid van dit park is: $$$"
},
priority: 20
})
private operatorByDefault = new
TagRenderingOptions({
question: "Wie beheert dit park?",
freeform: {
key: "operator",
renderTemplate: "Dit park wordt beheerd door {operator}",
template: "$$$",
},
mappings: [{
k: null, txt: "De gemeente beheert dit park"
}],
priority: 15
});
constructor() {
super("park");
this.name = "Park";
this.icon = undefined;
this.overpassFilter =
new Or([new Tag("leisure", "park"), new Tag("landuse", "village_green")]);
this.presets = [{
title: "Park",
description: "Voeg een ontbrekend park toe. Een park is een groene ruimte die openbaar is." +
"Typisch vind je er banken, vuilbakken, standbeelden, ... ",
tags: [new Tag("leisure", "park"),
new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")]
}];
this.maxAllowedOverlapPercentage = 25;
this.minzoom = 13;
this.style = this.generateStyleFunction();
this.title = new NameInline("Park");
this.elementsToShow = [
new ImageCarouselWithUploadConstructor(),
new NameQuestion(),
this.accessByDefault,
this.operatorByDefault,
new DescriptionQuestion("park"),
];
}
private generateStyleFunction() {
const self = this;
return function (properties: any) {
let questionSeverity = 0;
for (const qd of self.elementsToShow) {
if (qd instanceof DescriptionQuestion) {
continue;
}
if (qd.IsQuestioning(properties)) {
questionSeverity = Math.max(questionSeverity, qd.Priority() ?? 0);
}
}
let colormapping = {
0: "#00bb00",
1: "#00ff00",
10: "#dddd00",
20: "#ff0000"
};
let colour = colormapping[questionSeverity];
while (colour == undefined) {
questionSeverity--;
colour = colormapping[questionSeverity];
}
return {
color: colour,
icon: undefined
};
};
}
}

View file

@ -1,40 +0,0 @@
import {Layout} from "../Layout";
import Translations from "../../UI/i18n/Translations";
import Combine from "../../UI/Base/Combine";
export default class Cyclofix extends Layout {
private static RememberTheDead(): boolean {
const now = new Date();
const m = now.getMonth() + 1;
const day = new Date().getDay() + 1;
const date = day + "/" + m;
return (date === "31/10" || date === "1/11" || date === "2/11");
}
constructor() {
super(
"cyclofix",
["en", "nl", "fr", "gl","de"],
Translations.t.cyclofix.title,
["bike_repair_station", "bike_cafes", "bike_shops", "drinking_water", "bike_parking","bike_themed_object",
// The first of november, halloween and the second of november, we remember our dead
...(Cyclofix.RememberTheDead() ? ["ghost_bike"] : [])],
16,
50.8465573,
4.3516970,
new Combine([
"<h3>",
Translations.t.cyclofix.title,
"</h3><br/><p>",
Translations.t.cyclofix.description,
"</p>"
])
);
this.icon = "./assets/bike/logo.svg"
this.description = "Easily search and contribute bicycle data nearby";
this.socialImage = "./assets/bike/cyclofix.jpeg";
this.widenFactor = 0.05;
}
}

View file

@ -1,23 +0,0 @@
import {Layout} from "../Layout";
import {GrbToFix} from "../Layers/GrbToFix";
export class GRB extends Layout {
constructor() {
super("grb",
["en"],
"Grb import fix tool",
[new GrbToFix()],
15,
51.2083,
3.2279,
"<h3>GRB Fix tool</h3>\n" +
"\n" +
"Expert use only"
,
"", "");
this.hideFromOverview = true;
}
}

View file

@ -1,61 +0,0 @@
import {Park} from "../Layers/Park";
import {Bos} from "../Layers/Bos";
import {Layout} from "../Layout";
import {NatureReserves} from "../Layers/NatureReserves";
export class Groen extends Layout {
constructor() {
super("buurtnatuur",
["nl"],
"Buurtnatuur.be",
[new NatureReserves(), new Park(), new Bos(), "viewpoint"],
10,
50.8435,
4.3688,
"\n" +
"<img style='float:right;margin: 1em;width: 10em;height: auto;' src='./assets/themes/buurtnatuur/groen_logo.svg' alt='logo-groen' class='logo'> <br />" +
"<h3>Breng jouw buurtnatuur in kaart</h3>" +
"<b>Natuur maakt gelukkig.</b> Aan de hand van deze website willen we de natuur dicht bij ons beter inventariseren. Met als doel meer mensen te laten genieten van toegankelijke natuur én te strijden voor meer natuur in onze buurten. \n" +
"<ul>" +
"<li>In welke natuurgebieden kan jij terecht? Hoe toegankelijk zijn ze?</li>" +
"<li>In welke bossen kan een gezin in jouw gemeente opnieuw op adem komen?</li>" +
"<li>Op welke onbekende plekjes is het zalig spelen?</li>" +
"</ul>" +
"<p>Samen kleuren we heel Vlaanderen en Brussel groen.</p>" +
"<p>Blijf op de hoogte van de resultaten van buurtnatuur.be: <a href=\"https://www.groen.be/buurtnatuur\" target='_blank'>meld je aan voor e-mailupdates</a>.</p> \n"
,
"<b>Begin meteen door <a href=\"https://www.openstreetmap.org/user/new\" target=\"_blank\">een account te maken\n" +
" te maken</a> of\n" +
" <span onclick=\"authOsm()\" class=\"activate-osm-authentication\">in te loggen</span>.</b>",
"",
"<h4>Tips</h4>" +
"<ul>" +
"<li>Over groen ingekleurde gebieden weten we alles wat we willen weten.</li>" +
"<li>Bij rood ingekleurde gebieden ontbreekt nog heel wat info: klik een gebied aan en beantwoord de vragen.</li>" +
"<li>Je kan altijd een vraag overslaan als je het antwoord niet weet of niet zeker bent</li>" +
"<li>Je kan altijd een foto toevoegen</li>" +
"<li>Je kan ook zelf een gebied toevoegen door op de kaart te klikken</li>" +
"<li>Open buurtnatuur.be <b>op je smartphone</b> om al wandelend foto's te maken en vragen te beantwoorden</li>" +
"</ul>" +
"<small>" +
"<p>" +
"De oorspronkelijke data komt van <b>OpenStreetMap</b> en je antwoorden worden daar bewaard.<br/> Omdat iedereen vrij kan meewerken aan dit project, kunnen we niet garanderen dat er geen fouten opduiken." +
"Kan je hier niet aanpassen wat je wilt, dan kan je dat zelf via OpenStreetMap.org doen. Groen kan <b>geen enkele verantwoordelijkheid</b> nemen over de kaart." +
"</p>" +
"Je privacy is belangrijk. We tellen wel hoeveel gebruikers deze website bezoeken. We plaatsen een cookie waar geen persoonlijke informatie in bewaard wordt. " +
"Als je inlogt, komt er een tweede cookie bij met je inloggegevens." +
"</small>"
);
this.icon = "./assets/themes/buurtnatuur/groen_logo.svg"
this.socialImage = "assets/themes/buurtnatuur/social_image.jpg"
this.description = "Met deze tool kan je natuur in je buurt in kaart brengen en meer informatie geven over je favoriete plekje"
this.enableMoreQuests = false;
this.enableShareScreen = false
}
}

View file

@ -36,10 +36,6 @@ export class OnlyShowIfConstructor implements TagDependantUIElementConstructor{
return this._embedded.IsQuestioning(properties); return this._embedded.IsQuestioning(properties);
} }
Priority(): number {
return this._embedded.Priority();
}
GetContent(tags: any): Translation { GetContent(tags: any): Translation {
if(!this.IsKnown(tags)){ if(!this.IsKnown(tags)){
return undefined; return undefined;
@ -78,10 +74,6 @@ class OnlyShowIf extends UIElement implements TagDependantUIElement {
} }
} }
Priority(): number {
return this._embedded.Priority();
}
IsKnown(): boolean { IsKnown(): boolean {
if(!this.Matches()){ if(!this.Matches()){
return false; return false;

View file

@ -1,35 +0,0 @@
import {And, Tag} from "../../Logic/Tags";
import {TagRenderingOptions} from "../TagRenderingOptions";
export class AccessTag extends TagRenderingOptions {
private static options = {
priority: 20,
question: "Is dit gebied toegankelijk?",
freeform: {
key: "access:description",
template: "Iets anders: $$$",
renderTemplate: "De toegankelijkheid van dit gebied is: {access:description}",
placeholder: "Specifieer"
},
mappings: [
{k: new And([new Tag("access", "yes"), new Tag("fee", "")]), txt: "Publiek toegankelijk"},
{k: new And([new Tag("access", "no"), new Tag("fee", "")]), txt: "Niet toegankelijk"},
{k: new And([new Tag("access", "private"), new Tag("fee", "")]), txt: "Niet toegankelijk, want privegebied"},
{k: new And([new Tag("access", "permissive"), new Tag("fee", "")]), txt: "Toegankelijk, maar het is privegebied"},
{k: new And([new Tag("access", "guided"), new Tag("fee", "")]), txt: "Enkel met een gids of tijdens een activiteit toegankelijk"},
{
k: new And([new Tag("access", "yes"),
new Tag("fee", "yes")]),
txt: "Toegankelijk mits betaling",
priority: 10
},
]
}
constructor() {
super(AccessTag.options);
}
}

View file

@ -5,8 +5,8 @@ import {TagRenderingOptions} from "../TagRenderingOptions";
export class OperatorTag extends TagRenderingOptions { export class OperatorTag extends TagRenderingOptions {
private static options = { constructor() {
priority: 15, super({
question: "Wie beheert dit gebied?", question: "Wie beheert dit gebied?",
freeform: { freeform: {
key: "operator", key: "operator",
@ -19,10 +19,7 @@ export class OperatorTag extends TagRenderingOptions {
{k: new Tag("operator", "Agentschap Natuur en Bos"), txt: "het Agentschap Natuur en Bos (ANB)"}, {k: new Tag("operator", "Agentschap Natuur en Bos"), txt: "het Agentschap Natuur en Bos (ANB)"},
{k: new Tag("operator", "private"), txt: "Beheer door een privépersoon"} {k: new Tag("operator", "private"), txt: "Beheer door een privépersoon"}
] ]
} });
constructor() {
super(OperatorTag.options);
} }
} }

View file

@ -11,7 +11,6 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
* Notes: by not giving a 'question', one disables the question form alltogether * Notes: by not giving a 'question', one disables the question form alltogether
*/ */
public options: { public options: {
priority?: number;
question?: string | Translation; question?: string | Translation;
freeform?: { freeform?: {
key: string; key: string;
@ -22,7 +21,7 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
extraTags?: TagsFilter extraTags?: TagsFilter
}; };
multiAnswer?: boolean, multiAnswer?: boolean,
mappings?: { k: TagsFilter; txt: string | Translation; priority?: number, substitute?: boolean, hideInAnwser?: boolean }[] mappings?: { k: TagsFilter; txt: string | Translation; substitute?: boolean, hideInAnwser?: boolean }[]
}; };
constructor(options: { constructor(options: {
@ -146,8 +145,4 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
return !this.IsQuestioning(properties); return !this.IsQuestioning(properties);
} }
Priority(): number {
return this.options.priority ?? 0;
}
} }

View file

@ -12,7 +12,6 @@ export interface TagDependantUIElementConstructor {
construct(dependencies: Dependencies): TagDependantUIElement; construct(dependencies: Dependencies): TagDependantUIElement;
IsKnown(properties: any): boolean; IsKnown(properties: any): boolean;
IsQuestioning(properties: any): boolean; IsQuestioning(properties: any): boolean;
Priority(): number;
GetContent(tags: any): Translation; GetContent(tags: any): Translation;
} }
@ -23,7 +22,5 @@ export abstract class TagDependantUIElement extends UIElement {
abstract IsQuestioning(): boolean; abstract IsQuestioning(): boolean;
abstract Priority() : number;
abstract IsSkipped() : boolean; abstract IsSkipped() : boolean;
} }

View file

@ -106,23 +106,18 @@ export class Tag extends TagsFilter {
} }
matches(tags: { k: string; v: string }[]): boolean { matches(tags: { k: string; v: string }[]): boolean {
if (this.value === "") {
return true
}
for (const tag of tags) { for (const tag of tags) {
if (this.key == tag.k) { if (this.key == tag.k) {
return this.value === tag.v;
if (tag.v === "") { }
// This tag has been removed -> always matches false
return false;
} }
if (this.value === tag.v) { // The tag was not found
if(this.value === ""){
// and it shouldn't be found!
return true; return true;
} }
}
}
return false; return false;
} }

View file

@ -172,3 +172,10 @@ 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 https://commons.wikimedia.org/wiki/File:Map_icons_by_Scott_de_Jonge_-_bicycle-store.svg
Bicycle logo, Scott de Jonge Bicycle logo, Scott de Jonge
Nature Reserve icon via http://www.onlinewebfonts.com/icon/389579, CC BY 3.0 (@ Эдуард Черных)
Park icon via http://www.onlinewebfonts.com/icon/425974, CC BY 3.0 (@sterankofrank)
Forest icon via https://www.onlinewebfonts.com/icon/498112, CC BY

View file

@ -22,10 +22,11 @@ export class State {
// The singleton of the global state // The singleton of the global state
public static state: State; public static state: State;
public static vNumber = "0.0.8"; public static vNumber = "0.0.8a";
// The user journey states thresholds when a new feature gets unlocked // The user journey states thresholds when a new feature gets unlocked
public static userJourney = { public static userJourney = {
addNewPointsUnlock: 1,
moreScreenUnlock: 5, moreScreenUnlock: 5,
personalLayoutUnlock: 20, personalLayoutUnlock: 20,
tagsVisibleAt: 100, tagsVisibleAt: 100,
@ -33,6 +34,7 @@ export class State {
tagsVisibleAndWikiLinked: 150, tagsVisibleAndWikiLinked: 150,
themeGeneratorReadOnlyUnlock: 200, themeGeneratorReadOnlyUnlock: 200,
themeGeneratorFullUnlock: 500, themeGeneratorFullUnlock: 500,
addNewPointWithUnreadMessagesUnlock: 500
}; };
public static runningFromConsole: boolean = false; public static runningFromConsole: boolean = false;

View file

@ -19,7 +19,7 @@ export class SubtleButton extends UIElement{
if ((imageUrl ?? "") === "") { if ((imageUrl ?? "") === "") {
this.image = new FixedUiElement(""); this.image = new FixedUiElement("");
} else if (typeof (imageUrl) === "string") { } else if (typeof (imageUrl) === "string") {
this.image = new FixedUiElement(`<img src="${imageUrl}">`); this.image = new FixedUiElement(`<img style="height:3em" src="${imageUrl}">`);
} else { } else {
this.image = imageUrl; this.image = imageUrl;
} }

View file

@ -42,7 +42,8 @@ export default class CustomGeneratorPanel extends UIElement {
const encoded = es.map(config => btoa(JSON.stringify(config))); const encoded = es.map(config => btoa(JSON.stringify(config)));
encoded.addCallback(encoded => LocalStorageSource.Get("last-custom-theme")) encoded.addCallback(encoded => LocalStorageSource.Get("last-custom-theme"))
const liveUrl = encoded.map(encoded => `./index.html?userlayout=${es.data.id}#${encoded}`) const liveUrl = encoded.map(encoded => `./index.html?userlayout=${es.data.id}#${encoded}`)
const iframe = liveUrl.map(url => `<iframe src='${url}' width='100%' height='99%' style="box-sizing: border-box" title='Theme Preview'></iframe>`); const testUrl = encoded.map(encoded => `./index.html?test=true&userlayout=${es.data.id}#${encoded}`)
const iframe = testUrl.map(url => `<iframe src='${url}' width='100%' height='99%' style="box-sizing: border-box" title='Theme Preview'></iframe>`);
const currentSetting = new UIEventSource<SingleSetting<any>>(undefined) const currentSetting = new UIEventSource<SingleSetting<any>>(undefined)
const generalSettings = new GeneralSettings(es, currentSetting); const generalSettings = new GeneralSettings(es, currentSetting);
const languages = generalSettings.languages; const languages = generalSettings.languages;

View file

@ -43,8 +43,10 @@ export default class GeneralSettingsPanel extends UIElement {
"Supported languages", "Which languages do you want to support in this theme? Type the two letter code representing your language, seperated by <span class='literal-code'>;</span>. For example:<span class='literal-code'>en;nl</span> "), "Supported languages", "Which languages do you want to support in this theme? Type the two letter code representing your language, seperated by <span class='literal-code'>;</span>. For example:<span class='literal-code'>en;nl</span> "),
new SingleSetting(configuration, new MultiLingualTextFields(this.languages), "title", new SingleSetting(configuration, new MultiLingualTextFields(this.languages), "title",
"Title", "The title as shown in the welcome message, in the browser title bar, in the more screen, ..."), "Title", "The title as shown in the welcome message, in the browser title bar, in the more screen, ..."),
new SingleSetting(configuration, new MultiLingualTextFields(this.languages), "shortDescription","Short description",
"The short description is shown as subtext in the social preview and on the 'more screen'-buttons. It should be at most one sentence of around ~25words"),
new SingleSetting(configuration, new MultiLingualTextFields(this.languages, true), new SingleSetting(configuration, new MultiLingualTextFields(this.languages, true),
"description", "Description", "The description is shown in the welcomemessage. It is a small text welcoming users"), "description", "Description", "The description is shown in the welcome-message when opening MapComplete. It is a small text welcoming users"),
new SingleSetting(configuration, TextField.StringInput(), "icon", new SingleSetting(configuration, TextField.StringInput(), "icon",
"Icon", "A visual representation for your theme; used as logo in the welcomeMessage. If your theme is official, used as favicon and webapp logo", "Icon", "A visual representation for your theme; used as logo in the welcomeMessage. If your theme is official, used as favicon and webapp logo",
{ {

View file

@ -32,6 +32,7 @@ export class GenerateEmpty {
return { return {
id: "id", id: "id",
title: {}, title: {},
shortDescription: {},
description: {}, description: {},
language: [], language: [],
maintainer: "", maintainer: "",
@ -51,6 +52,7 @@ export class GenerateEmpty {
return { return {
id: "test", id: "test",
title: {"en": "Test layout"}, title: {"en": "Test layout"},
shortDescription: {},
description: {"en": "A layout for testing"}, description: {"en": "A layout for testing"},
language: ["en"], language: ["en"],
maintainer: "Pieter Vander Vennet", maintainer: "Pieter Vander Vennet",

View file

@ -115,30 +115,16 @@ export class FeatureInfoBox extends UIElement {
let questionElement: UIElement; let questionElement: UIElement;
if (!State.state.osmConnection.userDetails.data.loggedIn) { if (questions.length > 0) {
let mostImportantQuestion ;
let score = -1000;
for (const question of questions) {
if (mostImportantQuestion === undefined || question.Priority() > score) {
mostImportantQuestion = question;
score = question.Priority();
}
}
questionElement = mostImportantQuestion;
} else if (questions.length > 0) {
// We select the most important question and render that one // We select the most important question and render that one
let mostImportantQuestion; let mostImportantQuestion;
let score = -1000;
for (const question of questions) { for (const question of questions) {
if (mostImportantQuestion === undefined || question.Priority() > score) { if (mostImportantQuestion === undefined) {
mostImportantQuestion = question; mostImportantQuestion = question;
score = question.Priority(); break;
} }
} }
questionElement = mostImportantQuestion; questionElement = mostImportantQuestion;
} else if (skippedQuestions == 1) { } else if (skippedQuestions == 1) {
questionElement = this._oneSkipped; questionElement = this._oneSkipped;

View file

@ -162,12 +162,13 @@ export class SimpleAddUI extends UIElement {
return new Combine([header, this._loginButton]).Render() return new Combine([header, this._loginButton]).Render()
} }
if (userDetails.data.unreadMessages > 0) { if (userDetails.data.unreadMessages > 0 && userDetails.data.csCount < State.userJourney.addNewPointWithUnreadMessagesUnlock) {
return new Combine([header, "<span class='alert'>", return new Combine([header, "<span class='alert'>",
Translations.t.general.readYourMessages, Translations.t.general.readYourMessages,
"</span>", "</span>",
this.goToInboxButton this.goToInboxButton
]).Render(); ]).Render();
} }
if (userDetails.data.dryRun) { if (userDetails.data.dryRun) {
@ -178,7 +179,7 @@ export class SimpleAddUI extends UIElement {
]); ]);
} }
if (userDetails.data.csCount < 5) { if (userDetails.data.csCount < State.userJourney.addNewPointsUnlock) {
return new Combine([header, "<span class='alert'>", return new Combine([header, "<span class='alert'>",
Translations.t.general.fewChangesBefore, Translations.t.general.fewChangesBefore,
"</span>"]).Render(); "</span>"]).Render();

View file

@ -21,7 +21,6 @@ import {FixedUiElement} from "./Base/FixedUiElement";
export class TagRendering extends UIElement implements TagDependantUIElement { export class TagRendering extends UIElement implements TagDependantUIElement {
private readonly _priority: number;
private readonly _question: string | Translation; private readonly _question: string | Translation;
private readonly _mapping: { k: TagsFilter, txt: string | UIElement, priority?: number }[]; private readonly _mapping: { k: TagsFilter, txt: string | UIElement, priority?: number }[];
@ -58,8 +57,6 @@ export class TagRendering extends UIElement implements TagDependantUIElement {
} }
constructor(tags: UIEventSource<any>, options: { constructor(tags: UIEventSource<any>, options: {
priority?: number
question?: string | Translation, question?: string | Translation,
freeform?: { freeform?: {
key: string, key: string,
@ -80,8 +77,6 @@ export class TagRendering extends UIElement implements TagDependantUIElement {
const self = this; const self = this;
this._priority = options.priority ?? 0;
this.currentTags = this._source.map(tags => this.currentTags = this._source.map(tags =>
{ {
@ -525,10 +520,6 @@ export class TagRendering extends UIElement implements TagDependantUIElement {
} }
Priority(): number {
return this._priority;
}
private ApplyTemplate(template: string | Translation): UIElement { private ApplyTemplate(template: string | Translation): UIElement {
if (template === undefined || template === null) { if (template === undefined || template === null) {
return undefined; return undefined;

View file

@ -1,6 +1,7 @@
import {UIElement} from "../UIElement" import {UIElement} from "../UIElement"
import Locale from "./Locale" import Locale from "./Locale"
import Combine from "../Base/Combine"; import Combine from "../Base/Combine";
import {Utils} from "../../Utils";
export default class Translation extends UIElement { export default class Translation extends UIElement {
@ -87,4 +88,16 @@ export default class Translation extends UIElement {
} }
FirstSentence() {
const tr = {};
for (const lng in this.translations) {
let txt = this.translations[lng];
txt = txt.replace(/\..*/, "");
txt = Utils.EllipsesAfter(txt, 255);
tr[lng] = txt;
}
return new Translation(tr);
}
} }

View file

@ -12,97 +12,6 @@ export default class Translations {
static t = { static t = {
cyclofix: {
title: new T({
en: 'Cyclofix - an open map for cyclists',
nl: 'Cyclofix - een open kaart voor fietsers',
fr: 'Cyclofix - Une carte ouverte pour les cyclistes',
gl: 'Cyclofix - Un mapa aberto para os ciclistas',
de: 'Cyclofix - eine offene Karte für Radfahrer'
}),
description: new T({
en: "The goal of this map is to present cyclists with an easy-to-use solution to find the appropriate infrastructure for their needs.<br><br>" + //this works in spoken language: ; think about the nearest bike repair station for example
"You can track your precise location (mobile only) and select layers that are relevant for you in the bottom left corner. " +
"You can also use this tool to add or edit pins (points of interest) to the map and provide more data by answering the questions.<br><br>" +
"All changes you make will automatically be saved in the global database of OpenStreetMap and can be freely re-used by others.<br><br>" +
"For more information about the cyclofix project, go to <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
nl: "Het doel van deze kaart is om fietsers een gebruiksvriendelijke oplossing te bieden voor het vinden van de juiste infrastructuur voor hun behoeften.<br><br>" + //; denk bijvoorbeeld aan de dichtstbijzijnde fietsherstelplaats.
"U kunt uw exacte locatie volgen (enkel mobiel) en in de linkerbenedenhoek categorieën selecteren die voor u relevant zijn. " +
"U kunt deze tool ook gebruiken om 'spelden' aan de kaart toe te voegen of te bewerken en meer gegevens te verstrekken door de vragen te beantwoorden.<br><br>" +
"Alle wijzigingen die u maakt worden automatisch opgeslagen in de wereldwijde database van OpenStreetMap en kunnen door anderen vrij worden hergebruikt.<br><br>" +
"Bekijk voor meer info over cyclofix ook <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
fr: "Le but de cette carte est de présenter aux cyclistes une solution facile à utiliser pour trouver l'infrastructure appropriée à leurs besoins.<br><br>" + //; pensez par exemple à la station de réparation de vélos la plus proche.
"Vous pouvez suivre votre localisation précise (mobile uniquement) et sélectionner les couches qui vous concernent dans le coin inférieur gauche. " +
"Vous pouvez également utiliser cet outil pour ajouter ou modifier des épingles (points d'intérêt) sur la carte et fournir plus de données en répondant aux questions.<br><br>" +
"Toutes les modifications que vous apportez seront automatiquement enregistrées dans la base de données mondiale d'OpenStreetMap et peuvent être librement réutilisées par d'autres.<br><br>" +
"Pour plus d'informations sur le projet cyclofix, rendez-vous sur <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
gl: "O obxectivo deste mapa é amosar ós ciclistas unha solución doada de empregar para atopar a infraestrutura axeitada para as súas necesidades.<br><br>" + //isto funciona na lingua falada: ; pensa na estación de arranxo de bicicletas máis preta, por exemplo.
"Podes obter a túa localización precisa (só para dispositivos móbiles) e escoller as capas que sexan relevantes para ti na esquina inferior esquerda. " +
"Tamén podes empregar esta ferramenta para engadir ou editar puntos de interese ó mapa e fornecer máis datos respondendo as cuestións.<br><br>" +
"Todas as modificacións que fagas serán gardadas de xeito automático na base de datos global do OpenStreetMap e outros poderán reutilizalos libremente.<br><br>" +
"Para máis información sobre o proxecto cyclofix, vai a <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
de: "Das Ziel dieser Karte ist es, den Radfahrern eine einfach zu benutzende Lösung zu präsentieren, um die geeignete Infrastruktur für ihre Bedürfnisse zu finden.<br><br>" + //dies funktioniert in gesprochener Sprache: ; denken Sie zum Beispiel an die nächste Fahrradreparaturstation
"Sie können Ihren genauen Standort verfolgen (nur mobil) und in der linken unteren Ecke die für Sie relevanten Ebenen auswählen. " +
"Sie können dieses Tool auch verwenden, um Pins (Points of Interest/Interessante Orte) zur Karte hinzuzufügen oder zu bearbeiten und mehr Daten durch Beantwortung der Fragen bereitstellen.<br><br>" +
"Alle Änderungen, die Sie vornehmen, werden automatisch in der globalen Datenbank von OpenStreetMap gespeichert und können von anderen frei wiederverwendet werden.<br><br>" +
"Weitere Informationen über das Projekt Cyclofix finden Sie unter <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>."
}),
nonBikeShop: {
name: new T({
en: "shop that sells/repairs bikes",
nl: "winkel die fietsen verkoopt/herstelt",
fr: "magasin qui repare/vend des vélos",
gl: "tenda que vende/arranxa bicicletas",
de: "geschäft, das Fahrräder verkauft/repariert"
}),
title: new T({
en: "Shop that sells/repairs bikes",
nl: "Winkel die fietsen verkoopt/herstelt",
fr: "Magasin qui répare/vend des vélos",
gl: "Tenda que vende/arranxa bicicletas",
de: "Geschäft, das Fahrräder verkauft/repariert"
}),
titleRepair: new T({
en: "Shop that repairs bikes",
nl: "Winkel die fietsen herstelt",
fr: "Magasin qui répare les vélos",
gl: "Tenda que arranxa bicicletas",
de: "Geschäft, das Fahrräder repariert"
}),
titleShop: new T({
en: "Shop that sells bikes",
nl: "Winkel die fietsen verkoopt",
fr: "Magasin qui vend des vélos",
gl: "Tenda que vende bicicletas",
de: "Geschäft, das Fahrräder verkauft"
}),
titleNamed: new T({
en: "{name} (sells/repairs bikes)",
nl: "{name} (verkoopt/herstelt fietsen)",
fr: "vend/repare les vélos",
gl: "{name} (vende/arranxa bicicletas)",
de: "{name} (verkauft/repariert Fahrräder)"
}),
titleRepairNamed: new T({
en: "{name} (repairs bikes)",
nl: "{name} (herstelt fietsen)",
fr: "{name} (répare les vélos)",
gl: "{name} (arranxa bicicletas)",
de: "{name} (repariert Fahrräder)"
}),
titleShopNamed: new T({
en: "{name} (sells bikes)",
nl: "{name} (verkoopt fietsen)",
fr: "{name} (vend des vélos)",
gl: "{name} (vende bicicletas)",
de: "{name} (verkauft Fahrräder)"
}),
}
},
image: { image: {
addPicture: new T({ addPicture: new T({
en: 'Add picture', en: 'Add picture',

View file

@ -238,7 +238,7 @@
"en": "This pump supports the following valves: {valves}", "en": "This pump supports the following valves: {valves}",
"nl": "Deze pomp werkt met de volgende ventielen: {valves}", "nl": "Deze pomp werkt met de volgende ventielen: {valves}",
"fr": "Cette pompe est compatible avec les valves suivantes: {valves}", "fr": "Cette pompe est compatible avec les valves suivantes: {valves}",
"gl": "Esta bomba de ar admite as seguintes válvulas: {valves}", "gl": "Esta bomba de ar admite as seguintes válvulas: {valves}"
}, },
"freeform": { "freeform": {
"#addExtraTags": [ "#addExtraTags": [

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View file

@ -0,0 +1,556 @@
{
"id": "buurtnatuur",
"title": {
"nl": "Breng jouw buurtnatuur in kaart"
},
"shortDescription": {
"nl": "Met deze tool kan je natuur in je buurt in kaart brengen en meer informatie geven over je favoriete plekje"
},
"description": {
"nl": "<img style='float:right;margin: 1em;width: 10em;height: auto;' src='./assets/themes/buurtnatuur/groen_logo.svg' alt='logo-groen' class='logo'> <br /><b>Natuur maakt gelukkig.</b> Aan de hand van deze website willen we de natuur dicht bij ons beter inventariseren. Met als doel meer mensen te laten genieten van toegankelijke natuur én te strijden voor meer natuur in onze buurten. \n<ul><li>In welke natuurgebieden kan jij terecht? Hoe toegankelijk zijn ze?</li><li>In welke bossen kan een gezin in jouw gemeente opnieuw op adem komen?</li><li>Op welke onbekende plekjes is het zalig spelen?</li></ul><p>Samen kleuren we heel Vlaanderen en Brussel groen.</p><p>Blijf op de hoogte van de resultaten van buurtnatuur.be: <a href=\"https://www.groen.be/buurtnatuur\" target='_blank'>meld je aan voor e-mailupdates</a>.</p> <h4>Tips</h4><ul><li>Over groen ingekleurde gebieden weten we alles wat we willen weten.</li><li>Bij rood ingekleurde gebieden ontbreekt nog heel wat info: klik een gebied aan en beantwoord de vragen.</li><li>Je kan altijd een vraag overslaan als je het antwoord niet weet of niet zeker bent</li><li>Je kan altijd een foto toevoegen</li><li>Je kan ook zelf een gebied toevoegen door op de kaart te klikken</li><li>Open buurtnatuur.be <b>op je smartphone</b> om al wandelend foto's te maken en vragen te beantwoorden</li></ul><small><p>De oorspronkelijke data komt van <b>OpenStreetMap</b> en je antwoorden worden daar bewaard.<br/> Omdat iedereen vrij kan meewerken aan dit project, kunnen we niet garanderen dat er geen fouten opduiken.Kan je hier niet aanpassen wat je wilt, dan kan je dat zelf via OpenStreetMap.org doen. Groen kan <b>geen enkele verantwoordelijkheid</b> nemen over de kaart.</p>Je privacy is belangrijk. We tellen wel hoeveel gebruikers deze website bezoeken. We plaatsen een cookie waar geen persoonlijke informatie in bewaard wordt. Als je inlogt, komt er een tweede cookie bij met je inloggegevens.</small>"
},
"language": [
"nl"
],
"maintainer": "",
"icon": "./assets/themes/buurtnatuur/groen_logo.svg",
"version": "0",
"startLat": 50.8435,
"startLon": 4.3688,
"startZoom": 16,
"widenFactor": 0.05,
"socialImage": "./assets/themes/buurtnatuur/social_image.jpg",
"layers": [
{
"id": "nature_reserve",
"name": {
"nl": "Natuurgebied"
},
"minzoom": 12,
"overpassTags": {
"or": [
"leisure=nature_reserve",
"boundary=protected_area"
]
},
"title": {
"render": {
"nl": "Natuurgebied"
},
"mappings": [
{
"if": {
"and": [
"name:nl~"
]
},
"then": {
"nl": "{name:nl}"
}
},
{
"if": {
"and": [
"name~*"
]
},
"then": {
"nl": "{name}"
}
}
]
},
"description": {
"nl": "Een natuurgebied is een gebied waar actief ruimte gemaakt word voor de natuur. Typisch zijn deze in beheer van Natuurpunt of het Agentschap Natuur en Bos of zijn deze erkend door de overheid."
},
"tagRenderings": [],
"hideUnderlayingFeaturesMinPercentage": 10,
"icon": {
"render": "./assets/themes/buurtnatuur/nature_reserve.svg",
"mappings": [
{
"#": "This is a little bit a hack to force a circle to be shown while keeping the icon in the 'new' menu",
"if": "id~node/[0-9]*",
"then": "$circle"
}
]
},
"width": {
"render": "2"
},
"iconSize": {
"render": "50,50,center"
},
"color": {
"render": "#3c3",
"mappings": [
{
"if": {
"and": [
"name=",
"noname=",
"operator=",
"access=",
"access:description=",
"leisure=park"
]
},
"then": "#cc1100"
},
{
"if": {
"and": [
"name=",
"noname="
]
},
"then": "#fccb37"
}
]
},
"presets": [
{
"tags": [
"leisure=nature_reserve",
"fixme=Toegevoegd met MapComplete, geometry nog uit te tekenen"
],
"title": {
"nl": "Natuurreservaat"
},
"description": {
"nl": "Voeg een ontbrekend, erkend natuurreservaat toe, bv. een gebied dat beheerd wordt door het ANB of natuurpunt"
}
}
]
},
{
"id": "parks",
"name": {
"nl": "Park"
},
"minzoom": 12,
"overpassTags": {
"or": [
"leisure=park",
"landuse=village_green"
]
},
"title": {
"render": {
"nl": "Park"
},
"mappings": [
{
"if": {
"and": [
"name:nl~"
]
},
"then": {
"nl": "{name:nl}"
}
},
{
"if": {
"and": [
"name~*"
]
},
"then": {
"nl": "{name}"
}
}
]
},
"description": {
"nl": "Een park is een publiek toegankelijke, groene ruimte binnen de stad. Ze is typisch ingericht voor recreatief gebruik, met (verharde) wandelpaden, zitbanken, vuilnisbakken, een gezellig vijvertje, ..."
},
"tagRenderings": [],
"hideUnderlayingFeaturesMinPercentage": 10,
"icon": {
"render": "./assets/themes/buurtnatuur/park.svg",
"mappings": [
{
"#": "This is a little bit a hack to force a circle to be shown while keeping the icon in the 'new' menu",
"if": "id~node/[0-9]*",
"then": "$circle"
}
]
},
"width": {
"render": "2"
},
"iconSize": {
"render": "40,40,center"
},
"color": {
"render": "#3c3",
"mappings": [
{
"if": {
"and": [
"name=",
"noname="
]
},
"then": "#fccb37"
}
]
},
"presets": [
{
"tags": [
"leisure=park",
"fixme=Toegevoegd met MapComplete, geometry nog uit te tekenen"
],
"title": {
"nl": "Park"
},
"description": {
"nl": "Voeg een ontbrekend park toe"
}
}
]
},
{
"id": "forest",
"name": {
"nl": "Bos"
},
"minzoom": 12,
"overpassTags": {
"or": [
"landuse=forest",
"natural=wood",
"natural=scrub"
]
},
"title": {
"render": {
"nl": "Bos"
},
"mappings": [
{
"if": {
"and": [
"name:nl~"
]
},
"then": {
"nl": "{name:nl}"
}
},
{
"if": {
"and": [
"name~*"
]
},
"then": {
"nl": "{name}"
}
}
]
},
"description": {
"nl": "Een bos is een verzameling bomen, al dan niet als productiehout."
},
"tagRenderings": [],
"hideUnderlayingFeaturesMinPercentage": 0,
"icon": {
"render": "./assets/themes/buurtnatuur/forest.svg",
"mappings": [
{
"#": "This is a little bit a hack to force a circle to be shown while keeping the icon in the 'new' menu",
"if": "id~node/[0-9]*",
"then": "$circle"
}
]
},
"width": {
"render": "1"
},
"iconSize": {
"render": "40,40,center"
},
"color": {
"render": "#3a3",
"mappings": [
{
"if": {
"and": [
"operator=",
"access=",
"access:description="
]
},
"then": "#cc1100"
},
{
"if": {
"and": [
"operator="
]
},
"then": "#cccc00"
},
{
"if": {
"and": [
"name=",
"noname="
]
},
"then": "#fccb37"
}
]
},
"presets": [
{
"tags": [
"landuse=forest",
"fixme=Toegevoegd met MapComplete, geometry nog uit te tekenen"
],
"title": {
"nl": "Bos"
},
"description": {
"nl": "Voeg een ontbrekend bos toe aan de kaart"
}
}
]
},
"viewpoint"
],
"roamingRenderings": [
{
"#": "Access tag",
"condition": {
"and": [
"tourism!~viewpoint"
]
},
"render": {
"nl": "De toegankelijkheid van dit gebied is: {access:description}"
},
"question": {
"nl": "Is dit gebied toegankelijk?"
},
"freeform": {
"key": "access:description"
},
"mappings": [
{
"if": {
"and": [
"access:description=",
"access=",
"leisure=park"
]
},
"then": {
"nl": "Dit gebied is vrij toegankelijk"
},
"hideInAnswer": true
},
{
"if": {
"and": [
"access=yes",
"fee="
]
},
"then": {
"nl": "Vrij toegankelijk"
}
},
{
"if": {
"and": [
"access=no",
"fee="
]
},
"then": {
"nl": "Niet toegankelijk"
}
},
{
"if": {
"and": [
"access=private",
"fee="
]
},
"then": {
"nl": "Niet toegankelijk, want privégebied"
}
},
{
"if": {
"and": [
"access=permissive",
"fee="
]
},
"then": {
"nl": "Toegankelijk, ondanks dat het privegebied is"
}
},
{
"if": {
"and": [
"access=guided",
"fee="
]
},
"then": {
"nl": "Enkel toegankelijk met een gids of tijdens een activiteit"
}
},
{
"if": {
"and": [
"access=yes",
"fee=yes"
]
},
"then": {
"nl": "Toegankelijk mits betaling"
}
}
]
},
{
"#": "Operator tag",
"render": {
"nl": "Beheer door {operator}"
},
"question": {
"nl": "Wie beheert dit gebied?"
},
"freeform": {
"key": "operator"
},
"mappings": [
{
"if": {
"and": [
"leisure=park",
"operator="
]
},
"then": "Beheer door de gemeente"
},
{
"if": {
"and": [
"operator=Natuurpunt"
]
},
"then": {
"nl": "<img src=\"./assets/themes/buurtnatuur/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door Natuurpunt"
}
},
{
"if": {
"and": [
"operator~(n|N)atuurpunt.*"
]
},
"then": {
"nl": "<img src=\"./assets/themes/buurtnatuur/Natuurpunt.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door {operator}"
},
"hideInAnswer": true
},
{
"if": {
"and": [
"operator=Agentschap Natuur en Bos"
]
},
"then": {
"nl": "<img src=\"./assets/themes/buurtnatuur/ANB.jpg\" style=\"width:1.5em\">Dit gebied wordt beheerd door het Agentschap Natuur en Bos"
}
}
],
"condition": {
"and": [
"leisure!~park",
"tourism!~viewpoint"
]
}
},
{
"#": "Name:nl-tag",
"render": {
"nl": "Dit gebied heet {name:nl}"
},
"question": {
"nl": "Wat is de Nederlandstalige naam van dit gebied?"
},
"freeform": {
"key": "name:nl"
},
"condition": {
"and": [
"name:nl~*",
"viewpoint!~tourism"
]
}
},
{
"#": "Name tag",
"render": {
"nl": "Dit gebied heet {name}"
},
"question": {
"nl": "Wat is de naam van dit gebied?"
},
"freeform": {
"key": "name",
"addExtraTags": [
"noname="
]
},
"condition": {
"and": [
"name:nl=",
"tourism!~viewpoint"
]
},
"mappings": [
{
"if": {
"and": [
"noname=yes",
"name="
]
},
"then": {
"nl": "Dit gebied heeft geen naam"
}
}
]
},
{
"#": "Non-editable description {description}",
"render": {
"nl": "Extra info: <i>{description}</i>"
},
"freeform": {
"key": "description"
}
},
{
"#": "Editable description {description:0}",
"question": "Is er extra info die je kwijt wil?",
"render": {
"nl": "Extra info via buurtnatuur.be: <i>{description:0}</i>"
},
"freeform": {
"key": "description:0"
}
}
]
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><g transform="translate(0.000000,511.000000) scale(0.100000,-0.100000)"><path d="M3975.1,2900.8c-550.4-468.2-999.6-866.7-999.6-885.7c0-79.1,613.7-430.2,863.6-490.3c47.5-12.6,85.4-34.8,85.4-47.5c0-19-1309.6-1154.6-1483.6-1284.3c-41.1-31.6-41.1-47.5,6.3-120.2c82.3-123.4,449.2-354.3,781.3-490.3l291-120.2l-661.1-563.1c-879.4-749.7-790.8-654.8-708.6-771.9c230.9-319.5,1236.9-752.9,2015-860.4l265.7-38v-313.2v-313.2l151.8-66.4c208.8-94.9,626.3-94.9,838.3,0l148.7,66.4v313.2v313.2l259.4,38c790.8,120.2,1594.3,449.2,1948.6,790.8c72.8,72.7,132.9,142.3,132.9,155c0,15.8-322.7,300.5-714.9,635.8l-718.1,610.5l297.3,123.3C7227-230.8,7666.6,95,7574.9,177.2c-15.8,12.6-360.6,306.8-762.4,651.6c-404.9,341.6-737,635.8-737,648.5c0,12.7,38,34.8,88.6,47.5c246.8,60.1,860.4,411.2,860.4,490.3c0,34.8-1983.4,1739.8-2024.5,1739.8C4984.2,3754.9,4522.3,3372.2,3975.1,2900.8z"/><path d="M1558.3,2015.1c-420.7-363.8-768.7-673.8-771.9-686.4c-9.5-47.5,249.9-221.4,468.2-310c120.2-50.6,230.9-101.2,243.6-110.7c12.7-12.6-240.4-246.7-563.1-521.9S349.9-132.8,349.9-154.9c0-82.3,389.1-335.3,673.8-439.7c82.3-31.6,148.7-66.4,148.7-79.1c0-12.7-240.4-227.8-534.6-477.6C340.4-1401.3,100-1622.7,100-1644.9c-3.2-63.3,256.2-262.5,515.6-392.2c284.7-142.4,680.1-268.9,1009.1-325.8l227.8-37.9l15.8-249.9c15.8-253.1,15.8-253.1,126.5-306.8c79.1-41.1,186.6-56.9,363.8-56.9s284.7,15.8,363.8,56.9c98.1,47.5,110.7,69.6,120.2,196.1l6.3,142.3L2583.2-2480c-145.5,75.9-341.7,202.4-433.4,281.5c-161.3,145.5-344.8,392.3-344.8,471.3c0,22.1,246.7,249.9,547.2,502.9c297.4,256.2,578.9,496.6,620,534.6l72.8,72.7l-262.6,136c-294.2,151.9-594.7,423.9-654.8,588.4l-34.8,101.2l695.9,594.7l692.8,591.5l-234.1,123.4c-246.7,129.7-534.6,382.8-575.7,503c-15.8,53.8,0,88.6,85.4,158.2c56.9,47.5,98.1,91.7,88.6,98c-6.3,3.2-113.9,98.1-237.3,205.6c-126.5,107.6-240.4,196.1-253.1,193C2339.7,2676.2,1982.2,2378.9,1558.3,2015.1z"/><path d="M7499,2575c-63.3-53.8-167.6-148.7-234.1-205.6l-120.2-107.6l101.2-85.4c82.2-66.4,98-101.2,82.2-155c-41.1-120.2-329-373.3-575.7-503l-234.1-123.4l692.8-591.5l695.9-594.7l-34.8-101.2c-56.9-164.5-360.6-436.5-648.5-585.2c-145.5-75.9-262.5-139.2-262.5-145.5c0-6.3,278.4-246.7,616.9-537.8c338.5-287.9,616.8-540.9,616.8-559.9c0-202.5-477.7-639-911-832c-132.9-60.1-136-63.3-126.5-205.6c9.5-129.7,22.1-151.8,120.2-199.3c79.1-41.1,186.7-56.9,363.8-56.9c177.1,0,284.7,15.8,363.8,56.9c110.7,53.8,110.7,53.8,126.5,303.7l15.8,253.1l284.7,53.8c360.6,66.5,730.7,193,1002.8,335.3c227.8,120.2,468.2,310,465,366.9c0,22.1-240.4,243.6-537.8,493.5c-294.2,249.9-534.6,465-534.6,480.8c0,12.7,31.6,34.8,72.8,47.5c256.2,75.9,749.7,385.9,749.7,468.2c0,22.1-262.5,265.7-585.2,540.9s-575.7,509.3-563.1,521.9c12.6,9.5,123.3,60.1,243.6,110.7c237.3,98.1,480.8,265.7,461.8,316.3c-15.8,41.1-1543.7,1344.4-1572.2,1344.4C7619.2,2679.4,7559.1,2632,7499,2575z"/></g></g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><path d="M334.6,797.4c0,60.1,0,120.3,0,180.4c0,9.5,0,9.5-9.8,9.5c-26.3,0-52.7-0.3-79,0.2c-7.6,0.1-9.2-2.5-9.3-9.6c-0.4-117.1-0.9-234.3-1.7-351.4c0-5.8-1.6-12-4.2-17.1c-16.6-33.5-33.8-66.8-50.6-100.3c-2.4-4.9-5.3-6.9-10.9-7.4c-37.8-3.1-73.9-12-105.4-34.4C26.5,440.8,9.3,403.9,10,358.5c0.3-21.2,4.1-41.9,11.5-61.7c3.7-9.9,3.3-18.4-0.6-28.2c-12.4-31.8-14.7-64.5-3.3-97.1c16.1-45.7,49.5-72.7,95.6-84.4c12.3-3.1,25.2-4.3,37.9-5.2c6.4-0.5,10.6-2.8,14.5-7.6c21.9-26.6,48-47.6,81.7-57.3c42.1-12.2,80.5-4.3,114.1,23.5c10.8,8.9,19.6,20.5,28.7,31.4c3.4,4,6.5,6.2,11.8,6.9c33,4.2,65,11.9,94.5,28c44.6,24.4,68.9,71.8,60.6,122.2c-2.8,16.8-8.2,33.2-13.2,49.5c-1.7,5.7-2.1,10.4,0,15.9c10,25.8,14.9,52.6,10.8,80.2c-7.3,48.4-35.6,81.3-77.9,103.2c-26.2,13.6-54.2,20-83.8,19.3c-4.5-0.1-7,1.4-8.9,5.5c-15.8,34.2-31.9,68.3-47.6,102.5c-1.5,3.3-2.1,7.4-2.1,11.2C334.5,676.6,334.5,737,334.6,797.4z M245.3,514.5c-0.5,0.6-1,1.2-1.4,1.7c14.2,24.9,28.5,49.8,43.7,76.4c14.1-26.9,27.1-51.9,41.2-79C299.4,519,272.3,519.7,245.3,514.5z"/><path d="M719.2,987.9c2.8-12.9,5.5-25.3,8.3-37.7c12.8-56.7,25.7-113.5,38.6-170.2c1.2-5.1,0.3-7-5.2-7.1c-50.2-1-100.5-2.3-150.7-3.2c-3.2-0.1-7.5,2.2-9.4,4.8c-9.5,12.8-18.6,25.9-27.2,39.3c-1.7,2.6-1.9,7.4-0.8,10.4c19.7,51.4,39.7,102.7,59.7,154c0.9,2.4,1.8,4.9,3.2,8.9c-7.7,0.4-14.5,0.9-21.3,1.2c-16.1,0.7-16.1,0.7-21.7-14.2c-17.1-44.9-34.3-89.8-51.1-134.8c-2.3-6.1-5.2-8.4-11.7-6.8c-6.1,1.5-12.3,2.5-18.6,3c-6.9,0.5-9.1,3.4-9,10.5c0.4,43.5,0.2,87,0.2,130.4c0,10.9,0,10.9-11.2,10.9c-4.3,0-8.7-0.3-13,0.1c-6.2,0.6-7.7-2.1-7.7-7.9c0.2-34.3,0.1-68.6,0.1-102.9c0-18.6-0.2-37.2,0.2-55.8c0.1-3.6,1.9-8,4.4-10.7c11.6-12.3,23.7-24.2,35.8-35.9c3.6-3.5,4.3-6.4,2.3-11.3c-9.3-23.3-18.1-46.8-27.3-70.2c-1.8-4.5-1.3-7.3,2.3-10.7c19.7-18.8,39.1-38.1,59-56.8c2.9-2.7,8.1-4.3,12.2-4.4c70.3-0.8,140.6-1.4,210.9-1.7c6.3,0,10.2-2.1,13.9-7c17.1-22.8,34.7-45.2,51.9-68c1.7-2.2,3.7-6.8,2.8-7.8c-2-2.3-5.7-3.4-8.9-4.2c-4-0.9-8.2-0.6-12.2-1.5c-10.9-2.5-18.2-15.4-14.3-25.5c0.6-1.6,4.1-2.8,6.3-2.8c13.3-0.2,26.6-0.3,39.9,0c5.8,0.1,8.6-1.5,8-7.7c-0.4-4.1-0.4-8.2,0-12.3c0.6-6.5-2.1-8.2-8.4-8c-35.7,1.3-71.5,1.5-107.2,3.4c-18.4,1-32.2-6.6-44.3-18.8c-12.7-12.8-19.6-28.5-21.6-46.4c-1.1-9.7,3.2-19,9.1-20c6.1-1,13.5,6.6,14,16.6c1.2,20.3,11.4,34.9,26.9,46.7c2.2,1.6,5.1,3.1,7.7,3.2c19.3,0.3,38.6,0.2,58,0.1c0.9,0,1.8-0.4,3.9-0.8c-1.4-2.2-2.4-3.9-3.5-5.5c-4.1-6.2-8.7-12.2-12.2-18.8c-3.8-7-4.6-14.7-2-22.5c2.3-6.8,7.2-8.4,11.8-3.1c4.8,5.6,8.5,12.2,12.4,18.5c3.6,5.7,6.1,12.2,10.4,17.3c7,8.4,15.7,13.8,27.6,13.1c11.3-0.7,22.8-0.9,34,0c16.1,1.3,28-5.4,37.9-17.1c2.5-3,4.4-6.8,7.4-8.8c3.1-2,8-4.1,10.9-2.9c2.8,1.1,4.4,6.1,5.7,9.6c0.6,1.8-0.3,4.3-1,6.3c-5.5,15.1-27.9,31-43.9,31.3c-9.3,0.2-9.3,0.2-9.3,9.9c0,16.4,0,16.4,16.5,16.4c27.3,0,54.6,0.2,81.9-0.1c6.4-0.1,8.3,1.7,9,8.4c1.6,14.5-3,23.1-16.5,30.2c-23.3,12.2-45.2,26.9-67.9,40.3c-13,7.7-20.8,18.5-24.8,33.2c-9.8,36.1-19.8,72.1-30.7,107.9c-5.4,17.8-15.4,33.3-29.4,45.8c-3.9,3.5-4.5,6.6-3,11.4c21.6,66.5,43.1,133.1,64.6,199.7c0.6,1.7,0.9,3.6,1.5,6.4c-11.7,1.1-22.7,2.6-33.7,2.9c-2,0.1-5-4.5-5.9-7.4c-10-30.7-19.7-61.6-29.5-92.4c-5.9-18.6-11.9-37.3-17.8-55.9c-0.5-1.5-1.3-2.9-2.8-6.2c-1.2,4-1.9,6.2-2.4,8.4c-11.1,48-22.2,96-33,144.1c-1.5,6.7-4.3,9.4-11.1,9.1C738.3,987.6,729.2,987.9,719.2,987.9z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><g transform="matrix(1 0 0 -1 0 1920)"><path d="M504,983v19c0,5.3,1.8,9.8,5.5,13.5c3.7,3.7,8.2,5.5,13.5,5.5h19v247.4c-17-12.9-36-19.4-57-19.4c-23.1,0-43.3,7.3-60.8,22c-17.5,14.7-28.2,33.1-32.3,55.1c-0.8,0-1.8-0.1-3.2-0.2c-1.4-0.1-2.6-0.2-3.6-0.2c-30.7,1-56.6,12.5-77.9,34.4c-21.3,21.9-31.9,48.2-31.9,78.8c0,20,4.9,38.5,14.6,55.5s22.9,30.7,39.3,41c-10.1,17.7-15.2,36.2-15.2,55.5c0,31.4,11.1,58.3,33.4,80.6c22.3,22.3,49.1,33.4,80.6,33.4c0,27.6,6.8,53.1,20.3,76.4c13.6,23.3,32,41.7,55.3,55.3c23.3,13.6,48.8,20.3,76.4,20.3c36.5,0,68.7-11.5,96.5-34.6c27.9-23.1,45.3-52.2,52.4-87.4c13.7,5.3,27.4,8,41,8c15.5,0,30.2-3,44.3-9.1c14.1-6.1,26.2-14.2,36.3-24.3s18.2-22.2,24.3-36.3c6.1-14.1,9.1-28.8,9.1-44.3c0-19.5-5.1-38.1-15.2-55.9c16.2-10.4,29.1-24,38.8-40.8c9.6-16.8,14.4-35.3,14.4-55.3c0-31.4-11.1-58.3-33.4-80.6c-22.3-22.3-49.1-33.4-80.6-33.4h-1c0,0-0.3,0.1-0.9,0.4c1.3-6.3,1.9-12.8,1.9-19.4c0-26.3-9.2-48.8-27.7-67.3S739.3,1249,713,1249c-21,0-40,6.5-57,19.4V1021h19c5.3,0,9.8-1.8,13.5-5.5c3.7-3.7,5.5-8.2,5.5-13.5v-19H504z M238,1743c-1.3,1.5-3.2,3.2-5.9,5.1c-2.7,1.9-5.7,3.9-9.1,5.9c-3.4,2-7,4.1-10.6,6.1c-3.7,2-7.3,3.9-10.8,5.7c-3.5,1.8-6.7,3.4-9.5,4.9c-2.8,1.5-5.1,2.7-6.8,3.4l-2.7,1.1c-1,0.5-1.5,1.4-1.5,2.7v1.1c0,1.3,0.6,1.9,1.9,1.9c3.3-0.5,7.5-1.3,12.5-2.3s12.7-3.2,22.8-6.5c10.1-3.3,16.7-6.7,19.8-10.3c1.8,2,4.9,4.1,9.3,6.3c4.4,2.2,9.2,4,14.2,5.5c5.1,1.5,10,2.8,14.8,4c4.8,1.1,8.7,2,11.8,2.5l4.9,0.8c1.3,0,1.9-0.6,1.9-1.9v-1.1c0-1.3-0.5-2.2-1.5-2.7C263.3,1761.4,244.8,1750.6,238,1743z M124,1629c-5.6,6.3-17.5,14.9-35.9,25.6c-18.4,10.8-35.4,19.9-51.1,27.5l-23.6,11.4c-2.3,1.3-3.4,3.2-3.4,5.7v1.9c0,2.5,1.3,3.8,3.8,3.8c2.5-0.5,5.8-1.1,9.9-1.7s11.5-2.2,22.4-4.6c10.9-2.4,21-5,30.2-7.8c9.2-2.8,18.5-6.3,27.7-10.6c9.2-4.3,15.9-8.7,19.9-13.3c5.6,6.8,17.5,13.4,35.9,19.8c18.4,6.3,35.3,10.9,50.7,13.7l23.6,4.6c2.5,0,3.8-1.3,3.8-3.8v-1.9c0-2.5-1.1-4.4-3.4-5.7c-6.6-3-15.1-7.1-25.5-12.2c-10.4-5.1-25.6-13.4-45.8-24.9C143.2,1645,130.1,1635.8,124,1629z M751,983v19c0,5.3,1.8,9.8,5.5,13.5c3.7,3.7,8.2,5.5,13.5,5.5v133.4c-11.4-7.6-24.1-11.4-38-11.4c-8.4,0-17.2,2-26.6,6.1v50.9c2.8-0.3,5.3-0.4,7.6-0.4c23.6,0,45.6,5.3,66.1,16c20.5,10.6,37.4,25.1,50.7,43.5c13.3,18.4,21.8,38.9,25.6,61.7c35.5,10.6,64.1,31.4,85.9,62.3c14.7-7.1,26.5-17.5,35.3-31.3c8.9-13.8,13.3-29.1,13.3-45.8c0-15.5-3.7-29.7-11.2-42.7c-7.5-13-17.5-23.5-30.2-31.3c2.3-7.3,3.4-14.3,3.4-20.9c0-18.7-6.6-34.8-19.9-48.1c-13.3-13.3-29.3-19.9-48.1-19.9c-13.9,0-26.6,3.8-38,11.4V1021c3.5,0,6.8-0.8,9.7-2.5c2.9-1.6,5.2-3.9,6.8-6.8s2.5-6.1,2.5-9.7v-19H751z M86,983v76c-10.4,0-19.3,3.7-26.8,11.2c-7.5,7.5-11.2,16.4-11.2,26.8s3.7,19.3,11.2,26.8c7.5,7.5,16.4,11.2,26.8,11.2h342c10.4,0,19.3-3.7,26.8-11.2c7.5-7.5,11.2-16.4,11.2-26.8s-3.7-19.3-11.2-26.8c-7.5-7.5-16.4-11.2-26.8-11.2v-76h-76v76H162v-76H86z"/></g></g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -2,6 +2,7 @@
"id": "fietsstraten", "id": "fietsstraten",
"version": "2020-08-30", "version": "2020-08-30",
"title": "Fietsstraten", "title": "Fietsstraten",
"shortDescription": "Een kaart met alle gekende fietsstraten",
"description": "Een fietsstraat is een straat waar <ul><li><b>automobilisten geen fietsers mogen inhalen</b></li><li>Er een maximumsnelheid van <b>30km/u</b> geldt</li><li>Fietsers gemotoriseerde voortuigen links mogen inhalen</li><li>Fietsers nog steeds voorrang aan rechts moeten verlenen - ook aan auto's en voetgangers op het zebrapad</li></ul><br/><br/>Op deze open kaart kan je alle gekende fietsstraten zien en kan je ontbrekende fietsstraten aanduiden. Om de kaart aan te passen, moet je je aanmelden met OpenStreetMap en helemaal inzoomen tot straatniveau.", "description": "Een fietsstraat is een straat waar <ul><li><b>automobilisten geen fietsers mogen inhalen</b></li><li>Er een maximumsnelheid van <b>30km/u</b> geldt</li><li>Fietsers gemotoriseerde voortuigen links mogen inhalen</li><li>Fietsers nog steeds voorrang aan rechts moeten verlenen - ook aan auto's en voetgangers op het zebrapad</li></ul><br/><br/>Op deze open kaart kan je alle gekende fietsstraten zien en kan je ontbrekende fietsstraten aanduiden. Om de kaart aan te passen, moet je je aanmelden met OpenStreetMap en helemaal inzoomen tot straatniveau.",
"icon": "./assets/themes/cyclestreets/F111.svg", "icon": "./assets/themes/cyclestreets/F111.svg",

View file

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

View file

@ -0,0 +1,30 @@
{
"id": "cyclofix",
"title": {
"en": "Cyclofix - an open map for cyclists",
"nl": "Cyclofix - een open kaart voor fietsers",
"fr": "Cyclofix - Une carte ouverte pour les cyclistes",
"gl": "Cyclofix - Un mapa aberto para os ciclistas",
"de": "Cyclofix - eine offene Karte für Radfahrer"
},
"description": {
"en": "The goal of this map is to present cyclists with an easy-to-use solution to find the appropriate infrastructure for their needs.<br><br>You can track your precise location (mobile only) and select layers that are relevant for you in the bottom left corner. You can also use this tool to add or edit pins (points of interest) to the map and provide more data by answering the questions.<br><br>All changes you make will automatically be saved in the global database of OpenStreetMap and can be freely re-used by others.<br><br>For more information about the cyclofix project, go to <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
"nl": "Het doel van deze kaart is om fietsers een gebruiksvriendelijke oplossing te bieden voor het vinden van de juiste infrastructuur voor hun behoeften.<br><br>U kunt uw exacte locatie volgen (enkel mobiel) en in de linkerbenedenhoek categorieën selecteren die voor u relevant zijn. U kunt deze tool ook gebruiken om 'spelden' aan de kaart toe te voegen of te bewerken en meer gegevens te verstrekken door de vragen te beantwoorden.<br><br>Alle wijzigingen die u maakt worden automatisch opgeslagen in de wereldwijde database van OpenStreetMap en kunnen door anderen vrij worden hergebruikt.<br><br>Bekijk voor meer info over cyclofix ook <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
"fr": "Le but de cette carte est de présenter aux cyclistes une solution facile à utiliser pour trouver l'infrastructure appropriée à leurs besoins.<br><br>Vous pouvez suivre votre localisation précise (mobile uniquement) et sélectionner les couches qui vous concernent dans le coin inférieur gauche. Vous pouvez également utiliser cet outil pour ajouter ou modifier des épingles (points d'intérêt) sur la carte et fournir plus de données en répondant aux questions.<br><br>Toutes les modifications que vous apportez seront automatiquement enregistrées dans la base de données mondiale d'OpenStreetMap et peuvent être librement réutilisées par d'autres.<br><br>Pour plus d'informations sur le projet cyclofix, rendez-vous sur <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
"gl": "O obxectivo deste mapa é amosar ós ciclistas unha solución doada de empregar para atopar a infraestrutura axeitada para as súas necesidades.<br><br>Podes obter a túa localización precisa (só para dispositivos móbiles) e escoller as capas que sexan relevantes para ti na esquina inferior esquerda. Tamén podes empregar esta ferramenta para engadir ou editar puntos de interese ó mapa e fornecer máis datos respondendo as cuestións.<br><br>Todas as modificacións que fagas serán gardadas de xeito automático na base de datos global do OpenStreetMap e outros poderán reutilizalos libremente.<br><br>Para máis información sobre o proxecto cyclofix, vai a <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>.",
"de": "Das Ziel dieser Karte ist es, den Radfahrern eine einfach zu benutzende Lösung zu präsentieren, um die geeignete Infrastruktur für ihre Bedürfnisse zu finden.<br><br>Sie können Ihren genauen Standort verfolgen (nur mobil) und in der linken unteren Ecke die für Sie relevanten Ebenen auswählen. Sie können dieses Tool auch verwenden, um Pins (Points of Interest/Interessante Orte) zur Karte hinzuzufügen oder zu bearbeiten und mehr Daten durch Beantwortung der Fragen bereitstellen.<br><br>Alle Änderungen, die Sie vornehmen, werden automatisch in der globalen Datenbank von OpenStreetMap gespeichert und können von anderen frei wiederverwendet werden.<br><br>Weitere Informationen über das Projekt Cyclofix finden Sie unter <a href='https://cyclofix.osm.be/'>cyclofix.osm.be</a>."
},
"language": ["en", "nl", "fr", "gl","de"],
"maintainer": "MapComplete",
"icon": "./assets/themes/cyclofix/logo.svg",
"version": "0",
"startLat": 50.8465573,
"startLon": 4.3516970,
"startZoom": 16,
"widenFactor": 0.05,
"socialImage": "./assets/themes/cyclofix/logo.svg",
"layers": ["bike_repair_station", "bike_cafes", "bike_shops", "drinking_water", "bike_parking","bike_themed_object"],
"roamingRenderings": []
}

View file

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View file

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

View file

@ -7,6 +7,7 @@ import {UIEventSource} from "./Logic/UIEventSource";
import * as $ from "jquery"; import * as $ from "jquery";
import {FromJSON} from "./Customizations/JSON/FromJSON"; import {FromJSON} from "./Customizations/JSON/FromJSON";
import {TagRendering} from "./UI/TagRendering"; import {TagRendering} from "./UI/TagRendering";
import {State} from "./State";
TagRendering.injectFunction(); TagRendering.injectFunction();
@ -18,6 +19,8 @@ if (location.href.startsWith("http://buurtnatuur.be")) {
window.location.replace("https://buurtnatuur.be"); window.location.replace("https://buurtnatuur.be");
} }
let testing: UIEventSource<string>; let testing: UIEventSource<string>;
if (location.hostname === "localhost" || location.hostname === "127.0.0.1") { if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
testing = QueryParameters.GetQueryParameter("test", "true"); testing = QueryParameters.GetQueryParameter("test", "true");

View file

@ -9,6 +9,9 @@ import {FromJSON} from "../Customizations/JSON/FromJSON";
import {And, Tag} from "../Logic/Tags"; import {And, Tag} from "../Logic/Tags";
import Locale from "../UI/i18n/Locale"; import Locale from "../UI/i18n/Locale";
import Translations from "../UI/i18n/Translations"; import Translations from "../UI/i18n/Translations";
import {TagRenderingOptions} from "../Customizations/TagRenderingOptions";
import {UIEventSource} from "../Logic/UIEventSource";
import {TagRendering} from "../UI/TagRendering";
new T([ new T([
@ -64,9 +67,57 @@ new T([
equal(undefined, tr.GetContent({"foo": "bar"})); equal(undefined, tr.GetContent({"foo": "bar"}));
})], })],
[ [
"Select right value test", "Empty match test",
() => { () => {
const t = new Tag("key","");
equal(false, t.matches([{k: "key", v:"somevalue"}]))
}
],
[
"Tagrendering test",
() => {
const def = {
"render": {
"nl": "De toegankelijkheid van dit gebied is: {access:description}"
},
"question": {
"nl": "Is dit gebied toegankelijk?"
},
"freeform": {
"key": "access:description"
},
"mappings": [
{
"if": {
"and": [
"access:description=",
"access=",
"leisure=park"
]
},
"then": {
"nl": "Dit gebied is vrij toegankelijk"
},
"hideInAnswer": true
},
{
"if":"access=no",
"then":"Niet toegankelijk"
}
]
};
const constr = FromJSON.TagRendering(def, "test");
TagRendering.injectFunction();
const uiEl = constr.construct({
tags: new UIEventSource<any>(
{leisure: "park", "access": "no"})
});
const rendered = uiEl.InnerRender();
equal(true, rendered.indexOf("Niet toegankelijk") > 0)
} }
] ]