forked from MapComplete/MapComplete
Merge master into translations
This commit is contained in:
commit
a730345b16
77 changed files with 43519 additions and 1619 deletions
|
@ -1,22 +1,32 @@
|
|||
import {Groen} from "./Layouts/Groen";
|
||||
import {Toilets} from "./Layouts/Toilets";
|
||||
import {GRB} from "./Layouts/GRB";
|
||||
import {Statues} from "./Layouts/Statues";
|
||||
import {Bookcases} from "./Layouts/Bookcases";
|
||||
import { Groen } from "./Layouts/Groen";
|
||||
import { Toilets } from "./Layouts/Toilets";
|
||||
import { GRB } from "./Layouts/GRB";
|
||||
import { Statues } from "./Layouts/Statues";
|
||||
import { Bookcases } from "./Layouts/Bookcases";
|
||||
import Cyclofix from "./Layouts/Cyclofix";
|
||||
import {All} from "./Layouts/All";
|
||||
import {Layout} from "./Layout";
|
||||
import { WalkByBrussels } from "./Layouts/WalkByBrussels";
|
||||
import { All } from "./Layouts/All";
|
||||
import { Layout } from "./Layout";
|
||||
import {MetaMap} from "./Layouts/MetaMap";
|
||||
import {Widths} from "./Layers/Widths";
|
||||
import {StreetWidth} from "./Layouts/StreetWidth";
|
||||
import {NatureReserves} from "./Layers/NatureReserves";
|
||||
import {Natuurpunt} from "./Layouts/Natuurpunt";
|
||||
|
||||
export class AllKnownLayouts {
|
||||
public static allSets = AllKnownLayouts.AllLayouts();
|
||||
|
||||
private static AllLayouts(): Map<string, Layout> {
|
||||
const all = new All();
|
||||
const layouts : Layout[] = [
|
||||
const layouts: Layout[] = [
|
||||
new Groen(),
|
||||
new GRB(),
|
||||
new Cyclofix(),
|
||||
new Bookcases(),
|
||||
new WalkByBrussels(),
|
||||
new MetaMap(),
|
||||
new StreetWidth(),
|
||||
new Natuurpunt(),
|
||||
all
|
||||
/*new Toilets(),
|
||||
new Statues(),
|
||||
|
@ -29,4 +39,13 @@ export class AllKnownLayouts {
|
|||
}
|
||||
return allSets;
|
||||
}
|
||||
|
||||
public static GetSets(layoutNames): any {
|
||||
const all = new All();
|
||||
for (const name of layoutNames) {
|
||||
all.layers = all.layers.concat(AllKnownLayouts.allSets[name].layers);
|
||||
}
|
||||
|
||||
return all;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,16 @@ export class LayerDefinition {
|
|||
*/
|
||||
elementsToShow: TagDependantUIElementConstructor[];
|
||||
|
||||
style: (tags: any) => { color: string, icon: any };
|
||||
/**
|
||||
* A simple styling for the geojson element
|
||||
* color is the color for areas and ways
|
||||
* icon is the Leaflet icon
|
||||
* Note that this is passed entirely to leaflet, so other leaflet attributes work too
|
||||
*/
|
||||
style: (tags: any) => {
|
||||
color: string,
|
||||
icon: any,
|
||||
};
|
||||
|
||||
/**
|
||||
* If an object of the next layer is contained for this many percent in this feature, it is eaten and not shown
|
||||
|
@ -64,6 +73,36 @@ export class LayerDefinition {
|
|||
maxAllowedOverlapPercentage: number = undefined;
|
||||
|
||||
|
||||
constructor(options: {
|
||||
name: string,
|
||||
newElementTags: Tag[],
|
||||
icon: string,
|
||||
minzoom: number,
|
||||
overpassFilter: TagsFilter,
|
||||
title?: TagRenderingOptions,
|
||||
elementsToShow?: TagDependantUIElementConstructor[],
|
||||
maxAllowedOverlapPercentage?: number,
|
||||
style?: (tags: any) => {
|
||||
color: string,
|
||||
icon: any
|
||||
}
|
||||
} = undefined) {
|
||||
if (options === undefined) {
|
||||
console.log("No options!")
|
||||
return;
|
||||
}
|
||||
this.name = options.name;
|
||||
this.maxAllowedOverlapPercentage = options.maxAllowedOverlapPercentage ?? 0;
|
||||
this.newElementTags = options.newElementTags;
|
||||
this.icon = options.icon;
|
||||
this.minzoom = options.minzoom;
|
||||
this.overpassFilter = options.overpassFilter;
|
||||
this.title = options.title;
|
||||
this.elementsToShow = options.elementsToShow;
|
||||
this.style = options.style;
|
||||
console.log(this)
|
||||
}
|
||||
|
||||
asLayer(basemap: Basemap, allElements: ElementStorage, changes: Changes, userDetails: UIEventSource<UserDetails>, selectedElement: UIEventSource<any>,
|
||||
showOnPopup: (tags: UIEventSource<(any)>) => UIElement):
|
||||
FilteredLayer {
|
||||
|
|
|
@ -10,7 +10,7 @@ import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWi
|
|||
export default class BikeParkings extends LayerDefinition {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "bike_parking";
|
||||
this.name = "bike parking";
|
||||
this.icon = "./assets/bike/parking.svg";
|
||||
this.overpassFilter = new Tag("amenity", "bicycle_parking");
|
||||
this.newElementTags = [
|
||||
|
@ -20,10 +20,10 @@ export default class BikeParkings extends LayerDefinition {
|
|||
|
||||
this.minzoom = 13;
|
||||
this.style = this.generateStyleFunction();
|
||||
this.title = new FixedText("Fietsparking");
|
||||
this.title = new FixedText("Bicycle parking");
|
||||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
new OperatorTag(),
|
||||
// new OperatorTag(),
|
||||
new ParkingType()
|
||||
];
|
||||
|
||||
|
@ -36,7 +36,8 @@ export default class BikeParkings extends LayerDefinition {
|
|||
color: "#00bb00",
|
||||
icon: L.icon({
|
||||
iconUrl: self.icon,
|
||||
iconSize: [50, 50]
|
||||
iconSize: [50, 50],
|
||||
iconAnchor: [25,50]
|
||||
})
|
||||
};
|
||||
};
|
||||
|
|
112
Customizations/Layers/BikeShop.ts
Normal file
112
Customizations/Layers/BikeShop.ts
Normal file
|
@ -0,0 +1,112 @@
|
|||
import {TagRenderingOptions} from "../TagRendering";
|
||||
import {LayerDefinition} from "../LayerDefinition";
|
||||
import {Tag} from "../../Logic/TagsFilter";
|
||||
import L from "leaflet";
|
||||
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||
import {NameQuestion} from "../Questions/NameQuestion";
|
||||
|
||||
export class BikeShop extends LayerDefinition {
|
||||
|
||||
|
||||
private readonly sellsBikes = new Tag("service:bicycle:retail", "yes");
|
||||
private readonly repairsBikes = new Tag("service:bicycle:repair", "yes");
|
||||
|
||||
constructor() {
|
||||
super(
|
||||
{
|
||||
name: "bike shop or repair",
|
||||
icon: "assets/bike/repair_shop.svg",
|
||||
minzoom: 14,
|
||||
overpassFilter: new Tag("shop", "bicycle"),
|
||||
newElementTags: [new Tag("shop", "bicycle")]
|
||||
}
|
||||
);
|
||||
|
||||
this.title = new TagRenderingOptions({
|
||||
mappings: [
|
||||
{k: this.sellsBikes, txt: "Bicycle shop"},
|
||||
{k: new Tag("service:bicycle:retail", "no"), txt: "Bicycle repair"},
|
||||
{k: new Tag("service:bicycle:retail", ""), txt: "Bicycle repair/shop"},
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
new TagRenderingOptions({
|
||||
question: "What is the name of this bicycle shop?",
|
||||
freeform: {
|
||||
key: "name",
|
||||
renderTemplate: "The name of this bicycle shop is {name}",
|
||||
template: "The name of this bicycle shop is $$$"
|
||||
}
|
||||
}),
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Can one buy a bike here?",
|
||||
mappings: [
|
||||
{k: this.sellsBikes, txt: "Bikes are sold here"},
|
||||
{k: new Tag("service:bicycle:retail", "no"), txt: "No bikes are sold here"},
|
||||
]
|
||||
}),
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Can one buy a new bike here?",
|
||||
mappings: [
|
||||
{k: new Tag("service:bicycle:second_hand", "yes"), txt: "Second-hand bikes are sold here"},
|
||||
{k: new Tag("service:bicycle:second_hand", "only"), txt: "All bicycles sold here are second-hand"},
|
||||
{k: new Tag("service:bicycle:second_hand", "no"), txt: "Only brand new bikes are sold here"},
|
||||
]
|
||||
}).OnlyShowIf(this.sellsBikes),
|
||||
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Does this shop repair bicycles?",
|
||||
mappings: [
|
||||
{k: this.repairsBikes, txt: "Bikes are repaired here, by the shop owner (for a fee)"},
|
||||
{k: new Tag("service:bicycle:repair", "only_sold"), txt: "Only bikes that were bought here, are repaired"},
|
||||
{k: new Tag("service:bicycle:repair", "brand"), txt: "Only bikes of a fixed brand are repaired here"},
|
||||
{k: new Tag("service:bicycle:repair", "no"), txt: "Bikes are not repaired here"},
|
||||
]
|
||||
}),
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Can one hire a new bike here?",
|
||||
mappings: [
|
||||
{k: new Tag("service:bicycle:rental", "yes"), txt: "Bikes can be rented here"},
|
||||
{k: new Tag("service:bicycle:rental", "no"), txt: "Bikes cannot be rented here"},
|
||||
]
|
||||
}).OnlyShowIf(this.sellsBikes),
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Are there tools here so that one can repair their own bike?",
|
||||
mappings: [
|
||||
{k: new Tag("service:bicycle:diy", "yes"), txt: "Tools for DIY are available here"},
|
||||
{k: new Tag("service:bicycle:diy", "no"), txt: "No tools for DIY are available here"},
|
||||
]
|
||||
}),
|
||||
]
|
||||
|
||||
|
||||
this.style = (tags) => {
|
||||
let icon = "assets/bike/repair_shop.svg";
|
||||
|
||||
if (this.sellsBikes.matchesProperties(tags)) {
|
||||
icon = "assets/bike/shop.svg";
|
||||
}
|
||||
|
||||
return {
|
||||
color: "#ff0000",
|
||||
icon: L.icon({
|
||||
iconUrl: icon,
|
||||
iconSize: [50, 50],
|
||||
iconAnchor: [25, 50]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -17,7 +17,7 @@ import PumpValves from "../Questions/bike/PumpValves";
|
|||
export default class BikeStations extends LayerDefinition {
|
||||
private readonly pump = new Tag("service:bicycle:pump", "yes");
|
||||
private readonly pumpOperationalAny = new Tag("service:bicycle:pump:operational_status", "yes");
|
||||
private readonly pumpOperationalOk = new Or([new Tag("service:bicycle:pump:operational_status", "yes"), new Tag("service:bicycle:pump:operational_status", "operational"), new Tag("service:bicycle:pump:operational_status", "ok")]);
|
||||
private readonly pumpOperationalOk = new Or([new Tag("service:bicycle:pump:operational_status", "yes"), new Tag("service:bicycle:pump:operational_status", "operational"), new Tag("service:bicycle:pump:operational_status", "ok"), new Tag("service:bicycle:pump:operational_status", "")]);
|
||||
private readonly tools = new Tag("service:bicycle:tools", "yes");
|
||||
|
||||
constructor() {
|
||||
|
@ -31,7 +31,6 @@ export default class BikeStations extends LayerDefinition {
|
|||
|
||||
this.newElementTags = [
|
||||
new Tag("amenity", "bicycle_repair_station")
|
||||
// new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")
|
||||
];
|
||||
this.maxAllowedOverlapPercentage = 10;
|
||||
|
||||
|
@ -60,7 +59,7 @@ export default class BikeStations extends LayerDefinition {
|
|||
const self = this;
|
||||
return function (properties: any) {
|
||||
const hasPump = self.pump.matchesProperties(properties)
|
||||
const isOperational = !self.pumpOperationalAny.matchesProperties(properties) || self.pumpOperationalOk.matchesProperties(properties)
|
||||
const isOperational = self.pumpOperationalOk.matchesProperties(properties)
|
||||
const hasTools = self.tools.matchesProperties(properties)
|
||||
let iconName = ""
|
||||
if (hasPump) {
|
||||
|
@ -74,14 +73,19 @@ export default class BikeStations extends LayerDefinition {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
iconName = "repair_station.svg"
|
||||
if (!self.pump.matchesProperties(properties)) {
|
||||
iconName = "repair_station.svg"
|
||||
} else {
|
||||
iconName = "repair_station.svg"
|
||||
}
|
||||
}
|
||||
const iconUrl = `./assets/bike/${iconName}`
|
||||
return {
|
||||
color: "#00bb00",
|
||||
icon: L.icon({
|
||||
iconUrl: iconUrl,
|
||||
iconSize: [50, 50]
|
||||
iconSize: [50, 50],
|
||||
iconAnchor: [25,50]
|
||||
})
|
||||
};
|
||||
};
|
||||
|
|
146
Customizations/Layers/Birdhide.ts
Normal file
146
Customizations/Layers/Birdhide.ts
Normal file
|
@ -0,0 +1,146 @@
|
|||
import {LayerDefinition} from "../LayerDefinition";
|
||||
import {And, Or, Tag} from "../../Logic/TagsFilter";
|
||||
import {TagRenderingOptions} from "../TagRendering";
|
||||
import FixedText from "../Questions/FixedText";
|
||||
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||
import L from "leaflet";
|
||||
|
||||
export class Birdhide extends LayerDefinition {
|
||||
|
||||
private static readonly birdhide = new Tag("leisure", "bird_hide");
|
||||
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
name: "vogelkijkplaats",
|
||||
overpassFilter: Birdhide.birdhide,
|
||||
elementsToShow: [new FixedText("hi")],
|
||||
icon: "assets/nature/birdhide.svg",
|
||||
minzoom: 12,
|
||||
newElementTags: [Birdhide.birdhide],
|
||||
style(tags: any): { color: string; icon: any } {
|
||||
return {color: "", icon: undefined};
|
||||
},
|
||||
});
|
||||
|
||||
function rmStart(toRemove: string, title: string): string {
|
||||
if (title.toLowerCase().indexOf(toRemove.toLowerCase()) == 0) {
|
||||
return title.substr(toRemove.length).trim();
|
||||
}
|
||||
return title;
|
||||
|
||||
}
|
||||
|
||||
function rmStarts(toRemove: string[], title: string) {
|
||||
for (const toRm of toRemove) {
|
||||
title = rmStart(toRm, title);
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
this.title = new TagRenderingOptions({
|
||||
tagsPreprocessor: (tags) => {
|
||||
if (tags.name) {
|
||||
const nm =
|
||||
rmStarts(
|
||||
["Vogelkijkhut", "Vogelkijkwand", "Kijkwand", "Kijkhut"],
|
||||
tags.name);
|
||||
|
||||
tags.name = " '" + nm + "'";
|
||||
} else {
|
||||
tags.name = "";
|
||||
}
|
||||
},
|
||||
mappings: [
|
||||
{
|
||||
k: new And([new Tag("shelter", "no"), new Tag("building", "")]),
|
||||
txt: "Vogelkijkwand{name}"
|
||||
},
|
||||
{
|
||||
k: new And([new Tag("amenity", "shelter"), new Tag("building", "yes")]),
|
||||
txt: "Vogelijkhut{name}"
|
||||
},
|
||||
{
|
||||
k: new Tag("amenity", "shelter"),
|
||||
txt: "Vogelijkhut{name}"
|
||||
},
|
||||
{
|
||||
k: new Tag("building", "yes"),
|
||||
txt: "Vogelijkhut{name}"
|
||||
},
|
||||
{k: null, txt: "Vogelkijkplaats{name}"}
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
this.style = (properties) => {
|
||||
let icon = "assets/nature/birdhide.svg";
|
||||
if (new Or([new Tag("amenity", "shelter"), new Tag("building", "yes"), new Tag("shelter", "yes")]).matchesProperties(properties)) {
|
||||
icon = "assets/nature/birdshelter.svg";
|
||||
}
|
||||
|
||||
return {
|
||||
color: "#0000bb",
|
||||
icon: L.icon({
|
||||
iconUrl: icon,
|
||||
iconSize: [40,40],
|
||||
iconAnchor: [20,20]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Is dit een kijkwand of kijkhut?",
|
||||
mappings: [
|
||||
{
|
||||
k: new And([new Tag("shelter", "no"), new Tag("building", ""), new Tag("amenity", "")]),
|
||||
txt: "Vogelkijkwand"
|
||||
},
|
||||
{
|
||||
k: new And([new Tag("amenity", "shelter"), new Tag("building", "yes"), new Tag("shelter", "yes")]),
|
||||
txt: "Vogelijkhut"
|
||||
}
|
||||
]
|
||||
}),
|
||||
new TagRenderingOptions({
|
||||
question: "Is ze rolstoeltoegankelijk?",
|
||||
mappings: [
|
||||
{
|
||||
k: new Tag("wheelchair", "no"),
|
||||
txt: "Niet rolstoeltoegankelijk"
|
||||
},
|
||||
{
|
||||
k: new Tag("wheelchair", "limited"),
|
||||
txt: "Een rolstoel raakt er, maar het is niet makkelijk"
|
||||
},
|
||||
{
|
||||
k: new Tag("wheelchair", "yes"),
|
||||
txt: "Een rolstoel raakt er gemakkelijk"
|
||||
}
|
||||
]
|
||||
}),
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Wie beheert deze?",
|
||||
freeform: {
|
||||
key: "operator",
|
||||
template: "Beheer door $$$",
|
||||
renderTemplate: "Beheer door {operator}",
|
||||
placeholder: "organisatie"
|
||||
},
|
||||
mappings: [
|
||||
{k: new Tag("operator", "Natuurpunt"), txt: "Natuurpunt"},
|
||||
{k: new Tag("operator", "Agentschap Natuur en Bos"), txt: "het Agentschap Natuur en Bos (ANB)"},
|
||||
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
];
|
||||
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import {QuestionDefinition} from "../../Logic/Question";
|
|||
import {TagRenderingOptions} from "../TagRendering";
|
||||
import {NameInline} from "../Questions/NameInline";
|
||||
import {NameQuestion} from "../Questions/NameQuestion";
|
||||
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||
|
||||
export class Bookcases extends LayerDefinition {
|
||||
|
||||
|
@ -19,7 +20,7 @@ export class Bookcases extends LayerDefinition {
|
|||
|
||||
this.title = new NameInline("ruilboekenkastje");
|
||||
this.elementsToShow = [
|
||||
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
new TagRenderingOptions({
|
||||
question: "Heeft dit boekenruilkastje een naam?",
|
||||
freeform: {
|
||||
|
|
62
Customizations/Layers/DrinkingWater.ts
Normal file
62
Customizations/Layers/DrinkingWater.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import {LayerDefinition} from "../LayerDefinition";
|
||||
import {And, Or, Tag} from "../../Logic/TagsFilter";
|
||||
import {OperatorTag} from "../Questions/OperatorTag";
|
||||
import * as L from "leaflet";
|
||||
import FixedText from "../Questions/FixedText";
|
||||
import {TagRenderingOptions} from "../TagRendering";
|
||||
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||
|
||||
export class DrinkingWater extends LayerDefinition {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "drinking water";
|
||||
this.icon = "./assets/bike/drinking_water.svg";
|
||||
|
||||
this.overpassFilter = new Or([
|
||||
new And([
|
||||
new Tag("amenity", "drinking_water")
|
||||
])
|
||||
]);
|
||||
|
||||
|
||||
this.newElementTags = [
|
||||
new Tag("amenity", "drinking_water"),
|
||||
];
|
||||
this.maxAllowedOverlapPercentage = 10;
|
||||
|
||||
this.minzoom = 13;
|
||||
this.style = this.generateStyleFunction();
|
||||
this.title = new FixedText("Drinking water");
|
||||
this.elementsToShow = [
|
||||
new OperatorTag(),
|
||||
];
|
||||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
new TagRenderingOptions({
|
||||
question: "How easy is it to fill water bottles?",
|
||||
mappings: [
|
||||
{ k: new Tag("bottle", "yes"), txt: "It is easy to refill water bottles" },
|
||||
{ k: new Tag("bottle", "no"), txt: "Water bottles may not fit" }
|
||||
],
|
||||
})];
|
||||
|
||||
}
|
||||
|
||||
|
||||
private generateStyleFunction() {
|
||||
const self = this;
|
||||
return function (properties: any) {
|
||||
|
||||
return {
|
||||
color: "#00bb00",
|
||||
icon: new L.icon({
|
||||
iconUrl: self.icon,
|
||||
iconSize: [50, 50],
|
||||
iconAnchor: [25,50]
|
||||
})
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -52,19 +52,13 @@ export class GrbToFix extends LayerDefinition {
|
|||
|
||||
question: "Wat is het huisnummer?",
|
||||
tagsPreprocessor: tags => {
|
||||
const newTags = {};
|
||||
newTags["addr:housenumber"] = tags["addr:housenumber"]
|
||||
newTags["addr:street"] = tags["addr:street"]
|
||||
|
||||
const telltale = "GRB thinks that this has number ";
|
||||
const index = tags.fixme.indexOf(telltale);
|
||||
if (index >= 0) {
|
||||
const housenumber = tags.fixme.slice(index + telltale.length);
|
||||
newTags["grb:housenumber:human"] = housenumber;
|
||||
newTags["grb:housenumber"] = housenumber == "no number" ? "" : housenumber;
|
||||
tags["grb:housenumber:human"] = housenumber;
|
||||
tags["grb:housenumber"] = housenumber == "no number" ? "" : housenumber;
|
||||
}
|
||||
|
||||
return newTags;
|
||||
},
|
||||
freeform: {
|
||||
key: "addr:housenumber",
|
||||
|
|
117
Customizations/Layers/InformationBoard.ts
Normal file
117
Customizations/Layers/InformationBoard.ts
Normal file
|
@ -0,0 +1,117 @@
|
|||
import {LayerDefinition} from "../LayerDefinition";
|
||||
import FixedText from "../Questions/FixedText";
|
||||
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||
import {TagRenderingOptions} from "../TagRendering";
|
||||
import {And, Tag} from "../../Logic/TagsFilter";
|
||||
import L from "leaflet";
|
||||
|
||||
export class InformationBoard extends LayerDefinition {
|
||||
constructor() {
|
||||
super({
|
||||
name: "Informatiebord",
|
||||
minzoom: 12,
|
||||
overpassFilter: new Tag("tourism", "information"),
|
||||
newElementTags: [new Tag("tourism", "information")],
|
||||
maxAllowedOverlapPercentage: 0,
|
||||
icon: "assets/nature/info.png",
|
||||
});
|
||||
|
||||
const isMap = new Tag("information", "map");
|
||||
const isOsmSource = new Tag("map_source", "OpenStreetMap");
|
||||
|
||||
this.title = new TagRenderingOptions({
|
||||
mappings: [
|
||||
{k: isMap, txt: "Kaart"},
|
||||
{k:null, txt: "Informatiebord"}
|
||||
]
|
||||
});
|
||||
|
||||
this.style = (properties) => {
|
||||
let icon = "assets/nature/info.png";
|
||||
if (isMap.matchesProperties(properties)) {
|
||||
icon = "assets/map.svg";
|
||||
if (isOsmSource.matchesProperties(properties)) {
|
||||
icon = "assets/osm-logo-white-bg.svg";
|
||||
|
||||
const attr = properties["map_source:attribution"];
|
||||
if (attr == "sticker") {
|
||||
icon = "assets/map-stickered.svg"
|
||||
} else if (attr == "no") {
|
||||
icon = "assets/osm-logo-buggy-attr.svg"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
color: "#000000",
|
||||
icon: L.icon(
|
||||
{
|
||||
iconUrl: icon,
|
||||
iconSize: [50, 50]
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
this.elementsToShow = [
|
||||
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Heeft dit informatiebord een kaart?",
|
||||
mappings: [
|
||||
{k: new Tag("information","board"), txt: "Dit is een informatiebord"},
|
||||
{k: isMap, txt: "Dit is een kaart"}
|
||||
]
|
||||
}),
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Is this map based on OpenStreetMap?",
|
||||
mappings: [
|
||||
{
|
||||
k: isOsmSource,
|
||||
txt: "This map is based on OpenStreetMap"
|
||||
},
|
||||
{
|
||||
k: new And([new Tag("map_source:attribution", ""), new Tag("map_source","")]),
|
||||
txt: "Unknown"
|
||||
},
|
||||
],
|
||||
freeform: {
|
||||
key: "map_source",
|
||||
extraTags: new Tag("map_source:attribution", ""),
|
||||
renderTemplate: "The map data is based on {map_source}",
|
||||
template: "The map data is based on $$$"
|
||||
}
|
||||
}).OnlyShowIf(isMap),
|
||||
new TagRenderingOptions({
|
||||
question: "Is the attribution present?",
|
||||
mappings: [
|
||||
{
|
||||
k: new Tag("map_source:attribution", "yes"),
|
||||
txt: "OpenStreetMap is clearly attribute, including the ODBL-license"
|
||||
},
|
||||
{
|
||||
k: new Tag("map_source:attribution", "incomplete"),
|
||||
txt: "OpenStreetMap is clearly attribute, but the license is not mentioned"
|
||||
},
|
||||
{
|
||||
k: new Tag("map_source:attribution", "sticker"),
|
||||
txt: "OpenStreetMap wasn't mentioned, but someone put an OpenStreetMap-sticker on it"
|
||||
},
|
||||
{
|
||||
k: new Tag("map_source:attribution", "no"),
|
||||
txt: "There is no attribution at all"
|
||||
},
|
||||
{
|
||||
k: new Tag("map_source:attribution", "none"),
|
||||
txt: "There is no attribution at all"
|
||||
}
|
||||
]
|
||||
}).OnlyShowIf(new Tag("map_source", "OpenStreetMap"))
|
||||
]
|
||||
|
||||
|
||||
}
|
||||
}
|
96
Customizations/Layers/Map.ts
Normal file
96
Customizations/Layers/Map.ts
Normal file
|
@ -0,0 +1,96 @@
|
|||
import {LayerDefinition} from "../LayerDefinition";
|
||||
import FixedText from "../Questions/FixedText";
|
||||
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||
import {TagRenderingOptions} from "../TagRendering";
|
||||
import {And, Tag} from "../../Logic/TagsFilter";
|
||||
import L from "leaflet";
|
||||
|
||||
export class Map extends LayerDefinition {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "Map";
|
||||
this.title = new FixedText("Map");
|
||||
this.minzoom = 12;
|
||||
|
||||
this.overpassFilter = new Tag("information", "map");
|
||||
this.newElementTags = [new Tag("tourism", "information"), new Tag("information", "map")];
|
||||
|
||||
|
||||
const isOsmSource = new Tag("map_source", "OpenStreetMap");
|
||||
|
||||
|
||||
|
||||
this.style = (properties) => {
|
||||
let icon = "assets/map.svg";
|
||||
if(isOsmSource.matchesProperties(properties)){
|
||||
icon = "assets/osm-logo-white-bg.svg";
|
||||
|
||||
const attr = properties["map_source:attribution"];
|
||||
if(attr == "sticker"){
|
||||
icon = "assets/map-stickered.svg"
|
||||
}else if(attr == "no"){
|
||||
icon = "assets/osm-logo-buggy-attr.svg"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
color: "#000000",
|
||||
icon: L.icon(
|
||||
{
|
||||
iconUrl: icon,
|
||||
iconSize: [50, 50]
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
this.elementsToShow = [
|
||||
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
|
||||
new TagRenderingOptions({
|
||||
question: "Is this map based on OpenStreetMap?",
|
||||
mappings: [
|
||||
{
|
||||
k: isOsmSource,
|
||||
txt: "This map is based on OpenStreetMap"
|
||||
},
|
||||
],
|
||||
freeform: {
|
||||
key: "map_source",
|
||||
renderTemplate: "The map data is based on {map_source}",
|
||||
template: "The map data is based on $$$"
|
||||
}
|
||||
}),
|
||||
new TagRenderingOptions({
|
||||
question: "Is the attribution present?",
|
||||
mappings: [
|
||||
{
|
||||
k: new Tag("map_source:attribution", "yes"),
|
||||
txt: "OpenStreetMap is clearly attribute, including the ODBL-license"
|
||||
},
|
||||
{
|
||||
k: new Tag("map_source:attribution", "incomplete"),
|
||||
txt: "OpenStreetMap is clearly attribute, but the license is not mentioned"
|
||||
},
|
||||
{
|
||||
k: new Tag("map_source:attribution", "sticker"),
|
||||
txt: "OpenStreetMap wasn't mentioned, but someone put an OpenStreetMap-sticker on it"
|
||||
},
|
||||
{
|
||||
k: new Tag("map_source:attribution", "no"),
|
||||
txt: "There is no attribution at all"
|
||||
},
|
||||
{
|
||||
k: new Tag("map_source:attribution", "none"),
|
||||
txt: "There is no attribution at all"
|
||||
}
|
||||
]
|
||||
}).OnlyShowIf(new Tag("map_source", "OpenStreetMap"))
|
||||
]
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -10,18 +10,18 @@ import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWi
|
|||
|
||||
export class NatureReserves extends LayerDefinition {
|
||||
|
||||
constructor() {
|
||||
constructor(moreQuests: boolean = false) {
|
||||
super();
|
||||
this.name = "natuurgebied";
|
||||
this.icon = "./assets/tree_white_background.svg";
|
||||
this.overpassFilter =
|
||||
new Or([new Tag("leisure", "nature_reserve"), new Tag("boundary","protected_area")]);
|
||||
new Or([new Tag("leisure", "nature_reserve"), new Tag("boundary", "protected_area")]);
|
||||
this.maxAllowedOverlapPercentage = 10;
|
||||
|
||||
this.newElementTags = [new Tag("leisure", "nature_reserve"),
|
||||
new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")]
|
||||
this.minzoom = 13;
|
||||
this.title = new NameInline("natuurreservaat");
|
||||
this.title = new NameInline("natuurreservaat");
|
||||
this.style = this.generateStyleFunction();
|
||||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
|
@ -30,6 +30,67 @@ export class NatureReserves extends LayerDefinition {
|
|||
new OperatorTag(),
|
||||
new DescriptionQuestion("natuurgebied")
|
||||
];
|
||||
|
||||
|
||||
const extraRenderings = [
|
||||
new TagRenderingOptions({
|
||||
question: "Mogen honden in dit natuurgebied?",
|
||||
mappings: [
|
||||
{k: new Tag("dog", "leashed"), txt: "Honden moeten aan de leiband"},
|
||||
{k: new Tag("dog", "no"), txt: "Honden zijn niet toegestaan"},
|
||||
{k: new Tag("dog", "yes"), txt: "Honden zijn welkom"},
|
||||
]
|
||||
}).OnlyShowIf(new Tag("access", "yes")),
|
||||
new TagRenderingOptions({
|
||||
question: "Op welke website kunnen we meer informatie vinden over dit natuurgebied?",
|
||||
freeform: {
|
||||
key:"website",
|
||||
renderTemplate: "<a href='{website}' target='_blank'>Meer informatie</a>",
|
||||
template: "$$$"
|
||||
}
|
||||
}),
|
||||
new TagRenderingOptions({
|
||||
question: "Wie is de conservator van dit gebied?<br>" +
|
||||
"<span class='question-subtext'>Geef de naam van de conservator énkel als die duidelijk online staat gepubliceerd.</span>",
|
||||
freeform: {
|
||||
renderTemplate: "De conservator van dit gebied is {curator}",
|
||||
template: "$$$",
|
||||
key: "curator"
|
||||
}
|
||||
}),
|
||||
new TagRenderingOptions(
|
||||
{
|
||||
question: "Wat is het email-adres van de beheerder?<br>" +
|
||||
"<span class='question-subtext'>Geef bij voorkeur het emailadres van de Natuurpunt-afdeling; geef enkel een email-adres van de conservator als dit duidelijk is gepubliceerd</span>",
|
||||
freeform: {
|
||||
renderTemplate: "Bij problemen of vragen, de conservator kan bereikt worden via " +
|
||||
"<a href='mailto:{email}'>{email}</a>",
|
||||
template: "$$$",
|
||||
key: "email"
|
||||
}
|
||||
}),
|
||||
new TagRenderingOptions(
|
||||
{
|
||||
question: "Wat is het telefoonnummer van de beheerder?<br>" +
|
||||
"<span class='question-subtext'>Geef bij voorkeur het telefoonnummer van de Natuurpunt-afdeling; geef enkel een email-adres van de conservator als dit duidelijk is gepubliceerd</span>",
|
||||
freeform: {
|
||||
renderTemplate: "Bij problemen of vragen, de {conservator} kan bereikt worden via " +
|
||||
"<a href='tel:{phone}'>{phone}</a>",
|
||||
template: "$$$",
|
||||
key: "phone"
|
||||
}
|
||||
|
||||
}),
|
||||
|
||||
|
||||
];
|
||||
|
||||
if (moreQuests) {
|
||||
this.elementsToShow =
|
||||
this.elementsToShow.concat(extraRenderings);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
309
Customizations/Layers/Widths.ts
Normal file
309
Customizations/Layers/Widths.ts
Normal file
|
@ -0,0 +1,309 @@
|
|||
import {LayerDefinition} from "../LayerDefinition";
|
||||
import {And, Not, Or, Tag} from "../../Logic/TagsFilter";
|
||||
import {TagRenderingOptions} from "../TagRendering";
|
||||
import {UIEventSource} from "../../UI/UIEventSource";
|
||||
import {Park} from "./Park";
|
||||
|
||||
export class Widths extends LayerDefinition {
|
||||
|
||||
private cyclistWidth: number;
|
||||
private carWidth: number;
|
||||
private pedestrianWidth: number;
|
||||
|
||||
private readonly _bothSideParking = new Tag("parking:lane:both", "parallel");
|
||||
private readonly _noSideParking = new Tag("parking:lane:both", "no_parking");
|
||||
private readonly _otherParkingMode =
|
||||
new Or([
|
||||
new Tag("parking:lane:both", "perpendicular"),
|
||||
new Tag("parking:lane:left", "perpendicular"),
|
||||
new Tag("parking:lane:right", "perpendicular"),
|
||||
new Tag("parking:lane:both", "diagonal"),
|
||||
new Tag("parking:lane:left", "diagonal"),
|
||||
new Tag("parking:lane:right", "diagonal"),
|
||||
])
|
||||
|
||||
|
||||
private readonly _leftSideParking =
|
||||
new And([new Tag("parking:lane:left", "parallel"), new Tag("parking:lane:right", "no_parking")]);
|
||||
private readonly _rightSideParking =
|
||||
new And([new Tag("parking:lane:right", "parallel"), new Tag("parking:lane:left", "no_parking")]);
|
||||
|
||||
|
||||
private _sidewalkBoth = new Tag("sidewalk", "both");
|
||||
private _sidewalkLeft = new Tag("sidewalk", "left");
|
||||
private _sidewalkRight = new Tag("sidewalk", "right");
|
||||
private _sidewalkNone = new Tag("sidewalk", "none");
|
||||
|
||||
|
||||
private readonly _oneSideParking = new Or([this._leftSideParking, this._rightSideParking]);
|
||||
|
||||
private readonly _carfree = new Or([new Tag("highway", "pedestrian"), new Tag("highway", "living_street")])
|
||||
private readonly _notCarFree = new Not(this._carfree);
|
||||
|
||||
private calcProps(properties) {
|
||||
let parkingStateKnown = true;
|
||||
let parallelParkingCount = 0;
|
||||
|
||||
if (this._oneSideParking.matchesProperties(properties)) {
|
||||
parallelParkingCount = 1;
|
||||
} else if (this._bothSideParking.matchesProperties(properties)) {
|
||||
parallelParkingCount = 2;
|
||||
} else if (this._noSideParking.matchesProperties(properties)) {
|
||||
parallelParkingCount = 0;
|
||||
} else if (this._otherParkingMode.matchesProperties(properties)) {
|
||||
parallelParkingCount = 0;
|
||||
} else {
|
||||
parkingStateKnown = false;
|
||||
console.log("No parking data for ", properties.name, properties.id, properties)
|
||||
}
|
||||
|
||||
|
||||
let pedestrianFlowNeeded = 0;
|
||||
|
||||
if (this._sidewalkBoth.matchesProperties(properties)) {
|
||||
pedestrianFlowNeeded = 0;
|
||||
} else if (this._sidewalkNone.matchesProperties(properties)) {
|
||||
pedestrianFlowNeeded = 2;
|
||||
} else if (this._sidewalkLeft.matchesProperties(properties) || this._sidewalkRight.matches(properties)) {
|
||||
pedestrianFlowNeeded = 1;
|
||||
} else {
|
||||
pedestrianFlowNeeded = -1;
|
||||
}
|
||||
|
||||
|
||||
let onewayCar = properties.oneway === "yes";
|
||||
let onewayBike = properties["oneway:bicycle"] === "yes" ||
|
||||
(onewayCar && properties["oneway:bicycle"] === undefined)
|
||||
|
||||
let cyclingAllowed =
|
||||
!(properties.bicycle === "use_sidepath"
|
||||
|| properties.bicycle === "no");
|
||||
|
||||
let carWidth = (onewayCar ? 1 : 2) * this.carWidth;
|
||||
let cyclistWidth = 0;
|
||||
if (cyclingAllowed) {
|
||||
cyclistWidth = (onewayBike ? 1 : 2) * this.cyclistWidth;
|
||||
}
|
||||
|
||||
const width = parseFloat(properties["width:carriageway"]);
|
||||
|
||||
|
||||
const targetWidth =
|
||||
carWidth +
|
||||
cyclistWidth +
|
||||
Math.max(0, pedestrianFlowNeeded) * this.pedestrianWidth +
|
||||
parallelParkingCount * this.carWidth;
|
||||
|
||||
return {
|
||||
parkingLanes: parallelParkingCount,
|
||||
parkingStateKnown: parkingStateKnown,
|
||||
width: width,
|
||||
targetWidth: targetWidth,
|
||||
onewayBike: onewayBike,
|
||||
pedestrianFlowNeeded: pedestrianFlowNeeded,
|
||||
cyclingAllowed: cyclingAllowed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
constructor(carWidth: number,
|
||||
cyclistWidth: number,
|
||||
pedestrianWidth: number) {
|
||||
super();
|
||||
this.carWidth = carWidth;
|
||||
this.cyclistWidth = cyclistWidth;
|
||||
this.pedestrianWidth = pedestrianWidth;
|
||||
this.minzoom = 12;
|
||||
|
||||
function r(n: number) {
|
||||
const pre = Math.floor(n);
|
||||
const post = Math.floor((n * 10) % 10);
|
||||
return "" + pre + "." + post;
|
||||
}
|
||||
|
||||
this.name = "widths";
|
||||
this.overpassFilter = new Tag("width:carriageway", "*");
|
||||
|
||||
this.title = new TagRenderingOptions({
|
||||
freeform: {
|
||||
renderTemplate: "{name}",
|
||||
template: "$$$",
|
||||
key: "name"
|
||||
}
|
||||
})
|
||||
|
||||
const self = this;
|
||||
this.style = (properties) => {
|
||||
|
||||
let c = "#f00";
|
||||
|
||||
|
||||
const props = self.calcProps(properties);
|
||||
if (props.pedestrianFlowNeeded > 0) {
|
||||
c = "#fa0"
|
||||
}
|
||||
if (props.width >= props.targetWidth || !props.cyclingAllowed) {
|
||||
c = "#0c0";
|
||||
}
|
||||
|
||||
if (!props.parkingStateKnown && properties["note:width:carriageway"] === undefined) {
|
||||
c = "#f0f"
|
||||
}
|
||||
|
||||
if (this._carfree.matchesProperties(properties)) {
|
||||
c = "#aaa";
|
||||
}
|
||||
|
||||
|
||||
// Mark probably wrong data
|
||||
if (props.width > 15) {
|
||||
c = "#f0f"
|
||||
}
|
||||
|
||||
let dashArray = undefined;
|
||||
if (props.onewayBike) {
|
||||
dashArray = [20, 8]
|
||||
}
|
||||
return {
|
||||
icon: null,
|
||||
color: c,
|
||||
weight: 7,
|
||||
dashArray: dashArray
|
||||
}
|
||||
}
|
||||
|
||||
this.elementsToShow = [
|
||||
new TagRenderingOptions({
|
||||
question: "Mogen auto's hier parkeren?",
|
||||
mappings: [
|
||||
{
|
||||
k: this._bothSideParking,
|
||||
txt: "Auto's kunnen langs beide zijden parkeren.<br+>Dit gebruikt <b>" + r(this.carWidth * 2) + "m</b><br/>"
|
||||
},
|
||||
{
|
||||
k: this._oneSideParking,
|
||||
txt: "Auto's kunnen langs één kant parkeren.<br/>Dit gebruikt <b>" + r(this.carWidth) + "m</b><br/>"
|
||||
},
|
||||
{
|
||||
k: this._otherParkingMode,
|
||||
txt: "Deze straat heeft dwarsparkeren of diagonaalparkeren aan minstens één zijde. Deze parkeerruimte is niet opgenomen in de straatbreedte."
|
||||
},
|
||||
{k: this._noSideParking, txt: "Auto's mogen hier niet parkeren"},
|
||||
// {k: null, txt: "Nog geen parkeerinformatie bekend"}
|
||||
],
|
||||
freeform: {
|
||||
key: "note:width:carriageway",
|
||||
renderTemplate: "{note:width:carriageway}",
|
||||
template: "$$$",
|
||||
}
|
||||
}).OnlyShowIf(this._notCarFree),
|
||||
|
||||
|
||||
new TagRenderingOptions({
|
||||
mappings: [
|
||||
{
|
||||
k: this._sidewalkNone,
|
||||
txt: "Deze straat heeft geen voetpaden. Voetgangers hebben hier <b>" + r(this.pedestrianWidth * 2) + "m</b> nodig"
|
||||
},
|
||||
{
|
||||
k: new Or([this._sidewalkLeft, this._sidewalkRight]),
|
||||
txt: "Deze straat heeft een voetpad aan één kant. Voetgangers hebben hier <b>" + r(this.pedestrianWidth) + "m</b> nodig"
|
||||
},
|
||||
{k: this._sidewalkBoth, txt: "Deze straat heeft voetpad aan beide zijden."},
|
||||
],
|
||||
freeform: {
|
||||
key: "note:width:carriageway",
|
||||
renderTemplate: "{note:width:carriageway}",
|
||||
template: "$$$",
|
||||
}
|
||||
}).OnlyShowIf(this._notCarFree),
|
||||
|
||||
|
||||
new TagRenderingOptions({
|
||||
mappings: [
|
||||
{
|
||||
k: new Tag("bicycle", "use_sidepath"),
|
||||
txt: "Er is een afgescheiden, verplicht te gebruiken fietspad. Fietsen op dit wegsegment hoeft dus niet"
|
||||
},
|
||||
{
|
||||
k: new Tag("bicycle", "no"),
|
||||
txt: "Fietsen is hier niet toegestaan"
|
||||
},
|
||||
{
|
||||
k: new Tag("oneway:bicycle", "yes"),
|
||||
txt: "Eenrichtingsverkeer, óók voor fietsers. Dit gebruikt <b>" + r(this.carWidth + this.cyclistWidth) + "m</b>"
|
||||
},
|
||||
{
|
||||
k: new And([new Tag("oneway", "yes"), new Tag("oneway:bicycle", "no")]),
|
||||
txt: "Tweerichtingverkeer voor fietsers, eenrichting voor auto's Dit gebruikt <b>" + r(this.carWidth + 2 * this.cyclistWidth) + "m</b>"
|
||||
},
|
||||
{
|
||||
k: new Tag("oneway", "yes"),
|
||||
txt: "Eenrichtingsverkeer voor iedereen. Dit gebruikt <b>" + (this.carWidth + this.cyclistWidth) + "m</b>"
|
||||
},
|
||||
{
|
||||
k: null,
|
||||
txt: "Tweerichtingsverkeer voor iedereen. Dit gebruikt <b>" + r(2 * this.carWidth + 2 * this.cyclistWidth) + "m</b>"
|
||||
}
|
||||
]
|
||||
}).OnlyShowIf(this._notCarFree),
|
||||
|
||||
new TagRenderingOptions(
|
||||
{
|
||||
tagsPreprocessor: (tags) => {
|
||||
const props = self.calcProps(tags);
|
||||
tags.targetWidth = r(props.targetWidth);
|
||||
tags.short = "";
|
||||
if (props.width < props.targetWidth) {
|
||||
tags.short = "Er is dus <b class='alert'>" + r(props.targetWidth - props.width) + "m</b> te weinig"
|
||||
}
|
||||
},
|
||||
freeform: {
|
||||
key: "width:carriageway",
|
||||
renderTemplate: "De totale nodige ruimte voor vlot en veilig verkeer is dus <b>{targetWidth}m</b><br>" +
|
||||
"{short}",
|
||||
template: "$$$",
|
||||
}
|
||||
}
|
||||
).OnlyShowIf(this._notCarFree),
|
||||
|
||||
|
||||
new TagRenderingOptions({
|
||||
mappings: [
|
||||
{k:new Tag("highway","living_street"),txt: "Dit is een woonerf"},
|
||||
{k:new Tag("highway","pedestrian"),txt: "Deze weg is autovrij"}
|
||||
]
|
||||
}),
|
||||
|
||||
new TagRenderingOptions({
|
||||
mappings: [
|
||||
{
|
||||
k: new Tag("sidewalk", "none"),
|
||||
txt: "De afstand van huis tot huis is <b>{width:carriageway}m</b>"
|
||||
},
|
||||
{
|
||||
k: new Tag("sidewalk", "left"),
|
||||
txt: "De afstand van huis tot voetpad is <b>{width:carriageway}m</b>"
|
||||
},
|
||||
{
|
||||
k: new Tag("sidewalk", "right"),
|
||||
txt: "De afstand van huis tot voetpad is <b>{width:carriageway}m</b>"
|
||||
},
|
||||
{
|
||||
k: new Tag("sidewalk", "both"),
|
||||
txt: "De afstand van voetpad tot voetpad is <b>{width:carriageway}m</b>"
|
||||
},
|
||||
{
|
||||
k: new Tag("sidewalk", ""),
|
||||
txt: "De straatbreedte is <b>{width:carriageway}m</b>"
|
||||
}
|
||||
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,8 @@ import BikeParkings from "../Layers/BikeParkings";
|
|||
import BikeServices from "../Layers/BikeStations";
|
||||
import {GhostBike} from "../Layers/GhostBike";
|
||||
import Translations from "../../UI/i18n/Translations";
|
||||
import {DrinkingWater} from "../Layers/DrinkingWater";
|
||||
import {BikeShop} from "../Layers/BikeShop";
|
||||
|
||||
|
||||
export default class Cyclofix extends Layout {
|
||||
|
@ -10,7 +12,7 @@ export default class Cyclofix extends Layout {
|
|||
super(
|
||||
"pomp",
|
||||
Translations.t.cylofix.title,
|
||||
[new GhostBike(), new BikeServices(), new BikeParkings()],
|
||||
[new BikeServices(), new BikeShop(), new DrinkingWater(), new BikeParkings()],
|
||||
16,
|
||||
50.8465573,
|
||||
4.3516970,
|
||||
|
|
18
Customizations/Layouts/MetaMap.ts
Normal file
18
Customizations/Layouts/MetaMap.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import {Layout} from "../Layout";
|
||||
import * as Layer from "../Layers/Bookcases";
|
||||
import {Map} from "../Layers/Map";
|
||||
|
||||
export class MetaMap extends Layout{
|
||||
constructor() {
|
||||
super( "metamap",
|
||||
"Open Map Map",
|
||||
[new Map()],
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
|
||||
|
||||
" <h3>Open Map Map</h3>\n" +
|
||||
"This map is a map of physical maps, as known by OpenStreetMap.");
|
||||
}
|
||||
}
|
20
Customizations/Layouts/Natuurpunt.ts
Normal file
20
Customizations/Layouts/Natuurpunt.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import {Layout} from "../Layout";
|
||||
import {Birdhide} from "../Layers/Birdhide";
|
||||
import {InformationBoard} from "../Layers/InformationBoard";
|
||||
import {NatureReserves} from "../Layers/NatureReserves";
|
||||
|
||||
export class Natuurpunt extends Layout{
|
||||
constructor() {
|
||||
super(
|
||||
"natuurpunt",
|
||||
"De natuur in",
|
||||
[new Birdhide(), new InformationBoard(), new NatureReserves(true)],
|
||||
12,
|
||||
51.20875,
|
||||
3.22435,
|
||||
"<h3>Natuurpuntstuff</h3>",
|
||||
"",
|
||||
""
|
||||
);
|
||||
}
|
||||
}
|
35
Customizations/Layouts/StreetWidth.ts
Normal file
35
Customizations/Layouts/StreetWidth.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import {Layout} from "../Layout";
|
||||
import * as Layer from "../Layers/Bookcases";
|
||||
import {Widths} from "../Layers/Widths";
|
||||
import {UIEventSource} from "../../UI/UIEventSource";
|
||||
|
||||
export class StreetWidth extends Layout{
|
||||
|
||||
constructor() {
|
||||
super( "width",
|
||||
"Straatbreedtes in Brugge",
|
||||
[new Widths(
|
||||
2,
|
||||
1.5,
|
||||
0.75
|
||||
|
||||
)],
|
||||
15,
|
||||
51.20875,
|
||||
3.22435,
|
||||
"<h3>De straat is opgebruikt</h3>" +
|
||||
"<p>Er is steeds meer druk op de openbare ruimte. Voetgangers, fietsers, steps, auto's, bussen, bestelwagens, buggies, cargobikes, ... willen allemaal hun deel van de openbare ruimte.</p>" +
|
||||
"" +
|
||||
"<p>In deze studie nemen we Brugge onder de loep en kijken we hoe breed elke straat is én hoe breed elke straat zou moeten zijn voor een veilig én vlot verkeer.</p>" +
|
||||
"Verschillende ingrepen kunnen de stad teruggeven aan de inwoners en de stad leefbaarder en levendiger maken.<br/>" +
|
||||
"Denk aan:" +
|
||||
"<ul>" +
|
||||
"<li>De autovrije zone's uitbreiden</li>" +
|
||||
"<li>De binnenstad fietszone maken</li>" +
|
||||
"<li>Het aantal woonerven uitbreiden</li>" +
|
||||
"<li>Grotere auto's meer belasten - ze nemen immers meer parkeerruimte in.</li>" +
|
||||
"</ul>",
|
||||
"",
|
||||
"");
|
||||
}
|
||||
}
|
28
Customizations/Layouts/WalkByBrussels.ts
Normal file
28
Customizations/Layouts/WalkByBrussels.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { Layout } from "../Layout";
|
||||
import { DrinkingWater } from "../Layers/DrinkingWater";
|
||||
import { NatureReserves } from "../Layers/NatureReserves";
|
||||
import { Park } from "../Layers/Park";
|
||||
|
||||
export class WalkByBrussels extends Layout {
|
||||
constructor() {
|
||||
super("walkbybrussels",
|
||||
"Drinking Water Spots",
|
||||
[new DrinkingWater(), new Park(), new NatureReserves()],
|
||||
10,
|
||||
50.8435,
|
||||
4.3688,
|
||||
|
||||
|
||||
" <h3>Drinking water</h3>\n" +
|
||||
"\n" +
|
||||
"<p>" +
|
||||
"Help with creating a map of drinking water points!"
|
||||
|
||||
,
|
||||
" <p>Start by <a href=\"https://www.openstreetmap.org/user/new\" target=\"_blank\">creating an account\n" +
|
||||
" </a> or by " +
|
||||
" <span onclick=\"authOsm()\" class=\"activate-osm-authentication\">logging in</span>.</p>",
|
||||
"Start by clicking a pin and answering the questions");
|
||||
}
|
||||
|
||||
}
|
|
@ -17,9 +17,9 @@ export class OnlyShowIfConstructor implements TagDependantUIElementConstructor{
|
|||
this._embedded = embedded;
|
||||
}
|
||||
|
||||
construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement {
|
||||
return new OnlyShowIf(tags,
|
||||
this._embedded.construct(tags, changes),
|
||||
construct(dependencies): TagDependantUIElement {
|
||||
return new OnlyShowIf(dependencies.tags,
|
||||
this._embedded.construct(dependencies),
|
||||
this._tagsFilter);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@ import {TagRenderingOptions} from "../TagRendering";
|
|||
export class WikipediaLink extends TagRenderingOptions {
|
||||
|
||||
private static FixLink(value: string): string {
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
// @ts-ignore
|
||||
if (value.startsWith("https")) {
|
||||
return value;
|
||||
|
@ -20,6 +23,11 @@ export class WikipediaLink extends TagRenderingOptions {
|
|||
static options = {
|
||||
priority: 10,
|
||||
// question: "Wat is het overeenstemmende wkipedia-artikel?",
|
||||
tagsPreprocessor: (tags) => {
|
||||
if (tags.wikipedia !== undefined) {
|
||||
tags.wikipedia = WikipediaLink.FixLink(tags.wikipedia);
|
||||
}
|
||||
},
|
||||
freeform: {
|
||||
key: "wikipedia",
|
||||
template: "$$$",
|
||||
|
@ -28,19 +36,8 @@ export class WikipediaLink extends TagRenderingOptions {
|
|||
"<a href='{wikipedia}' target='_blank'>" +
|
||||
"<img width='64px' src='./assets/wikipedia.svg' alt='wikipedia'>" +
|
||||
"</a></span>",
|
||||
placeholder: "",
|
||||
tagsPreprocessor: (tags) => {
|
||||
placeholder: ""
|
||||
|
||||
const newTags = {};
|
||||
for (const k in tags) {
|
||||
if (k === "wikipedia") {
|
||||
newTags["wikipedia"] = WikipediaLink.FixLink(tags[k]);
|
||||
} else {
|
||||
newTags[k] = tags[k];
|
||||
}
|
||||
}
|
||||
return newTags;
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ export default class BikeStationOperator extends TagRenderingOptions {
|
|||
{k: new Tag("operator", "Stad Halle"), txt: "Stad Halle"},
|
||||
{k: new Tag("operator", "Saint Gilles - Sint Gillis"), txt: "Saint Gilles - Sint Gillis"},
|
||||
{k: new Tag("operator", "Jette"), txt: "Jette"},
|
||||
{k: new Tag("operator", "private"), txt: "Beheer door een privépersoon"}
|
||||
{k: new Tag("operator", "private"), txt: "Operated by a private individual"}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ export default class BikeStationPumpTools extends TagRenderingOptions {
|
|||
constructor() {
|
||||
super({
|
||||
priority: 15,
|
||||
question: "Which services are available at this bike station?",
|
||||
question: "Which services are available here?",
|
||||
mappings: [
|
||||
{k: new And([new Tag("service:bicycle:tools", "no"), new Tag("service:bicycle:pump", "yes")]), txt: "There is only a pump available."},
|
||||
{k: new And([new Tag("service:bicycle:tools", "yes"), new Tag("service:bicycle:pump", "no")]), txt: "There are only tools (screwdrivers, pliers...) available."},
|
||||
|
|
|
@ -80,14 +80,15 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
|||
|
||||
/**
|
||||
* In some very rare cases, tags have to be rewritten before displaying
|
||||
* This function adds this
|
||||
* This function can be used for that.
|
||||
* This function is ran on a _copy_ of the original properties
|
||||
*/
|
||||
tagsPreprocessor?: ((tags: any) => any)
|
||||
tagsPreprocessor?: ((tags: any) => void)
|
||||
}) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
OnlyShowIf(tagsFilter: TagsFilter) : TagDependantUIElementConstructor{
|
||||
|
||||
OnlyShowIf(tagsFilter: TagsFilter): TagDependantUIElementConstructor {
|
||||
return new OnlyShowIfConstructor(tagsFilter, this);
|
||||
}
|
||||
|
||||
|
@ -111,8 +112,8 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
|||
}
|
||||
|
||||
|
||||
construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement {
|
||||
return new TagRendering(tags, changes, this.options);
|
||||
construct(dependencies: { tags: UIEventSource<any>, changes: Changes }): TagDependantUIElement {
|
||||
return new TagRendering(dependencies.tags, dependencies.changes, this.options);
|
||||
}
|
||||
|
||||
IsKnown(properties: any): boolean {
|
||||
|
@ -183,11 +184,22 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
|
||||
this._userDetails = changes.login.userDetails;
|
||||
this.ListenTo(this._userDetails);
|
||||
|
||||
|
||||
this._question = options.question;
|
||||
this._priority = options.priority ?? 0;
|
||||
this._primer = options.primer ?? "";
|
||||
this._tagsPreprocessor = options.tagsPreprocessor;
|
||||
this._tagsPreprocessor = function (properties) {
|
||||
if (options.tagsPreprocessor === undefined) {
|
||||
return properties;
|
||||
}
|
||||
const newTags = {};
|
||||
for (const k in properties) {
|
||||
newTags[k] = properties[k];
|
||||
}
|
||||
options.tagsPreprocessor(newTags);
|
||||
return newTags;
|
||||
};
|
||||
|
||||
this._mapping = [];
|
||||
this._renderMapping = [];
|
||||
this._freeform = options.freeform;
|
||||
|
@ -313,9 +325,9 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
|
||||
const cancelContents = this._editMode.map((isEditing) => {
|
||||
if (isEditing) {
|
||||
return "<span class='skip-button'>Annuleren</span>";
|
||||
return "<span class='skip-button'>Cancel</span>";
|
||||
} else {
|
||||
return "<span class='skip-button'>Overslaan (Ik weet het niet zeker...)</span>";
|
||||
return "<span class='skip-button'>Skip this question</span>";
|
||||
}
|
||||
});
|
||||
// And at last, set up the skip button
|
||||
|
@ -325,12 +337,7 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
}
|
||||
|
||||
private ApplyTemplate(template: string): string {
|
||||
let tags = this._source.data;
|
||||
if (this._tagsPreprocessor !== undefined) {
|
||||
tags = this._tagsPreprocessor(tags);
|
||||
}
|
||||
|
||||
|
||||
const tags = this._tagsPreprocessor(this._source.data);
|
||||
return TagUtils.ApplyTemplate(template, tags);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import {UIElement} from "../UI/UIElement";
|
|||
|
||||
export interface TagDependantUIElementConstructor {
|
||||
|
||||
construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement;
|
||||
construct(dependencies: {tags: UIEventSource<any>, changes: Changes}): TagDependantUIElement;
|
||||
IsKnown(properties: any): boolean;
|
||||
IsQuestioning(properties: any): boolean;
|
||||
Priority(): number;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue