Various bug fixes and updates
This commit is contained in:
parent
97ec893479
commit
e069b31e4e
29 changed files with 482 additions and 148 deletions
|
@ -17,6 +17,7 @@ import * as viewpoint from "../../assets/layers/viewpoint/viewpoint.json"
|
||||||
import * as bike_parking from "../../assets/layers/bike_parking/bike_parking.json"
|
import * as bike_parking from "../../assets/layers/bike_parking/bike_parking.json"
|
||||||
import * as bike_repair_station from "../../assets/layers/bike_repair_station/bike_repair_station.json"
|
import * as bike_repair_station from "../../assets/layers/bike_repair_station/bike_repair_station.json"
|
||||||
import * as birdhides from "../../assets/layers/bird_hide/birdhides.json"
|
import * as birdhides from "../../assets/layers/bird_hide/birdhides.json"
|
||||||
|
import * as nature_reserve from "../../assets/layers/nature_reserve/nature_reserve.json"
|
||||||
|
|
||||||
import {Utils} from "../../Utils";
|
import {Utils} from "../../Utils";
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ export class FromJSON {
|
||||||
FromJSON.Layer(bike_parking),
|
FromJSON.Layer(bike_parking),
|
||||||
FromJSON.Layer(bike_repair_station),
|
FromJSON.Layer(bike_repair_station),
|
||||||
FromJSON.Layer(birdhides),
|
FromJSON.Layer(birdhides),
|
||||||
|
FromJSON.Layer(nature_reserve),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const layer of sharedLayersList) {
|
for (const layer of sharedLayersList) {
|
||||||
|
@ -102,7 +104,6 @@ export class FromJSON {
|
||||||
public static TagRenderingWithDefault(json: TagRenderingConfigJson | string, propertyName, defaultValue: string): TagDependantUIElementConstructor {
|
public static TagRenderingWithDefault(json: TagRenderingConfigJson | string, propertyName, defaultValue: string): TagDependantUIElementConstructor {
|
||||||
if (json === undefined) {
|
if (json === undefined) {
|
||||||
if(defaultValue !== undefined){
|
if(defaultValue !== undefined){
|
||||||
console.log(`Using default value ${defaultValue} for ${propertyName}`)
|
|
||||||
return FromJSON.TagRendering(defaultValue, propertyName);
|
return FromJSON.TagRendering(defaultValue, propertyName);
|
||||||
}
|
}
|
||||||
throw `Tagrendering ${propertyName} is undefined...`
|
throw `Tagrendering ${propertyName} is undefined...`
|
||||||
|
@ -207,7 +208,7 @@ export class FromJSON {
|
||||||
return new Tag(tag[0], tag[1]);
|
return new Tag(tag[0], tag[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Tag(json: AndOrTagConfigJson | string, context: string): TagsFilter {
|
public static Tag(json: AndOrTagConfigJson | string, context: string = ""): TagsFilter {
|
||||||
if(json === undefined){
|
if(json === undefined){
|
||||||
throw "Error while parsing a tag: nothing defined. Make sure all the tags are defined and at least one tag is present in a complex expression"
|
throw "Error while parsing a tag: nothing defined. Make sure all the tags are defined and at least one tag is present in a complex expression"
|
||||||
}
|
}
|
||||||
|
@ -286,7 +287,6 @@ export class FromJSON {
|
||||||
|
|
||||||
private static LayerUncaught(json: LayerConfigJson): LayerDefinition {
|
private static LayerUncaught(json: LayerConfigJson): LayerDefinition {
|
||||||
|
|
||||||
console.log("Parsing layer", json)
|
|
||||||
const tr = FromJSON.Translation;
|
const tr = FromJSON.Translation;
|
||||||
const overpassTags = FromJSON.Tag(json.overpassTags, "overpasstags for layer "+json.id);
|
const overpassTags = FromJSON.Tag(json.overpassTags, "overpasstags for layer "+json.id);
|
||||||
const icon = FromJSON.TagRenderingWithDefault(json.icon, "icon", "./assets/bug.svg");
|
const icon = FromJSON.TagRenderingWithDefault(json.icon, "icon", "./assets/bug.svg");
|
||||||
|
@ -381,6 +381,7 @@ export class FromJSON {
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
layer.maxAllowedOverlapPercentage = json.hideUnderlayingFeaturesMinPercentage;
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,14 @@ export interface LayerConfigJson {
|
||||||
*/
|
*/
|
||||||
wayHandling?: number;
|
wayHandling?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consider that we want to show 'Nature Reserves' and 'Forests'. Now, ofter, there are pieces of forest mapped _in_ the nature reserve.
|
||||||
|
* Now, showing those pieces of forest overlapping with the nature reserve truly clutters the map and is very user-unfriendly.
|
||||||
|
*
|
||||||
|
* The features are placed layer by layer. If a feature below a feature on this layer overlaps for more then 'x'-percent, the underlying feature is hidden.
|
||||||
|
*/
|
||||||
|
hideUnderlayingFeaturesMinPercentage?:number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Presets for this layer
|
* Presets for this layer
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -130,46 +130,4 @@ export class LayerDefinition {
|
||||||
this.wayHandling = options.wayHandling ?? LayerDefinition.WAYHANDLING_DEFAULT;
|
this.wayHandling = options.wayHandling ?? LayerDefinition.WAYHANDLING_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
ToJson() {
|
|
||||||
|
|
||||||
function t(translation: string | Translation | UIElement) {
|
|
||||||
if (translation === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (typeof (translation) === "string") {
|
|
||||||
return translation;
|
|
||||||
}
|
|
||||||
if (translation instanceof Translation && translation.translations !== undefined) {
|
|
||||||
return translation.translations;
|
|
||||||
}
|
|
||||||
return translation.InnerRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
function tr(tagRendering : TagRenderingOptions) : TagRenderingConfigJson{
|
|
||||||
const o = tagRendering.options;
|
|
||||||
return {
|
|
||||||
key: o.freeform.key,
|
|
||||||
render: o.freeform.renderTemplate,
|
|
||||||
type: o.freeform.template.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const layerConfig : LayerConfigJson = {
|
|
||||||
name: t(this.name),
|
|
||||||
description: t(this.description),
|
|
||||||
maxAllowedOverlapPercentage: this.maxAllowedOverlapPercentage,
|
|
||||||
presets: this.presets,
|
|
||||||
icon: this.icon,
|
|
||||||
minzoom: this.minzoom,
|
|
||||||
overpassFilter: this.overpassFilter,
|
|
||||||
title: this.title,
|
|
||||||
elementsToShow: this.elementsToShow,
|
|
||||||
style: this.style,
|
|
||||||
wayHandling: this.wayHandling,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
return JSON.stringify(layerConfig)
|
|
||||||
}*/
|
|
||||||
}
|
}
|
|
@ -35,7 +35,7 @@ export class Bos extends LayerDefinition {
|
||||||
|
|
||||||
this.minzoom = 13;
|
this.minzoom = 13;
|
||||||
this.style = this.generateStyleFunction();
|
this.style = this.generateStyleFunction();
|
||||||
this.title = new NameInline("bos");
|
this.title = new NameInline("Bos");
|
||||||
this.elementsToShow = [
|
this.elementsToShow = [
|
||||||
new ImageCarouselWithUploadConstructor(),
|
new ImageCarouselWithUploadConstructor(),
|
||||||
new NameQuestion(),
|
new NameQuestion(),
|
||||||
|
|
|
@ -26,7 +26,7 @@ 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 = this.generateStyleFunction();
|
||||||
this.elementsToShow = [
|
this.elementsToShow = [
|
||||||
new ImageCarouselWithUploadConstructor(),
|
new ImageCarouselWithUploadConstructor(),
|
||||||
|
|
|
@ -13,7 +13,7 @@ export class Park extends LayerDefinition {
|
||||||
question: "Is dit park publiek toegankelijk?",
|
question: "Is dit park publiek toegankelijk?",
|
||||||
mappings: [
|
mappings: [
|
||||||
{k: new Tag("access", "yes"), txt: "Publiek toegankelijk"},
|
{k: new Tag("access", "yes"), txt: "Publiek toegankelijk"},
|
||||||
{k: new Tag("access", ""), 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", "no"), txt: "Niet publiek toegankelijk"},
|
||||||
{k: new Tag("access", "private"), txt: "Niet publiek toegankelijk, want privaat"},
|
{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"},
|
{k: new Tag("access", "guided"), txt: "Enkel toegankelijk met een gids of op een activiteit"},
|
||||||
|
@ -59,7 +59,7 @@ export class Park extends LayerDefinition {
|
||||||
|
|
||||||
this.minzoom = 13;
|
this.minzoom = 13;
|
||||||
this.style = this.generateStyleFunction();
|
this.style = this.generateStyleFunction();
|
||||||
this.title = new NameInline("park");
|
this.title = new NameInline("Park");
|
||||||
this.elementsToShow = [
|
this.elementsToShow = [
|
||||||
new ImageCarouselWithUploadConstructor(),
|
new ImageCarouselWithUploadConstructor(),
|
||||||
new NameQuestion(),
|
new NameQuestion(),
|
||||||
|
|
|
@ -168,12 +168,12 @@ export class Widths extends LayerDefinition {
|
||||||
|
|
||||||
let dashArray = undefined;
|
let dashArray = undefined;
|
||||||
if (props.onewayBike) {
|
if (props.onewayBike) {
|
||||||
dashArray = [20, 8]
|
dashArray = [5, 6]
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
icon: null,
|
icon: null,
|
||||||
color: c,
|
color: c,
|
||||||
weight: 9,
|
weight: 5,
|
||||||
dashArray: dashArray
|
dashArray: dashArray
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {NatureReserves} from "../Layers/NatureReserves";
|
|
||||||
import {Park} from "../Layers/Park";
|
import {Park} from "../Layers/Park";
|
||||||
import {Bos} from "../Layers/Bos";
|
import {Bos} from "../Layers/Bos";
|
||||||
import {Layout} from "../Layout";
|
import {Layout} from "../Layout";
|
||||||
|
import {NatureReserves} from "../Layers/NatureReserves";
|
||||||
|
|
||||||
export class Groen extends Layout {
|
export class Groen extends Layout {
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ export class OnlyShowIfConstructor implements TagDependantUIElementConstructor{
|
||||||
}
|
}
|
||||||
|
|
||||||
GetContent(tags: any): Translation {
|
GetContent(tags: any): Translation {
|
||||||
if(this.IsKnown(tags)){
|
if(!this.IsKnown(tags)){
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return this._embedded.GetContent(tags);
|
return this._embedded.GetContent(tags);
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class AccessTag extends TagRenderingOptions {
|
||||||
{k: new And([new Tag("access", "no"), new Tag("fee", "")]), txt: "Niet 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", "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", "permissive"), new Tag("fee", "")]), txt: "Toegankelijk, maar het is privegebied"},
|
||||||
{k: new And([new Tag("access", "guided"), new Tag("fee", "")]), txt: "Enkel met gids of op activiteit"},
|
{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"),
|
k: new And([new Tag("access", "yes"),
|
||||||
new Tag("fee", "yes")]),
|
new Tag("fee", "yes")]),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {Tag} from "../../Logic/Tags";
|
import {RegexTag, Tag} from "../../Logic/Tags";
|
||||||
import Translations from "../../UI/i18n/Translations";
|
import Translations from "../../UI/i18n/Translations";
|
||||||
import {TagRenderingOptions} from "../TagRenderingOptions";
|
import {TagRenderingOptions} from "../TagRenderingOptions";
|
||||||
import Translation from "../../UI/i18n/Translation";
|
import Translation from "../../UI/i18n/Translation";
|
||||||
|
@ -8,18 +8,10 @@ export class NameInline extends TagRenderingOptions{
|
||||||
|
|
||||||
constructor(category: string | Translation ) {
|
constructor(category: string | Translation ) {
|
||||||
super({
|
super({
|
||||||
question: "",
|
|
||||||
|
|
||||||
freeform: {
|
|
||||||
renderTemplate: "{name}",
|
|
||||||
template: Translations.t.general.nameInlineQuestion.Subs({category: category}),
|
|
||||||
key: "name",
|
|
||||||
extraTags: new Tag("noname", "") // Remove 'noname=yes'
|
|
||||||
},
|
|
||||||
|
|
||||||
mappings: [
|
mappings: [
|
||||||
{k: new Tag("noname","yes"), txt: Translations.t.general.noNameCategory.Subs({category: category})},
|
{k: new Tag("noname", "yes"), txt: Translations.t.general.noNameCategory.Subs({category: category})},
|
||||||
{k: null, txt: category}
|
{k: new RegexTag("name", /.+/), txt: "{name}"},
|
||||||
|
{k:new Tag("name",""), txt: category}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
* One is a big 'name-question', the other is the 'edit name' in the title.
|
* One is a big 'name-question', the other is the 'edit name' in the title.
|
||||||
* THis one is the big question
|
* THis one is the big question
|
||||||
*/
|
*/
|
||||||
import {Tag} from "../../Logic/Tags";
|
import {And, Tag} from "../../Logic/Tags";
|
||||||
import {TagRenderingOptions} from "../TagRenderingOptions";
|
import {TagRenderingOptions} from "../TagRenderingOptions";
|
||||||
|
|
||||||
export class NameQuestion extends TagRenderingOptions{
|
export class NameQuestion extends TagRenderingOptions {
|
||||||
|
|
||||||
static options = {
|
constructor() {
|
||||||
|
super({
|
||||||
priority: 10, // Move this last on the priority list, in order to prevent ppl to enter access restrictions and descriptions
|
priority: 10, // Move this last on the priority list, in order to prevent ppl to enter access restrictions and descriptions
|
||||||
question: "Wat is de <i>officiële</i> naam van dit gebied?<br><span class='question-subtext'>" +
|
question: "Wat is de <i>officiële</i> naam van dit gebied?<br><span class='question-subtext'>" +
|
||||||
"Zelf een naam bedenken wordt afgeraden.<br/>" +
|
"Zelf een naam bedenken wordt afgeraden.<br/>" +
|
||||||
|
@ -17,17 +18,14 @@ export class NameQuestion extends TagRenderingOptions{
|
||||||
freeform: {
|
freeform: {
|
||||||
key: "name",
|
key: "name",
|
||||||
template: "De naam is $$$",
|
template: "De naam is $$$",
|
||||||
renderTemplate: "", // We don't actually render it, only ask
|
renderTemplate: "Dit gebied heet <i>{name}</i>",
|
||||||
placeholder: "",
|
placeholder: "",
|
||||||
extraTags: new Tag("noname","")
|
extraTags: new Tag("noname", "")
|
||||||
},
|
},
|
||||||
mappings: [
|
mappings: [
|
||||||
{k: new Tag("noname", "yes"), txt: "Dit gebied heeft geen naam"},
|
{k: new And([new Tag("name", ""), new Tag("noname", "yes")]), txt: "Dit gebied heeft geen naam"},
|
||||||
]
|
]
|
||||||
}
|
});
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super(NameQuestion.options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import {Img} from "../../UI/Img";
|
import {Img} from "../../UI/Img";
|
||||||
import {Tag} from "../../Logic/Tags";
|
import {RegexTag, Tag} from "../../Logic/Tags";
|
||||||
import {TagRenderingOptions} from "../TagRenderingOptions";
|
import {TagRenderingOptions} from "../TagRenderingOptions";
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ export class OsmLink extends TagRenderingOptions {
|
||||||
placeholder: "",
|
placeholder: "",
|
||||||
},
|
},
|
||||||
mappings: [
|
mappings: [
|
||||||
{k: new Tag("id", "node/-1"), txt: "<span class='alert'>Uploading</span>"}
|
{k: new RegexTag("id", /node\/-.+/), txt: "<span class='alert'>Uploading</span>"}
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,15 +18,14 @@ import Translation from "../UI/i18n/Translation";
|
||||||
import Combine from "../UI/Base/Combine";
|
import Combine from "../UI/Base/Combine";
|
||||||
|
|
||||||
|
|
||||||
export class
|
export class TagRendering extends UIElement implements TagDependantUIElement {
|
||||||
TagRendering extends UIElement implements TagDependantUIElement {
|
|
||||||
|
|
||||||
|
|
||||||
private readonly _priority: number;
|
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 }[];
|
||||||
|
|
||||||
private currentTags : UIEventSource<any> ;
|
private currentTags: UIEventSource<any>;
|
||||||
|
|
||||||
|
|
||||||
private readonly _freeform: {
|
private readonly _freeform: {
|
||||||
|
@ -110,7 +109,6 @@ TagRendering extends UIElement implements TagDependantUIElement {
|
||||||
|
|
||||||
for (const choice of options.mappings ?? []) {
|
for (const choice of options.mappings ?? []) {
|
||||||
|
|
||||||
|
|
||||||
let choiceSubbed = {
|
let choiceSubbed = {
|
||||||
k: choice.k?.substituteValues(this.currentTags.data),
|
k: choice.k?.substituteValues(this.currentTags.data),
|
||||||
txt: choice.txt,
|
txt: choice.txt,
|
||||||
|
@ -225,7 +223,7 @@ TagRendering extends UIElement implements TagDependantUIElement {
|
||||||
}
|
}
|
||||||
previousTexts.push(this.ApplyTemplate(mapping.txt));
|
previousTexts.push(this.ApplyTemplate(mapping.txt));
|
||||||
|
|
||||||
elements.push(this.InputElementForMapping(mapping));
|
elements.push(this.InputElementForMapping(mapping, mapping.substitute));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,14 +245,26 @@ TagRendering extends UIElement implements TagDependantUIElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private InputElementForMapping(mapping: { k: TagsFilter, txt: (string | Translation) }) {
|
private InputElementForMapping(mapping: { k: TagsFilter, txt: (string | Translation) }, substituteValues: boolean) {
|
||||||
|
if (substituteValues) {
|
||||||
|
|
||||||
return new FixedInputElement(this.ApplyTemplate(mapping.txt),
|
return new FixedInputElement(this.ApplyTemplate(mapping.txt),
|
||||||
mapping.k.substituteValues(this.currentTags.data)
|
mapping.k.substituteValues(this.currentTags.data),
|
||||||
|
(t0, t1) => t0.isEquivalent(t1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return new FixedInputElement(this.ApplyTemplate(mapping.txt),mapping.k,
|
||||||
|
(t0, t1) => t0.isEquivalent(t1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private InputForFreeForm(freeform): InputElement<TagsFilter> {
|
private InputForFreeForm(freeform : {
|
||||||
|
key: string,
|
||||||
|
template: string | Translation,
|
||||||
|
renderTemplate: string | Translation,
|
||||||
|
placeholder?: string | Translation,
|
||||||
|
extraTags?: TagsFilter,
|
||||||
|
}): InputElement<TagsFilter> {
|
||||||
if (freeform?.template === undefined) {
|
if (freeform?.template === undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -283,7 +293,7 @@ TagRendering extends UIElement implements TagDependantUIElement {
|
||||||
const tag = new Tag(freeform.key, formatter(string, this._source.data._country));
|
const tag = new Tag(freeform.key, formatter(string, this._source.data._country));
|
||||||
|
|
||||||
if (tag.value.length > 255) {
|
if (tag.value.length > 255) {
|
||||||
return undefined; // Toolong
|
return undefined; // Too long
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freeform.extraTags === undefined) {
|
if (freeform.extraTags === undefined) {
|
||||||
|
@ -299,7 +309,13 @@ TagRendering extends UIElement implements TagDependantUIElement {
|
||||||
const toString =
|
const toString =
|
||||||
(tag) => {
|
(tag) => {
|
||||||
if (tag instanceof And) {
|
if (tag instanceof And) {
|
||||||
return toString(tag.and[0])
|
for (const subtag of tag.and) {
|
||||||
|
if(subtag instanceof Tag && subtag.key === freeform.key){
|
||||||
|
return subtag.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
} else if (tag instanceof Tag) {
|
} else if (tag instanceof Tag) {
|
||||||
return tag.value
|
return tag.value
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,9 +222,14 @@ export class FilteredLayer {
|
||||||
color: style.color
|
color: style.color
|
||||||
});
|
});
|
||||||
|
|
||||||
|
} else if (style.icon.iconUrl.startsWith("$circle ")) {
|
||||||
|
marker = L.circle(latLng, {
|
||||||
|
radius: 25,
|
||||||
|
color: style.color
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if(style.icon.iconSize === undefined){
|
if (style.icon.iconSize === undefined) {
|
||||||
style.icon.iconSize = [50,50]
|
style.icon.iconSize = [50, 50]
|
||||||
}
|
}
|
||||||
|
|
||||||
marker = L.marker(latLng, {
|
marker = L.marker(latLng, {
|
||||||
|
@ -253,11 +258,7 @@ export class FilteredLayer {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self._geolayer.setStyle(function (featureX) {
|
self._geolayer.setStyle(function (featureX) {
|
||||||
const style = self._style(featureX.properties);
|
return self._style(featureX.properties);
|
||||||
if (featureX === feature) {
|
|
||||||
console.log("Selected element is", featureX.properties.id)
|
|
||||||
}
|
|
||||||
return style;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,9 @@ export abstract class TagsFilter {
|
||||||
abstract matches(tags: { k: string, v: string }[]): boolean
|
abstract matches(tags: { k: string, v: string }[]): boolean
|
||||||
abstract asOverpass(): string[]
|
abstract asOverpass(): string[]
|
||||||
abstract substituteValues(tags: any) : TagsFilter;
|
abstract substituteValues(tags: any) : TagsFilter;
|
||||||
abstract isUsableAsAnswer() : boolean;
|
abstract isUsableAsAnswer(): boolean;
|
||||||
|
|
||||||
|
abstract isEquivalent(other: TagsFilter): boolean;
|
||||||
|
|
||||||
matchesProperties(properties: Map<string, string>): boolean {
|
matchesProperties(properties: Map<string, string>): boolean {
|
||||||
return this.matches(TagUtils.proprtiesToKV(properties));
|
return this.matches(TagUtils.proprtiesToKV(properties));
|
||||||
|
@ -58,7 +60,7 @@ export class RegexTag extends TagsFilter {
|
||||||
return this.invert;
|
return this.invert;
|
||||||
}
|
}
|
||||||
|
|
||||||
substituteValues(tags: any) : TagsFilter{
|
substituteValues(tags: any): TagsFilter {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +70,16 @@ export class RegexTag extends TagsFilter {
|
||||||
}
|
}
|
||||||
return `~${this.key.source}${this.invert ? "!" : ""}~${RegexTag.source(this.value)}`
|
return `~${this.key.source}${this.invert ? "!" : ""}~${RegexTag.source(this.value)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEquivalent(other: TagsFilter): boolean {
|
||||||
|
if (other instanceof RegexTag) {
|
||||||
|
return other.asHumanString() == this.asHumanString();
|
||||||
|
}
|
||||||
|
if(other instanceof Tag){
|
||||||
|
return RegexTag.doesMatch(other.key, this.key) && RegexTag.doesMatch(other.value, this.value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,6 +152,16 @@ export class Tag extends TagsFilter {
|
||||||
isUsableAsAnswer(): boolean {
|
isUsableAsAnswer(): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEquivalent(other: TagsFilter): boolean {
|
||||||
|
if(other instanceof Tag){
|
||||||
|
return this.key === other.key && this.value === other.value;
|
||||||
|
}
|
||||||
|
if(other instanceof RegexTag){
|
||||||
|
other.isEquivalent(this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,6 +209,24 @@ export class Or extends TagsFilter {
|
||||||
isUsableAsAnswer(): boolean {
|
isUsableAsAnswer(): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEquivalent(other: TagsFilter): boolean {
|
||||||
|
if(other instanceof Or){
|
||||||
|
|
||||||
|
for (const selfTag of this.or) {
|
||||||
|
let matchFound = false;
|
||||||
|
for (let i = 0; i < other.or.length && !matchFound; i++){
|
||||||
|
let otherTag = other.or[i];
|
||||||
|
matchFound = selfTag.isEquivalent(otherTag);
|
||||||
|
}
|
||||||
|
if(!matchFound){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -256,6 +296,24 @@ export class And extends TagsFilter {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEquivalent(other: TagsFilter): boolean {
|
||||||
|
if(other instanceof And){
|
||||||
|
|
||||||
|
for (const selfTag of this.and) {
|
||||||
|
let matchFound = false;
|
||||||
|
for (let i = 0; i < other.and.length && !matchFound; i++){
|
||||||
|
let otherTag = other.and[i];
|
||||||
|
matchFound = selfTag.isEquivalent(otherTag);
|
||||||
|
}
|
||||||
|
if(!matchFound){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
2
State.ts
2
State.ts
|
@ -23,7 +23,7 @@ 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.7j";
|
public static vNumber = "0.0.7k";
|
||||||
|
|
||||||
// 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 = {
|
||||||
|
|
|
@ -10,6 +10,8 @@ import {UserDetails} from "../../Logic/Osm/OsmConnection";
|
||||||
import {MultiInput} from "../Input/MultiInput";
|
import {MultiInput} from "../Input/MultiInput";
|
||||||
import TagRenderingPanel from "./TagRenderingPanel";
|
import TagRenderingPanel from "./TagRenderingPanel";
|
||||||
import SingleSetting from "./SingleSetting";
|
import SingleSetting from "./SingleSetting";
|
||||||
|
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||||
|
import {FromJSON} from "../../Customizations/JSON/FromJSON";
|
||||||
|
|
||||||
export default class AllLayersPanel extends UIElement {
|
export default class AllLayersPanel extends UIElement {
|
||||||
|
|
||||||
|
@ -49,9 +51,22 @@ export default class AllLayersPanel extends UIElement {
|
||||||
|
|
||||||
const layers = this._config.data.layers;
|
const layers = this._config.data.layers;
|
||||||
for (let i = 0; i < layers.length; i++) {
|
for (let i = 0; i < layers.length; i++) {
|
||||||
|
|
||||||
tabs.push({
|
tabs.push({
|
||||||
header: "<img src='./assets/bug.svg'>",
|
header: new VariableUiElement(this._config.map((config: LayoutConfigJson) => {
|
||||||
|
const layer = config.layers[i];
|
||||||
|
if (typeof layer !== "string") {
|
||||||
|
try {
|
||||||
|
const iconTagRendering = FromJSON.TagRendering(layer.icon, "icon");
|
||||||
|
const icon = iconTagRendering.GetContent({"id": "node/-1"}).txt;
|
||||||
|
return `<img src='${icon}'>`
|
||||||
|
} catch (e) {
|
||||||
|
return "<img src='./assets/bug.svg'>"
|
||||||
|
// Nothing to do here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "<img src='./assets/help.svg'>"
|
||||||
|
|
||||||
|
})),
|
||||||
content: new LayerPanelWithPreview(this._config, this.languages, i, userDetails)
|
content: new LayerPanelWithPreview(this._config, this.languages, i, userDetails)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ export class GenerateEmpty {
|
||||||
title: {},
|
title: {},
|
||||||
description: {},
|
description: {},
|
||||||
tagRenderings: [],
|
tagRenderings: [],
|
||||||
|
hideUnderlayingFeaturesMinPercentage: 0,
|
||||||
icon: {
|
icon: {
|
||||||
render: "./assets/bug.svg"
|
render: "./assets/bug.svg"
|
||||||
},
|
},
|
||||||
|
|
|
@ -96,7 +96,10 @@ export default class LayerPanel extends UIElement {
|
||||||
{value: 2, shown: "Show both the ways/areas and the centerpoints"},
|
{value: 2, shown: "Show both the ways/areas and the centerpoints"},
|
||||||
{value: 1, shown: "Show everything as centerpoint"}]), "wayHandling", "Way handling",
|
{value: 1, shown: "Show everything as centerpoint"}]), "wayHandling", "Way handling",
|
||||||
"Describes how ways and areas are represented on the map: areas can be represented as the area itself, or it can be converted into the centerpoint"),
|
"Describes how ways and areas are represented on the map: areas can be represented as the area itself, or it can be converted into the centerpoint"),
|
||||||
|
setting(TextField.NumberInput("nat", n => n <= 100), "hideUnderlayingFeaturesMinPercentage", "Max allowed overlap percentage",
|
||||||
|
"Consider that we want to show 'Nature Reserves' and 'Forests'. Now, ofter, there are pieces of forest mapped _in_ the nature reserve.<br/>" +
|
||||||
|
"Now, showing those pieces of forest overlapping with the nature reserve truly clutters the map and is very user-unfriendly.<br/>" +
|
||||||
|
"The features are placed layer by layer. If a feature below a feature on this layer overlaps for more then 'x'-percent, the underlying feature is hidden."),
|
||||||
setting(new AndOrTagInput(), "overpassTags", "Overpass query",
|
setting(new AndOrTagInput(), "overpassTags", "Overpass query",
|
||||||
"The tags of the objects to load from overpass"),
|
"The tags of the objects to load from overpass"),
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ import {UserDetails} from "../../Logic/Osm/OsmConnection";
|
||||||
|
|
||||||
export default class LayerPanelWithPreview extends UIElement{
|
export default class LayerPanelWithPreview extends UIElement{
|
||||||
private panel: UIElement;
|
private panel: UIElement;
|
||||||
|
|
||||||
constructor(config: UIEventSource<any>, languages: UIEventSource<string[]>, index: number, userDetails: UserDetails) {
|
constructor(config: UIEventSource<any>, languages: UIEventSource<string[]>, index: number, userDetails: UserDetails) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ export default class TagRenderingPanel extends InputElement<TagRenderingConfigJs
|
||||||
|
|
||||||
"<h3>Mappings</h3>",
|
"<h3>Mappings</h3>",
|
||||||
setting(new MultiInput<{ if: AndOrTagConfigJson, then: (string | any), hideInAnswer?: boolean }>("Add a mapping",
|
setting(new MultiInput<{ if: AndOrTagConfigJson, then: (string | any), hideInAnswer?: boolean }>("Add a mapping",
|
||||||
() => ({if: undefined, then: undefined}),
|
() => ({if: {and: []}, then: {}}),
|
||||||
() => new MappingInput(languages, options?.disableQuestions ?? false),
|
() => new MappingInput(languages, options?.disableQuestions ?? false),
|
||||||
undefined, {allowMovement: true}), "mappings",
|
undefined, {allowMovement: true}), "mappings",
|
||||||
"If a tag matches, then show the first respective text", "")
|
"If a tag matches, then show the first respective text", "")
|
||||||
|
|
|
@ -7,9 +7,13 @@ export class FixedInputElement<T> extends InputElement<T> {
|
||||||
private readonly rendering: UIElement;
|
private readonly rendering: UIElement;
|
||||||
private readonly value: UIEventSource<T>;
|
private readonly value: UIEventSource<T>;
|
||||||
public readonly IsSelected : UIEventSource<boolean> = new UIEventSource<boolean>(false);
|
public readonly IsSelected : UIEventSource<boolean> = new UIEventSource<boolean>(false);
|
||||||
|
private readonly _comparator: (t0: T, t1: T) => boolean;
|
||||||
|
|
||||||
constructor(rendering: UIElement | string, value: T) {
|
constructor(rendering: UIElement | string,
|
||||||
|
value: T,
|
||||||
|
comparator: ((t0: T, t1: T) => boolean ) = undefined) {
|
||||||
super(undefined);
|
super(undefined);
|
||||||
|
this._comparator = comparator ?? ((t0, t1) => t0 == t1);
|
||||||
this.value = new UIEventSource<T>(value);
|
this.value = new UIEventSource<T>(value);
|
||||||
this.rendering = typeof (rendering) === 'string' ? new FixedUiElement(rendering) : rendering;
|
this.rendering = typeof (rendering) === 'string' ? new FixedUiElement(rendering) : rendering;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +26,9 @@ export class FixedInputElement<T> extends InputElement<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
IsValid(t: T): boolean {
|
IsValid(t: T): boolean {
|
||||||
return t == this.value.data;
|
|
||||||
|
console.log("Comparing ",t, "with", this.value.data);
|
||||||
|
return this._comparator(t, this.value.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected InnerUpdate(htmlElement: HTMLElement) {
|
protected InnerUpdate(htmlElement: HTMLElement) {
|
||||||
|
|
|
@ -8,14 +8,15 @@ export class RadioButton<T> extends InputElement<T> {
|
||||||
private readonly _selectedElementIndex: UIEventSource<number>
|
private readonly _selectedElementIndex: UIEventSource<number>
|
||||||
= new UIEventSource<number>(null);
|
= new UIEventSource<number>(null);
|
||||||
|
|
||||||
private value: UIEventSource<T>;
|
private readonly value: UIEventSource<T>;
|
||||||
private readonly _elements: InputElement<T>[]
|
private readonly _elements: InputElement<T>[]
|
||||||
private _selectFirstAsDefault: boolean;
|
private readonly _selectFirstAsDefault: boolean;
|
||||||
|
|
||||||
|
|
||||||
constructor(elements: InputElement<T>[],
|
constructor(elements: InputElement<T>[],
|
||||||
selectFirstAsDefault = true) {
|
selectFirstAsDefault = true) {
|
||||||
super(undefined);
|
super(undefined);
|
||||||
|
console.log("Created new radiobutton with values ", elements)
|
||||||
this._elements = Utils.NoNull(elements);
|
this._elements = Utils.NoNull(elements);
|
||||||
this._selectFirstAsDefault = selectFirstAsDefault;
|
this._selectFirstAsDefault = selectFirstAsDefault;
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
|
@ -54,6 +54,9 @@ export class SimpleAddUI extends UIElement {
|
||||||
if (typeof (preset.icon) !== "string") {
|
if (typeof (preset.icon) !== "string") {
|
||||||
const tags = Utils.MergeTags(TagUtils.KVtoProperties(preset.tags), {id:"node/-1"});
|
const tags = Utils.MergeTags(TagUtils.KVtoProperties(preset.tags), {id:"node/-1"});
|
||||||
icon = preset.icon.GetContent(tags).txt;
|
icon = preset.icon.GetContent(tags).txt;
|
||||||
|
if(icon.startsWith("$")){
|
||||||
|
icon = undefined;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
icon = preset.icon;
|
icon = preset.icon;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ export abstract class UIElement extends UIEventSource<string> {
|
||||||
|
|
||||||
public dumbMode = false;
|
public dumbMode = false;
|
||||||
|
|
||||||
|
private lastInnerRender: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In the 'deploy'-step, some code needs to be run by ts-node.
|
* In the 'deploy'-step, some code needs to be run by ts-node.
|
||||||
* However, ts-node crashes when it sees 'document'. When running from console, we flag this and disable all code where document is needed.
|
* However, ts-node crashes when it sees 'document'. When running from console, we flag this and disable all code where document is needed.
|
||||||
|
@ -37,6 +39,7 @@ export abstract class UIElement extends UIEventSource<string> {
|
||||||
this.dumbMode = false;
|
this.dumbMode = false;
|
||||||
const self = this;
|
const self = this;
|
||||||
source.addCallback(() => {
|
source.addCallback(() => {
|
||||||
|
self.lastInnerRender = undefined;
|
||||||
self.Update();
|
self.Update();
|
||||||
})
|
})
|
||||||
return this;
|
return this;
|
||||||
|
@ -92,7 +95,7 @@ export abstract class UIElement extends UIEventSource<string> {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setData(this.InnerRender());
|
this.setData(this.lastInnerRender ?? this.InnerRender());
|
||||||
element.innerHTML = this.data;
|
element.innerHTML = this.data;
|
||||||
|
|
||||||
if (this._hideIfEmpty) {
|
if (this._hideIfEmpty) {
|
||||||
|
@ -151,14 +154,15 @@ export abstract class UIElement extends UIEventSource<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Render(): string {
|
Render(): string {
|
||||||
|
this.lastInnerRender = this.lastInnerRender ?? this.InnerRender();
|
||||||
if (this.dumbMode) {
|
if (this.dumbMode) {
|
||||||
return this.InnerRender();
|
return this.lastInnerRender;
|
||||||
}
|
}
|
||||||
let style = "";
|
let style = "";
|
||||||
if (this.style !== undefined && this.style !== "") {
|
if (this.style !== undefined && this.style !== "") {
|
||||||
style = `style="${this.style}"`;
|
style = `style="${this.style}"`;
|
||||||
}
|
}
|
||||||
return `<span class='uielement ${this.clss.join(" ")}' ${style} id='${this.id}'>${this.InnerRender()}</span>`
|
return `<span class='uielement ${this.clss.join(" ")}' ${style} id='${this.id}'>${this.lastInnerRender}</span>`
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachTo(divId: string) {
|
AttachTo(divId: string) {
|
||||||
|
|
|
@ -52,7 +52,12 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"service:bicycle:pump:operational_status=broken",
|
"service:bicycle:pump:operational_status=broken",
|
||||||
"service:bicycle:tools=no"
|
{
|
||||||
|
"or": [
|
||||||
|
"service:bicycle:tools=no",
|
||||||
|
"service:bicycle:tools="
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -381,7 +386,12 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"service:bicycle:pump=yes",
|
"service:bicycle:pump=yes",
|
||||||
"service:bicycle:tools=no"
|
{
|
||||||
|
"or": [
|
||||||
|
"service:bicycle:tools=no",
|
||||||
|
"service:bicycle:tools="
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": "./assets/layers/bike_repair_station/pump.svg"
|
"then": "./assets/layers/bike_repair_station/pump.svg"
|
||||||
|
|
252
assets/layers/nature_reserve/nature_reserve.json
Normal file
252
assets/layers/nature_reserve/nature_reserve.json
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
{
|
||||||
|
"id": "nature_reserve_simple",
|
||||||
|
"name": "Layer",
|
||||||
|
"minzoom": 10,
|
||||||
|
"overpassTags": {
|
||||||
|
"or": [
|
||||||
|
"leisure=nature_reserve",
|
||||||
|
"boundary=protected_area"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"name~*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Natuurgebied <i>{name}</i>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"render": {
|
||||||
|
"nl": "Natuurgebied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"nl": "Een natuurreservaat is een gebied dat wordt beheerd door Natuurpunt, ANB of een privépersoon zodat deze biodiversiteit bevordert. "
|
||||||
|
},
|
||||||
|
"tagRenderings": [
|
||||||
|
{
|
||||||
|
"question": {
|
||||||
|
"nl": "Is dit gebied vrij toegankelijk?"
|
||||||
|
},
|
||||||
|
"freeform": {
|
||||||
|
"key": "access:description",
|
||||||
|
"addExtraTags": []
|
||||||
|
},
|
||||||
|
"render": {
|
||||||
|
"nl": "De toegankelijkheid van dit gebied is {access:description}"
|
||||||
|
},
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"access=yes",
|
||||||
|
"fee="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Publiek toegankelijk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"access=no",
|
||||||
|
"fee="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Niet publiek toegankelijk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"access=guided",
|
||||||
|
"fee="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Enkel met gids of op activiteit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"access=private",
|
||||||
|
"fee="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Niet toegankelijk privégebied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"access=permissive",
|
||||||
|
"fee="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Toegankelijk, maar het is privégebied"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"access=yes",
|
||||||
|
"fee=yes"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Toegankelijk mits betaling"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"render": {
|
||||||
|
"nl": "Beheer door {operator}"
|
||||||
|
},
|
||||||
|
"question": {
|
||||||
|
"nl": "Wie beheert dit natuurgebied?"
|
||||||
|
},
|
||||||
|
"freeform": {
|
||||||
|
"key": "operator"
|
||||||
|
},
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"operator=Natuurpunt"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Beheer door Natuurpunt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"operator=Agenstchap Natuur en Bos"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Beheer door het Agentschap Natuur en Bos (ANB)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": {
|
||||||
|
"nl": "<b>Wat is de <i>officiële</i> naam van dit natuurgebied?</b><br/><span class='subtle'>Sommige gebieden hebben geen naam</span>"
|
||||||
|
},
|
||||||
|
"freeform": {
|
||||||
|
"key": "name",
|
||||||
|
"addExtraTags": [
|
||||||
|
"noname="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"render": {
|
||||||
|
"nl": "Dit gebied heet <i>{name}</i>"
|
||||||
|
},
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"noname=yes",
|
||||||
|
"name="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"nl": "Dit gebied heeft geen naam"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"condition": {
|
||||||
|
"and": [
|
||||||
|
"name:nl="
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"render": {
|
||||||
|
"nl": "De naam van dit gebied is {name:nl}"
|
||||||
|
},
|
||||||
|
"freeform": {
|
||||||
|
"key": "name:nl"
|
||||||
|
},
|
||||||
|
"question": {
|
||||||
|
"nl": "Wat is de Nederlandstalige naam van dit gebied?"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"and": [
|
||||||
|
"name:nl~*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"render": {
|
||||||
|
"nl": "Meer uitleg:<br/><i>{description:0}</i>"
|
||||||
|
},
|
||||||
|
"question": {
|
||||||
|
"nl": "Zijn er nog opmerkingen of vermeldenswaardigheden?"
|
||||||
|
},
|
||||||
|
"freeform": {
|
||||||
|
"key": "description:0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"icon": {
|
||||||
|
"render": "$circle"
|
||||||
|
},
|
||||||
|
"width": {
|
||||||
|
"render": "3"
|
||||||
|
},
|
||||||
|
"iconSize": {
|
||||||
|
"render": "40,40,center"
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"render": "#c90014",
|
||||||
|
"mappings": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"name~*",
|
||||||
|
"operator~*",
|
||||||
|
"access~*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": "#37c65b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"and": [
|
||||||
|
"name~*",
|
||||||
|
"access~*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"then": "#c98d00"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"presets": [
|
||||||
|
{
|
||||||
|
"tags": [
|
||||||
|
"leisure=nature_reserve"
|
||||||
|
],
|
||||||
|
"title": {
|
||||||
|
"nl": "Natuurreservaat"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"nl": "Voeg een ontbrekend, erkend natuurreservaat toe, bv. een gebied dat beheerd wordt door het ANB of natuurpunt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hideUnderlayingFeaturesMinPercentage": 10
|
||||||
|
}
|
|
@ -54,14 +54,22 @@ new T([
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
condition: "x="
|
condition: "x="
|
||||||
});
|
}, "");
|
||||||
|
|
||||||
equal(true, tr.IsKnown({"noname": "yes"}));
|
equal(true, tr.IsKnown({"noname": "yes"}));
|
||||||
equal(true, tr.IsKnown({"name": "ABC"}));
|
equal(true, tr.IsKnown({"name": "ABC"}));
|
||||||
equal(false, tr.IsKnown({"foo": "bar"}));
|
equal(false, tr.IsKnown({"foo": "bar"}));
|
||||||
equal("Has no name", tr.GetContent({"noname": "yes"}));
|
equal("Has no name", tr.GetContent({"noname": "yes"})?.txt);
|
||||||
equal("Ook een xyz", tr.GetContent({"name": "xyz"}));
|
equal("Ook een xyz", tr.GetContent({"name": "xyz"})?.txt);
|
||||||
equal("Ook een {name}", tr.GetContent({"foo": "bar"}));
|
equal(undefined, tr.GetContent({"foo": "bar"}));
|
||||||
|
|
||||||
|
})],
|
||||||
|
[
|
||||||
|
"Select right value test",
|
||||||
|
() => {
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
})]
|
|
||||||
]);
|
]);
|
||||||
|
|
Loading…
Reference in a new issue