Merge master into translations

This commit is contained in:
Pieter Vander Vennet 2020-07-20 21:48:24 +02:00
commit a730345b16
77 changed files with 43519 additions and 1619 deletions

View file

@ -1,22 +1,32 @@
import {Groen} from "./Layouts/Groen"; import { Groen } from "./Layouts/Groen";
import {Toilets} from "./Layouts/Toilets"; import { Toilets } from "./Layouts/Toilets";
import {GRB} from "./Layouts/GRB"; import { GRB } from "./Layouts/GRB";
import {Statues} from "./Layouts/Statues"; import { Statues } from "./Layouts/Statues";
import {Bookcases} from "./Layouts/Bookcases"; import { Bookcases } from "./Layouts/Bookcases";
import Cyclofix from "./Layouts/Cyclofix"; import Cyclofix from "./Layouts/Cyclofix";
import {All} from "./Layouts/All"; import { WalkByBrussels } from "./Layouts/WalkByBrussels";
import {Layout} from "./Layout"; 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 { export class AllKnownLayouts {
public static allSets = AllKnownLayouts.AllLayouts(); public static allSets = AllKnownLayouts.AllLayouts();
private static AllLayouts(): Map<string, Layout> { private static AllLayouts(): Map<string, Layout> {
const all = new All(); const all = new All();
const layouts : Layout[] = [ const layouts: Layout[] = [
new Groen(), new Groen(),
new GRB(), new GRB(),
new Cyclofix(), new Cyclofix(),
new Bookcases(), new Bookcases(),
new WalkByBrussels(),
new MetaMap(),
new StreetWidth(),
new Natuurpunt(),
all all
/*new Toilets(), /*new Toilets(),
new Statues(), new Statues(),
@ -29,4 +39,13 @@ export class AllKnownLayouts {
} }
return allSets; 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;
}
} }

View file

@ -56,7 +56,16 @@ export class LayerDefinition {
*/ */
elementsToShow: TagDependantUIElementConstructor[]; 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 * 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; 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>, asLayer(basemap: Basemap, allElements: ElementStorage, changes: Changes, userDetails: UIEventSource<UserDetails>, selectedElement: UIEventSource<any>,
showOnPopup: (tags: UIEventSource<(any)>) => UIElement): showOnPopup: (tags: UIEventSource<(any)>) => UIElement):
FilteredLayer { FilteredLayer {

View file

@ -10,7 +10,7 @@ import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWi
export default class BikeParkings extends LayerDefinition { export default class BikeParkings extends LayerDefinition {
constructor() { constructor() {
super(); super();
this.name = "bike_parking"; this.name = "bike parking";
this.icon = "./assets/bike/parking.svg"; this.icon = "./assets/bike/parking.svg";
this.overpassFilter = new Tag("amenity", "bicycle_parking"); this.overpassFilter = new Tag("amenity", "bicycle_parking");
this.newElementTags = [ this.newElementTags = [
@ -20,10 +20,10 @@ export default class BikeParkings extends LayerDefinition {
this.minzoom = 13; this.minzoom = 13;
this.style = this.generateStyleFunction(); this.style = this.generateStyleFunction();
this.title = new FixedText("Fietsparking"); this.title = new FixedText("Bicycle parking");
this.elementsToShow = [ this.elementsToShow = [
new ImageCarouselWithUploadConstructor(), new ImageCarouselWithUploadConstructor(),
new OperatorTag(), // new OperatorTag(),
new ParkingType() new ParkingType()
]; ];
@ -36,7 +36,8 @@ export default class BikeParkings extends LayerDefinition {
color: "#00bb00", color: "#00bb00",
icon: L.icon({ icon: L.icon({
iconUrl: self.icon, iconUrl: self.icon,
iconSize: [50, 50] iconSize: [50, 50],
iconAnchor: [25,50]
}) })
}; };
}; };

View 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]
})
}
}
}
}

View file

@ -17,7 +17,7 @@ import PumpValves from "../Questions/bike/PumpValves";
export default class BikeStations extends LayerDefinition { export default class BikeStations extends LayerDefinition {
private readonly pump = new Tag("service:bicycle:pump", "yes"); private readonly pump = new Tag("service:bicycle:pump", "yes");
private readonly pumpOperationalAny = new Tag("service:bicycle:pump:operational_status", "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"); private readonly tools = new Tag("service:bicycle:tools", "yes");
constructor() { constructor() {
@ -31,7 +31,6 @@ export default class BikeStations extends LayerDefinition {
this.newElementTags = [ this.newElementTags = [
new Tag("amenity", "bicycle_repair_station") new Tag("amenity", "bicycle_repair_station")
// new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")
]; ];
this.maxAllowedOverlapPercentage = 10; this.maxAllowedOverlapPercentage = 10;
@ -60,7 +59,7 @@ export default class BikeStations extends LayerDefinition {
const self = this; const self = this;
return function (properties: any) { return function (properties: any) {
const hasPump = self.pump.matchesProperties(properties) 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) const hasTools = self.tools.matchesProperties(properties)
let iconName = "" let iconName = ""
if (hasPump) { if (hasPump) {
@ -74,14 +73,19 @@ export default class BikeStations extends LayerDefinition {
} }
} }
} else { } else {
iconName = "repair_station.svg" if (!self.pump.matchesProperties(properties)) {
iconName = "repair_station.svg"
} else {
iconName = "repair_station.svg"
}
} }
const iconUrl = `./assets/bike/${iconName}` const iconUrl = `./assets/bike/${iconName}`
return { return {
color: "#00bb00", color: "#00bb00",
icon: L.icon({ icon: L.icon({
iconUrl: iconUrl, iconUrl: iconUrl,
iconSize: [50, 50] iconSize: [50, 50],
iconAnchor: [25,50]
}) })
}; };
}; };

View 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)"},
]
})
];
}
}

View file

@ -5,6 +5,7 @@ import {QuestionDefinition} from "../../Logic/Question";
import {TagRenderingOptions} from "../TagRendering"; import {TagRenderingOptions} from "../TagRendering";
import {NameInline} from "../Questions/NameInline"; import {NameInline} from "../Questions/NameInline";
import {NameQuestion} from "../Questions/NameQuestion"; import {NameQuestion} from "../Questions/NameQuestion";
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
export class Bookcases extends LayerDefinition { export class Bookcases extends LayerDefinition {
@ -19,7 +20,7 @@ export class Bookcases extends LayerDefinition {
this.title = new NameInline("ruilboekenkastje"); this.title = new NameInline("ruilboekenkastje");
this.elementsToShow = [ this.elementsToShow = [
new ImageCarouselWithUploadConstructor(),
new TagRenderingOptions({ new TagRenderingOptions({
question: "Heeft dit boekenruilkastje een naam?", question: "Heeft dit boekenruilkastje een naam?",
freeform: { freeform: {

View 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]
})
};
};
}
}

View file

@ -52,19 +52,13 @@ export class GrbToFix extends LayerDefinition {
question: "Wat is het huisnummer?", question: "Wat is het huisnummer?",
tagsPreprocessor: tags => { 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 telltale = "GRB thinks that this has number ";
const index = tags.fixme.indexOf(telltale); const index = tags.fixme.indexOf(telltale);
if (index >= 0) { if (index >= 0) {
const housenumber = tags.fixme.slice(index + telltale.length); const housenumber = tags.fixme.slice(index + telltale.length);
newTags["grb:housenumber:human"] = housenumber; tags["grb:housenumber:human"] = housenumber;
newTags["grb:housenumber"] = housenumber == "no number" ? "" : housenumber; tags["grb:housenumber"] = housenumber == "no number" ? "" : housenumber;
} }
return newTags;
}, },
freeform: { freeform: {
key: "addr:housenumber", key: "addr:housenumber",

View 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"))
]
}
}

View 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"))
]
}
}

View file

@ -10,18 +10,18 @@ import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWi
export class NatureReserves extends LayerDefinition { export class NatureReserves extends LayerDefinition {
constructor() { constructor(moreQuests: boolean = false) {
super(); super();
this.name = "natuurgebied"; this.name = "natuurgebied";
this.icon = "./assets/tree_white_background.svg"; this.icon = "./assets/tree_white_background.svg";
this.overpassFilter = 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.maxAllowedOverlapPercentage = 10;
this.newElementTags = [new Tag("leisure", "nature_reserve"), this.newElementTags = [new Tag("leisure", "nature_reserve"),
new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")] new Tag("fixme", "Toegevoegd met MapComplete, geometry nog uit te tekenen")]
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(),
@ -30,6 +30,67 @@ export class NatureReserves extends LayerDefinition {
new OperatorTag(), new OperatorTag(),
new DescriptionQuestion("natuurgebied") 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);
}
} }

View 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>"
}
]
})
]
}
}

View file

@ -3,6 +3,8 @@ import BikeParkings from "../Layers/BikeParkings";
import BikeServices from "../Layers/BikeStations"; import BikeServices from "../Layers/BikeStations";
import {GhostBike} from "../Layers/GhostBike"; import {GhostBike} from "../Layers/GhostBike";
import Translations from "../../UI/i18n/Translations"; import Translations from "../../UI/i18n/Translations";
import {DrinkingWater} from "../Layers/DrinkingWater";
import {BikeShop} from "../Layers/BikeShop";
export default class Cyclofix extends Layout { export default class Cyclofix extends Layout {
@ -10,7 +12,7 @@ export default class Cyclofix extends Layout {
super( super(
"pomp", "pomp",
Translations.t.cylofix.title, Translations.t.cylofix.title,
[new GhostBike(), new BikeServices(), new BikeParkings()], [new BikeServices(), new BikeShop(), new DrinkingWater(), new BikeParkings()],
16, 16,
50.8465573, 50.8465573,
4.3516970, 4.3516970,

View 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.");
}
}

View 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>",
"",
""
);
}
}

View 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>",
"",
"");
}
}

View 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");
}
}

View file

@ -17,9 +17,9 @@ export class OnlyShowIfConstructor implements TagDependantUIElementConstructor{
this._embedded = embedded; this._embedded = embedded;
} }
construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement { construct(dependencies): TagDependantUIElement {
return new OnlyShowIf(tags, return new OnlyShowIf(dependencies.tags,
this._embedded.construct(tags, changes), this._embedded.construct(dependencies),
this._tagsFilter); this._tagsFilter);
} }

View file

@ -4,6 +4,9 @@ import {TagRenderingOptions} from "../TagRendering";
export class WikipediaLink extends TagRenderingOptions { export class WikipediaLink extends TagRenderingOptions {
private static FixLink(value: string): string { private static FixLink(value: string): string {
if (value === undefined) {
return undefined;
}
// @ts-ignore // @ts-ignore
if (value.startsWith("https")) { if (value.startsWith("https")) {
return value; return value;
@ -20,6 +23,11 @@ export class WikipediaLink extends TagRenderingOptions {
static options = { static options = {
priority: 10, priority: 10,
// question: "Wat is het overeenstemmende wkipedia-artikel?", // question: "Wat is het overeenstemmende wkipedia-artikel?",
tagsPreprocessor: (tags) => {
if (tags.wikipedia !== undefined) {
tags.wikipedia = WikipediaLink.FixLink(tags.wikipedia);
}
},
freeform: { freeform: {
key: "wikipedia", key: "wikipedia",
template: "$$$", template: "$$$",
@ -28,19 +36,8 @@ export class WikipediaLink extends TagRenderingOptions {
"<a href='{wikipedia}' target='_blank'>" + "<a href='{wikipedia}' target='_blank'>" +
"<img width='64px' src='./assets/wikipedia.svg' alt='wikipedia'>" + "<img width='64px' src='./assets/wikipedia.svg' alt='wikipedia'>" +
"</a></span>", "</a></span>",
placeholder: "", placeholder: ""
tagsPreprocessor: (tags) => {
const newTags = {};
for (const k in tags) {
if (k === "wikipedia") {
newTags["wikipedia"] = WikipediaLink.FixLink(tags[k]);
} else {
newTags[k] = tags[k];
}
}
return newTags;
}
}, },
} }

View file

@ -18,7 +18,7 @@ export default class BikeStationOperator extends TagRenderingOptions {
{k: new Tag("operator", "Stad Halle"), txt: "Stad Halle"}, {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", "Saint Gilles - Sint Gillis"), txt: "Saint Gilles - Sint Gillis"},
{k: new Tag("operator", "Jette"), txt: "Jette"}, {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"}
] ]
}); });
} }

View file

@ -6,7 +6,7 @@ export default class BikeStationPumpTools extends TagRenderingOptions {
constructor() { constructor() {
super({ super({
priority: 15, priority: 15,
question: "Which services are available at this bike station?", question: "Which services are available here?",
mappings: [ 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", "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."}, {k: new And([new Tag("service:bicycle:tools", "yes"), new Tag("service:bicycle:pump", "no")]), txt: "There are only tools (screwdrivers, pliers...) available."},

View file

@ -80,14 +80,15 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
/** /**
* In some very rare cases, tags have to be rewritten before displaying * 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; this.options = options;
} }
OnlyShowIf(tagsFilter: TagsFilter) : TagDependantUIElementConstructor{ OnlyShowIf(tagsFilter: TagsFilter): TagDependantUIElementConstructor {
return new OnlyShowIfConstructor(tagsFilter, this); return new OnlyShowIfConstructor(tagsFilter, this);
} }
@ -111,8 +112,8 @@ export class TagRenderingOptions implements TagDependantUIElementConstructor {
} }
construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement { construct(dependencies: { tags: UIEventSource<any>, changes: Changes }): TagDependantUIElement {
return new TagRendering(tags, changes, this.options); return new TagRendering(dependencies.tags, dependencies.changes, this.options);
} }
IsKnown(properties: any): boolean { IsKnown(properties: any): boolean {
@ -183,11 +184,22 @@ class TagRendering extends UIElement implements TagDependantUIElement {
this._userDetails = changes.login.userDetails; this._userDetails = changes.login.userDetails;
this.ListenTo(this._userDetails); this.ListenTo(this._userDetails);
this._question = options.question; this._question = options.question;
this._priority = options.priority ?? 0; this._priority = options.priority ?? 0;
this._primer = options.primer ?? ""; 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._mapping = [];
this._renderMapping = []; this._renderMapping = [];
this._freeform = options.freeform; this._freeform = options.freeform;
@ -313,9 +325,9 @@ class TagRendering extends UIElement implements TagDependantUIElement {
const cancelContents = this._editMode.map((isEditing) => { const cancelContents = this._editMode.map((isEditing) => {
if (isEditing) { if (isEditing) {
return "<span class='skip-button'>Annuleren</span>"; return "<span class='skip-button'>Cancel</span>";
} else { } 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 // And at last, set up the skip button
@ -325,12 +337,7 @@ class TagRendering extends UIElement implements TagDependantUIElement {
} }
private ApplyTemplate(template: string): string { private ApplyTemplate(template: string): string {
let tags = this._source.data; const tags = this._tagsPreprocessor(this._source.data);
if (this._tagsPreprocessor !== undefined) {
tags = this._tagsPreprocessor(tags);
}
return TagUtils.ApplyTemplate(template, tags); return TagUtils.ApplyTemplate(template, tags);
} }

View file

@ -5,7 +5,7 @@ import {UIElement} from "../UI/UIElement";
export interface TagDependantUIElementConstructor { export interface TagDependantUIElementConstructor {
construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement; construct(dependencies: {tags: UIEventSource<any>, changes: Changes}): TagDependantUIElement;
IsKnown(properties: any): boolean; IsKnown(properties: any): boolean;
IsQuestioning(properties: any): boolean; IsQuestioning(properties: any): boolean;
Priority(): number; Priority(): number;

View file

@ -117,7 +117,7 @@ console.log("Received change",key, value)
return geojson; return geojson;
} }
public uploadAll(optionalContinuation: (() => void)) { public uploadAll(optionalContinuation: (() => void) = undefined) {
const self = this; const self = this;
this.isSaving.setData(true); this.isSaving.setData(true);

View file

@ -1,11 +1,11 @@
import {Basemap} from "./Basemap"; import { Basemap } from "./Basemap";
import {TagsFilter, TagUtils} from "./TagsFilter"; import { TagsFilter, TagUtils } from "./TagsFilter";
import {UIEventSource} from "../UI/UIEventSource"; import { UIEventSource } from "../UI/UIEventSource";
import {ElementStorage} from "./ElementStorage"; import { ElementStorage } from "./ElementStorage";
import {Changes} from "./Changes"; import { Changes } from "./Changes";
import L from "leaflet" import L from "leaflet"
import {GeoOperations} from "./GeoOperations"; import { GeoOperations } from "./GeoOperations";
import {UIElement} from "../UI/UIElement"; import { UIElement } from "../UI/UIElement";
/*** /***
* A filtered layer is a layer which offers a 'set-data' function * A filtered layer is a layer which offers a 'set-data' function
@ -20,6 +20,7 @@ export class FilteredLayer {
public readonly name: string; public readonly name: string;
public readonly filters: TagsFilter; public readonly filters: TagsFilter;
public readonly isDisplayed: UIEventSource<boolean> = new UIEventSource(true);
private readonly _map: Basemap; private readonly _map: Basemap;
private readonly _maxAllowedOverlap: number; private readonly _maxAllowedOverlap: number;
@ -65,6 +66,16 @@ export class FilteredLayer {
this._style = style; this._style = style;
this._storage = storage; this._storage = storage;
this._maxAllowedOverlap = maxAllowedOverlap; this._maxAllowedOverlap = maxAllowedOverlap;
const self = this;
this.isDisplayed.addCallback(function (isDisplayed) {
if (self._geolayer !== undefined && self._geolayer !== null) {
if (isDisplayed) {
self._geolayer.addTo(self._map.map);
} else {
self._map.map.removeLayer(self._geolayer);
}
}
})
} }
@ -93,7 +104,7 @@ export class FilteredLayer {
const notShadowed = []; const notShadowed = [];
for (const feature of leftoverFeatures) { for (const feature of leftoverFeatures) {
if (this._maxAllowedOverlap !== undefined && this._maxAllowedOverlap >= 0) { if (this._maxAllowedOverlap !== undefined && this._maxAllowedOverlap > 0) {
if (GeoOperations.featureIsContainedInAny(feature, selfFeatures, this._maxAllowedOverlap)) { if (GeoOperations.featureIsContainedInAny(feature, selfFeatures, this._maxAllowedOverlap)) {
// This feature is filtered away // This feature is filtered away
continue; continue;
@ -164,7 +175,7 @@ export class FilteredLayer {
radius: 25, radius: 25,
color: style.color color: style.color
}); });
} else { } else {
marker = L.marker(latLng, { marker = L.marker(latLng, {
icon: style.icon icon: style.icon
@ -204,7 +215,9 @@ export class FilteredLayer {
} }
}); });
this._geolayer.addTo(this._map.map); if (this.isDisplayed.data) {
this._geolayer.addTo(this._map.map);
}
} }

View file

@ -123,11 +123,12 @@ export class OsmConnection {
public preferenceSources : any = {} public preferenceSources : any = {}
public GetPreference(key: string) : UIEventSource<string>{ public GetPreference(key: string) : UIEventSource<string>{
if(this.preferenceSources[key] !== undefined){ if (this.preferenceSources[key] !== undefined) {
return this.preferenceSources[key]; return this.preferenceSources[key];
} }
this.UpdatePreferences(); if (this.userDetails.data.loggedIn) {
console.log("Getting preference object", key, "currently upstreamed as ",this.preferences.data[key] ); this.UpdatePreferences();
}
const pref = new UIEventSource<string>(this.preferences.data[key]); const pref = new UIEventSource<string>(this.preferences.data[key]);
pref.addCallback((v) => { pref.addCallback((v) => {
this.SetPreference(key, v); this.SetPreference(key, v);

View file

@ -32,15 +32,16 @@ export class StrayClickHandler {
self._lastMarker = L.marker([lastClick.lat, lastClick.lon]); self._lastMarker = L.marker([lastClick.lat, lastClick.lon]);
const uiElement = uiToShow(); const uiElement = uiToShow();
const popup = L.popup().setContent(uiElement.Render()); const popup = L.popup().setContent(uiElement.Render());
uiElement.Activate();
uiElement.Update(); uiElement.Update();
uiElement.Activate();
self._lastMarker.addTo(map); self._lastMarker.addTo(map);
self._lastMarker.bindPopup(popup).openPopup(); self._lastMarker.bindPopup(popup).openPopup();
self._lastMarker.on("click", () => { self._lastMarker.on("click", () => {
leftMessage.setData(self._uiToShow); leftMessage.setData(self._uiToShow);
}); });
uiElement.Update();
uiElement.Activate();
}); });
selectElement.addCallback(() => { selectElement.addCallback(() => {

View file

@ -25,6 +25,10 @@ export class Regex extends TagsFilter {
} }
matches(tags: { k: string; v: string }[]): boolean { matches(tags: { k: string; v: string }[]): boolean {
if(!(tags instanceof Array)){
throw "You used 'matches' on something that is not a list. Did you mean to use 'matchesProperties'?"
}
for (const tag of tags) { for (const tag of tags) {
if (tag.k === this._k) { if (tag.k === this._k) {
if (tag.v === "") { if (tag.v === "") {
@ -201,6 +205,28 @@ export class And extends TagsFilter {
} }
} }
export class Not extends TagsFilter{
private not: TagsFilter;
constructor(not: TagsFilter) {
super();
this.not = not;
}
asOverpass(): string[] {
throw "Not supported yet"
}
matches(tags: { k: string; v: string }[]): boolean {
return !this.not.matches(tags);
}
substituteValues(tags: any): TagsFilter {
return new Not(this.not.substituteValues(tags));
}
}
export class TagUtils { export class TagUtils {

View file

@ -20,6 +20,7 @@ Furthermore, it shows images present in the `image` tag or, if a `wikidata` or `
- [Buurtnatuur.be](http://buurntatuur.be), developed for the Belgian [Green party](https://www.groen.be/). They also funded the initial development! - [Buurtnatuur.be](http://buurntatuur.be), developed for the Belgian [Green party](https://www.groen.be/). They also funded the initial development!
- [Cyclofix](https://pietervdvn.github.io/MapComplete/index.html?quests=pomp), further development on [Open Summer of Code](https://summerofcode.be/) funded by [Brussels Mobility](https://mobilite-mobiliteit.brussels/en) - [Cyclofix](https://pietervdvn.github.io/MapComplete/index.html?quests=pomp), further development on [Open Summer of Code](https://summerofcode.be/) funded by [Brussels Mobility](https://mobilite-mobiliteit.brussels/en)
- [Bookcases](https://pietervdvn.github.io/MapComplete/index.html?quests=bookcases#element) cause I like to collect them. - [Bookcases](https://pietervdvn.github.io/MapComplete/index.html?quests=bookcases#element) cause I like to collect them.
- [Map of Maps](https://pietervdvn.github.io/MapComplete/index.html?layout=metamap#element), after a tweet
Have a theme idea? Drop it in the [issues](https://github.com/pietervdvn/MapComplete/issues) Have a theme idea? Drop it in the [issues](https://github.com/pietervdvn/MapComplete/issues)

19
UI/Base/CheckBox.ts Normal file
View file

@ -0,0 +1,19 @@
import {UIElement} from "../UIElement";
import {UIEventSource} from "../UIEventSource";
export class CheckBox extends UIElement{
private data: UIEventSource<boolean>;
constructor(data: UIEventSource<boolean>) {
super(data);
this.data = data;
}
protected InnerRender(): string {
return "Current val: "+this.data.data;
}
}

View file

@ -25,16 +25,4 @@ export class VerticalCombine extends UIElement {
} }
return "<div class='"+this._className+"'>" + html + "</div>"; return "<div class='"+this._className+"'>" + html + "</div>";
} }
InnerUpdate(htmlElement: HTMLElement) {
for (const element of this._elements){
element.Update();
}
}
Activate() {
for (const element of this._elements){
element.Activate();
}
}
} }

View file

@ -39,13 +39,12 @@ export class CenterMessageBox extends UIElement {
if (this._centermessage.data != "") { if (this._centermessage.data != "") {
return this._centermessage.data; return this._centermessage.data;
} }
if (this._queryRunning.data) {
if (this._zoomInMore.data) { return "Data is loading...";
return "Zoom in om de data te zien en te bewerken"; } else if (this._zoomInMore.data) {
} else if (this._queryRunning.data) { return "Zoom in more to see the data";
return "Data wordt geladen...";
} }
return "Klaar!"; return "Done!";
} }

View file

@ -41,12 +41,13 @@ export class FeatureInfoBox extends UIElement {
this._userDetails = userDetails; this._userDetails = userDetails;
this.ListenTo(userDetails); this.ListenTo(userDetails);
const deps = {tags:this._tagsES , changes:this._changes}
this._infoboxes = []; this._infoboxes = [];
elementsToShow = elementsToShow ?? [] elementsToShow = elementsToShow ?? []
for (const tagRenderingOption of elementsToShow) { for (const tagRenderingOption of elementsToShow) {
this._infoboxes.push( this._infoboxes.push(
tagRenderingOption.construct(this._tagsES, this._changes)); tagRenderingOption.construct(deps));
} }
title = title ?? new TagRenderingOptions( title = title ?? new TagRenderingOptions(
@ -55,9 +56,9 @@ export class FeatureInfoBox extends UIElement {
} }
) )
this._title = new TagRenderingOptions(title.options).construct(this._tagsES, this._changes); this._title = new TagRenderingOptions(title.options).construct(deps);
this._osmLink =new OsmLink().construct(this._tagsES, this._changes); this._osmLink =new OsmLink().construct(deps);
this._wikipedialink = new WikipediaLink().construct(this._tagsES, this._changes); this._wikipedialink = new WikipediaLink().construct(deps);
} }
@ -113,19 +114,5 @@ export class FeatureInfoBox extends UIElement {
"" + "" +
"</div>"; "</div>";
} }
Activate() {
super.Activate();
for (const infobox of this._infoboxes) {
infobox.Activate();
}
}
Update() {
super.Update();
this._title.Update();
for (const infobox of this._infoboxes) {
infobox.Update();
}
}
} }

View file

@ -23,10 +23,10 @@ export class ImageCarouselConstructor implements TagDependantUIElementConstructo
return 0; return 0;
} }
construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement { construct(dependencies: { tags: UIEventSource<any>, changes: Changes }): TagDependantUIElement {
return new ImageCarousel(tags, changes); return new ImageCarousel(dependencies.tags, dependencies.changes);
} }
} }
export class ImageCarousel extends TagDependantUIElement { export class ImageCarousel extends TagDependantUIElement {

View file

@ -19,8 +19,8 @@ export class ImageCarouselWithUploadConstructor implements TagDependantUIElement
return 0; return 0;
} }
construct(tags: UIEventSource<any>, changes: Changes): TagDependantUIElement { construct(dependencies): TagDependantUIElement {
return new ImageCarouselWithUpload(tags, changes); return new ImageCarouselWithUpload(dependencies);
} }
} }
@ -28,8 +28,10 @@ class ImageCarouselWithUpload extends TagDependantUIElement {
private _imageElement: ImageCarousel; private _imageElement: ImageCarousel;
private _pictureUploader: ImageUploadFlow; private _pictureUploader: ImageUploadFlow;
constructor(tags: UIEventSource<any>, changes: Changes) { constructor(dependencies: {tags: UIEventSource<any>, changes: Changes}) {
super(tags); super(dependencies.tags);
const tags = dependencies.tags;
const changes = dependencies.changes;
this._imageElement = new ImageCarousel(tags, changes); this._imageElement = new ImageCarousel(tags, changes);
const userDetails = changes.login.userDetails; const userDetails = changes.login.userDetails;
const license = changes.login.GetPreference( "mapcomplete-pictures-license"); const license = changes.login.GetPreference( "mapcomplete-pictures-license");

View file

@ -9,7 +9,6 @@ import {VariableUiElement} from "./Base/VariableUIElement";
export class ImageUploadFlow extends UIElement { export class ImageUploadFlow extends UIElement {
private _licensePicker: UIElement; private _licensePicker: UIElement;
private _selectedLicence: UIEventSource<string>; private _selectedLicence: UIEventSource<string>;
private _licenseExplanation: UIElement;
private _isUploading: UIEventSource<number> = new UIEventSource<number>(0) private _isUploading: UIEventSource<number> = new UIEventSource<number>(0)
private _uploadOptions: (license: string) => { title: string; description: string; handleURL: (url: string) => void; allDone: (() => void) }; private _uploadOptions: (license: string) => { title: string; description: string; handleURL: (url: string) => void; allDone: (() => void) };
private _userdetails: UIEventSource<UserDetails>; private _userdetails: UIEventSource<UserDetails>;
@ -31,12 +30,12 @@ export class ImageUploadFlow extends UIElement {
this._uploadOptions = uploadOptions; this._uploadOptions = uploadOptions;
this.ListenTo(this._isUploading); this.ListenTo(this._isUploading);
const licensePicker = new DropDownUI("Jouw foto wordt gepubliceerd ", const licensePicker = new DropDownUI("The picture is published ",
[ [
{value: "CC0", shown: "in het publiek domein"}, {value: "CC0", shown: "in the public domain"},
{value: "CC-BY-SA 4.0", shown: "onder een CC-BY-SA-licentie"}, {value: "CC-BY-SA 4.0", shown: "with a CC-BY-SA license"},
{value: "CC-BY 4.0", shown: "onder een CC-BY-licentie"} {value: "CC-BY 4.0", shown: "with a CC-BY license"}
], ],
preferedLicense preferedLicense
); );
@ -44,48 +43,37 @@ export class ImageUploadFlow extends UIElement {
this._selectedLicence = licensePicker.selectedElement; this._selectedLicence = licensePicker.selectedElement;
const licenseExplanations = {
"CC-BY-SA 4.0":
"<b>Creative Commonse met naamsvermelding en gelijk delen</b><br/>" +
"Je foto mag door iedereen gratis gebruikt worden, als ze je naam vermelden én ze afgeleide werken met deze licentie en attributie delen.",
"CC-BY 4.0":
"<b>Creative Commonse met naamsvermelding</b> <br/>" +
"Je foto mag door iedereen gratis gebruikt worden, als ze je naam vermelden",
"CC0":
"<b>Geen copyright</b><br/> Je foto mag door iedereen voor alles gebruikt worden"
}
this._licenseExplanation = new VariableUiElement(
this._selectedLicence.map((license) => {
return licenseExplanations[license]
})
);
} }
protected InnerRender(): string { protected InnerRender(): string {
if (!this._userdetails.data.loggedIn) { if (!this._userdetails.data.loggedIn) {
return "<div class='activate-osm-authentication'>Gelieve je aan te melden om een foto toe te voegen of vragen te beantwoorden</div>"; return "<div class='activate-osm-authentication'>Please log in to add a picture</div>";
} }
let uploadingMessage = "";
if (this._isUploading.data == 1) { if (this._isUploading.data == 1) {
return "<b>Bezig met een foto te uploaden...</b>" uploadingMessage = "<b>Uploading a picture...</b>"
} }
if (this._isUploading.data > 0) { if (this._isUploading.data > 0) {
return "<b>Bezig met uploaden, nog " + this._isUploading.data + " foto's te gaan...</b>" uploadingMessage = "<b>Uploading multiple pictures, " + this._isUploading.data + " left...</b>"
} }
return "" + return "" +
"<div class='imageflow'>" + "<div class='imageflow'>" +
"<label for='fileselector-" + this.id + "'>" + "<label for='fileselector-" + this.id + "'>" +
"<div class='imageflow-file-input-wrapper'>" + "<div class='imageflow-file-input-wrapper'>" +
"<img src='./assets/camera-plus.svg' alt='upload image'/> " + "<img src='./assets/camera-plus.svg' alt='upload image'/> " +
"<span class='imageflow-add-picture'>Voeg foto toe</span>" + "<span class='imageflow-add-picture'>Add a picture</span>" +
"<div class='break'></div>"+ "<div class='break'></div>" +
"</div>" + "</div>" +
this._licensePicker.Render() +
this._licensePicker.Render() + "<br/>" +
uploadingMessage +
"</label>" + "</label>" +
"<input id='fileselector-" + this.id + "' " + "<input id='fileselector-" + this.id + "' " +

View file

@ -22,7 +22,7 @@ export class MessageBoxHandler {
} }
} }
new VariableUiElement(new UIEventSource<string>("<h2>Naar de kaart</h2>"), new VariableUiElement(new UIEventSource<string>("<h2>Return to the map</h2>"),
() => { () => {
document.getElementById("to-the-map").onclick = function () { document.getElementById("to-the-map").onclick = function () {
uielement.setData(undefined); uielement.setData(undefined);

View file

@ -1,20 +1,24 @@
import {UIElement} from "./UIElement"; import {UIElement} from "./UIElement";
import {UIEventSource} from "./UIEventSource"; import {UIEventSource} from "./UIEventSource";
import {Changes} from "../Logic/Changes";
export class PendingChanges extends UIElement { export class PendingChanges extends UIElement {
private _pendingChangesCount: UIEventSource<number>; private _pendingChangesCount: UIEventSource<number>;
private _countdown: UIEventSource<number>; private _countdown: UIEventSource<number>;
private _isSaving: UIEventSource<boolean>; private _isSaving: UIEventSource<boolean>;
constructor(pendingChangesCount: UIEventSource<number>, constructor(changes: Changes,
countdown: UIEventSource<number>, countdown: UIEventSource<number>) {
isSaving: UIEventSource<boolean>) { super(changes.pendingChangesES);
super(pendingChangesCount); this.ListenTo(changes.isSaving);
this.ListenTo(isSaving);
this.ListenTo(countdown); this.ListenTo(countdown);
this._pendingChangesCount = pendingChangesCount; this._pendingChangesCount = changes.pendingChangesES;
this._countdown = countdown; this._countdown = countdown;
this._isSaving = isSaving; this._isSaving = changes.isSaving;
this.onClick(() => {
changes.uploadAll();
})
} }
protected InnerRender(): string { protected InnerRender(): string {

View file

@ -43,10 +43,5 @@ export class QuestionPicker extends UIElement {
highestQ.CreateHtml(this.source).Render() + highestQ.CreateHtml(this.source).Render() +
"</div>"; "</div>";
} }
InnerUpdate(htmlElement: HTMLElement) {
}
Activate() {
}
} }

View file

@ -19,7 +19,7 @@ export class SaveButton extends UIElement {
) { ) {
return "<span class='save-non-active'>Opslaan</span>" return "<span class='save-non-active'>Opslaan</span>"
} }
return "<span class='save'>Opslaan</span>"; return "<span class='save'>Save</span>";
} }
} }

View file

@ -8,8 +8,8 @@ import {Basemap} from "../Logic/Basemap";
export class SearchAndGo extends UIElement { export class SearchAndGo extends UIElement {
private _placeholder = new UIEventSource("Zoek naar een locatie...") private _placeholder = new UIEventSource("Search a location...")
private _searchField = new TextField(this._placeholder); private _searchField = new TextField(this._placeholder, undefined);
private _foundEntries = new UIEventSource([]); private _foundEntries = new UIEventSource([]);
private _map: Basemap; private _map: Basemap;
@ -35,7 +35,7 @@ export class SearchAndGo extends UIElement {
private RunSearch() { private RunSearch() {
const searchString = this._searchField.value.data; const searchString = this._searchField.value.data;
this._searchField.Clear(); this._searchField.Clear();
this._placeholder.setData("Bezig met zoeken..."); this._placeholder.setData("Searching...");
const self = this; const self = this;
Geocoding.Search(searchString, this._map, (result) => { Geocoding.Search(searchString, this._map, (result) => {
@ -50,10 +50,10 @@ export class SearchAndGo extends UIElement {
[bb[1], bb[3]] [bb[1], bb[3]]
] ]
self._map.map.fitBounds(bounds); self._map.map.fitBounds(bounds);
this._placeholder.setData("Zoek naar een locatie..."); this._placeholder.setData("Search a location...");
}, },
() => { () => {
this._placeholder.setData("Niets gevonden: er ging iets mis"); this._placeholder.setData("Something went wrong. Try again.");
}); });
} }

View file

@ -42,7 +42,7 @@ export class SimpleAddUI extends UIElement {
// <button type='button'> looks SO retarded // <button type='button'> looks SO retarded
// the default type of button is 'submit', which performs a POST and page reload // the default type of button is 'submit', which performs a POST and page reload
const button = const button =
new Button(new FixedUiElement("Voeg hier een " + option.name + " toe"), new Button(new FixedUiElement("Add a " + option.name + " here"),
this.CreatePoint(option)); this.CreatePoint(option));
this._addButtons.push(button); this._addButtons.push(button);
} }
@ -61,18 +61,18 @@ export class SimpleAddUI extends UIElement {
} }
protected InnerRender(): string { protected InnerRender(): string {
const header = "<h2>Geen selectie</h2>" + const header = "<h2>No data here</h2>" +
"Je klikte ergens waar er nog geen gezochte data is.<br/>"; "You clicked somewhere where no data is known yet.<br/>";
if (!this._userDetails.data.loggedIn) { if (!this._userDetails.data.loggedIn) {
return header + "<a class='activate-osm-authentication'>Gelieve je aan te melden om een nieuw punt toe te voegen</a>" return header + "<a class='activate-osm-authentication'>Please log in to add a new point</a>"
} }
if (this._zoomlevel.data.zoom < 19) { if (this._zoomlevel.data.zoom < 19) {
return header + "Zoom verder in om een element toe te voegen."; return header + "Zoom in further to add a point.";
} }
if (this._dataIsLoading.data) { if (this._dataIsLoading.data) {
return header + "De data is nog aan het laden. Nog even geduld, dan kan je een punt toevoegen"; return header + "The data is still loading. Please wait a bit before you add a new point";
} }
var html = ""; var html = "";

View file

@ -1,4 +1,5 @@
import {UIEventSource} from "./UIEventSource"; import {UIEventSource} from "./UIEventSource";
import instantiate = WebAssembly.instantiate;
export abstract class UIElement { export abstract class UIElement {
@ -58,20 +59,22 @@ export abstract class UIElement {
} }
element.style.pointerEvents = "all"; element.style.pointerEvents = "all";
element.style.cursor = "pointer"; element.style.cursor = "pointer";
/*
const childs = element.children;
for (let i = 0; i < childs.length; i++) {
const ch = childs[i];
console.log(ch);
ch.style.cursor = "pointer";
ch.onclick = () => {
self._onClick();
}
ch.style.pointerEvents = "all";
}*/
} }
this.InnerUpdate(element); this.InnerUpdate(element);
for (const i in this) {
const child = this[i];
if (child instanceof UIElement) {
child.Update();
} else if (child instanceof Array) {
for (const ch of child) {
if (ch instanceof UIElement) {
ch.Update();
}
}
}
}
} }
HideOnEmpty(hide : boolean){ HideOnEmpty(hide : boolean){
@ -89,7 +92,7 @@ export abstract class UIElement {
AttachTo(divId: string) { AttachTo(divId: string) {
let element = document.getElementById(divId); let element = document.getElementById(divId);
if(element === null){ if (element === null) {
console.log("SEVERE: could not attach UIElement to ", divId); console.log("SEVERE: could not attach UIElement to ", divId);
return; return;
} }
@ -99,7 +102,21 @@ export abstract class UIElement {
} }
protected abstract InnerRender(): string; protected abstract InnerRender(): string;
public Activate(): void {};
public Activate(): void {
for (const i in this) {
const child = this[i];
if (child instanceof UIElement) {
child.Activate();
} else if (child instanceof Array) {
for (const ch of child) {
if (ch instanceof UIElement) {
ch.Activate();
}
}
}
}
};
public IsEmpty(): boolean { public IsEmpty(): boolean {
return this.InnerRender() === ""; return this.InnerRender() === "";

View file

@ -4,6 +4,7 @@ import {UIEventSource} from "./UIEventSource";
import {Basemap} from "../Logic/Basemap"; import {Basemap} from "../Logic/Basemap";
import L from "leaflet"; import L from "leaflet";
import {FixedUiElement} from "./Base/FixedUiElement"; import {FixedUiElement} from "./Base/FixedUiElement";
import {VariableUiElement} from "./Base/VariableUIElement";
/** /**
* Handles and updates the user badge * Handles and updates the user badge
@ -13,6 +14,7 @@ export class UserBadge extends UIElement {
private _pendingChanges: UIElement; private _pendingChanges: UIElement;
private _logout: UIElement; private _logout: UIElement;
private _basemap: Basemap; private _basemap: Basemap;
private _homeButton: UIElement;
constructor(userDetails: UIEventSource<UserDetails>, constructor(userDetails: UIEventSource<UserDetails>,
@ -38,12 +40,27 @@ export class UserBadge extends UIElement {
} }
}); });
this._homeButton = new VariableUiElement(
userDetails.map((userinfo) => {
if (userinfo.home) {
return "<img id='home' src='./assets/home.svg' alt='home' class='small-userbadge-icon'> ";
}
return "";
})
).onClick(() => {
const home = userDetails.data?.home;
if (home === undefined) {
return;
}
basemap.map.flyTo([home.lat, home.lon], 18);
});
} }
protected InnerRender(): string { protected InnerRender(): string {
const user = this._userDetails.data; const user = this._userDetails.data;
if (!user.loggedIn) { if (!user.loggedIn) {
return "<div class='activate-osm-authentication'>Klik hier om aan te melden bij OSM</div>"; return "<div class='activate-osm-authentication'>Login with OpenStreetMap</div>";
} }
@ -66,9 +83,7 @@ export class UserBadge extends UIElement {
dryrun = " <span class='alert'>TESTING</span>"; dryrun = " <span class='alert'>TESTING</span>";
} }
let home = "";
if (user.home !== undefined) { if (user.home !== undefined) {
home = "<img id='home' src='./assets/home.svg' alt='home' class='small-userbadge-icon'> ";
const icon = L.icon({ const icon = L.icon({
iconUrl: 'assets/home.svg', iconUrl: 'assets/home.svg',
iconSize: [20, 20], iconSize: [20, 20],
@ -91,7 +106,7 @@ export class UserBadge extends UIElement {
dryrun + dryrun +
"</p> " + "</p> " +
"<p id='userstats'>" + "<p id='userstats'>" +
home + this._homeButton.Render() +
settings + settings +
messageSpan + messageSpan +
"<span id='csCount'> " + "<span id='csCount'> " +
@ -104,25 +119,5 @@ export class UserBadge extends UIElement {
"</div>"; "</div>";
} }
InnerUpdate(htmlElement: HTMLElement) {
this._pendingChanges.Update();
var btn = document.getElementById("home");
if (btn) {
const self = this;
btn.onclick = function () {
const home = self._userDetails?.data?.home;
if (home === undefined) {
return;
}
self._basemap.map.flyTo([home.lat, home.lon], 18);
}
}
this._logout.Update();
}
Activate() {
this._pendingChanges.Activate();
}
} }

View file

@ -9,9 +9,10 @@
<rect x="34.3118" y="72.5698" width="28" height="5" fill="white"/> <rect x="34.3118" y="72.5698" width="28" height="5" fill="white"/>
<rect x="65.3118" y="60.5698" width="4" height="8" fill="white"/> <rect x="65.3118" y="60.5698" width="4" height="8" fill="white"/>
<rect x="68.3118" y="64.5699" width="3" height="4" fill="white"/> <rect x="68.3118" y="64.5699" width="3" height="4" fill="white"/>
<rect x="66" y="72.2385" width="21.8167" height="3.68967" transform="rotate(-44.3049 66 72.2385)" fill="#F00D0D"/> <rect x="56" y="42" width="5" height="10" fill="#171615"/>
</g> </g>
<rect x="68.4303" y="56.8712" width="22.1163" height="3.52552" transform="rotate(43.5782 68.4303 56.8712)" fill="#F00D0D"/> <rect x="72.4167" y="53.8615" width="29.0549" height="7.85787" transform="rotate(43.5782 72.4167 53.8615)" fill="#F00D0D"/>
<path d="M68.2141 73.9097L88.6128 54L94.0003 59.5199L73.6016 79.4295L68.2141 73.9097Z" fill="#F00D0D"/>
<defs> <defs>
<filter id="filter0_d" x="-3" y="2" width="102.479" height="102.479" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> <filter id="filter0_d" x="-3" y="2" width="102.479" height="102.479" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/> <feFlood flood-opacity="0" result="BackgroundImageFix"/>

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -0,0 +1,18 @@
<svg width="98" height="124" viewBox="0 0 98 124" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M55.0445 114.094C53.2614 117.981 47.7386 117.981 45.9555 114.094L15.2124 47.085C13.6928 43.7729 16.1129 40 19.7569 40L81.2431 40C84.8871 40 87.3072 43.7729 85.7876 47.085L55.0445 114.094Z" fill="#6BC4F7"/>
<circle cx="49" cy="49" r="49" fill="#6BC4F7"/>
<g filter="url(#filter0_d)">
<path d="M79 41.8705C79 39.3976 77.4079 35.6726 74.1327 30.4823C71.8064 26.7956 69.5171 23.8005 69.4208 23.6747C69.0964 23.2513 68.5726 23 68.0144 23C67.4562 23 66.9322 23.2514 66.6078 23.6748C66.3787 23.9738 61.828 29.939 59.0942 35.3688C54.8849 28.8794 50.9494 23.7307 50.9067 23.6748C50.5821 23.2513 50.0582 23 49.5 23C48.9418 23 48.4179 23.2513 48.0934 23.6747C48.0468 23.7357 43.367 29.8581 38.753 37.1701C38.2587 37.9536 37.7856 38.7192 37.3295 39.4706C34.9483 35.6504 32.5162 32.4661 32.3922 32.3043C32.0677 31.8809 31.5438 31.6296 30.9856 31.6296C30.4274 31.6296 29.9036 31.8809 29.5791 32.3043C29.4828 32.43 27.1935 35.4252 24.8672 39.1119C21.5921 44.3021 20 48.0271 20 50.5C20 55.6193 24.0504 59.8732 29.3205 60.6234C30.1402 70.3329 38.8775 78 49.5 78C60.6619 78 69.7429 69.5347 69.7429 59.1295C69.7429 57.2539 69.2077 54.9089 68.1449 52.1097C74.1423 52.0443 79 47.4766 79 41.8705V41.8705ZM23.457 50.5C23.457 49.457 24.0257 46.8053 27.8344 40.7656C28.9755 38.9562 30.126 37.2947 30.9856 36.0929C32.1576 37.7318 33.8718 40.2278 35.3741 42.8008C31.9223 48.9002 29.9183 53.7824 29.3954 57.3607C26.0053 56.6784 23.457 53.8613 23.457 50.5V50.5ZM49.5 74.7773C40.2443 74.7773 32.7142 67.7578 32.7142 59.1295C32.7142 56.3792 34.2766 50.6239 41.7201 38.8241C44.7375 34.0407 47.784 29.7745 49.5 27.4354C51.213 29.7702 54.2519 34.0258 57.2673 38.8042C64.7212 50.6167 66.2857 56.3773 66.2857 59.1296C66.2858 67.7578 58.7557 74.7773 49.5 74.7773V74.7773ZM68.0144 48.8887C67.5836 48.8887 67.156 48.8549 66.7362 48.7879C65.3713 45.8533 63.5372 42.506 61.2717 38.8163C62.8077 35.0043 66.1199 30.1147 68.0149 27.4638C68.8707 28.6601 70.0148 30.3125 71.153 32.1162C74.9727 38.1694 75.543 40.8257 75.543 41.8705C75.543 45.7402 72.1656 48.8887 68.0144 48.8887V48.8887Z" fill="white"/>
</g>
<defs>
<filter id="filter0_d" x="16" y="23" width="67" height="63" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -1,86 +1,11 @@
<svg width="97" height="123" viewBox="0 0 97 123" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="97" height="123" viewBox="0 0 97 123" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M52.1412 111.419C50.4633 115.605 44.5366 115.605 42.8588 111.419L24.7014 66.1099C23.385 62.8252 25.8039 59.25 29.3426 59.25L65.6574 59.25C69.1962 59.25 71.615 62.8252 70.2986 66.11L52.1412 111.419Z" fill="#5675DF"/> <path d="M52.1412 111.419C50.4633 115.605 44.5366 115.605 42.8588 111.419L24.7014 66.1099C23.385 62.8252 25.8039 59.25 29.3426 59.25L65.6574 59.25C69.1962 59.25 71.615 62.8252 70.2986 66.11L52.1412 111.419Z" fill="#1647F8"/>
<ellipse cx="48.5" cy="47.5" rx="48.5" ry="47.5" fill="#5675DF"/> <ellipse cx="48.5" cy="47.5" rx="48.5" ry="47.5" fill="#1647F8"/>
<g filter="url(#filter0_d)"> <g filter="url(#filter0_d)">
<circle cx="39" cy="66" r="2" stroke="white" stroke-width="2"/> <path d="M42.2812 53.1875V71H36.2812V25.5H53.0625C58.0417 25.5 61.9375 26.7708 64.75 29.3125C67.5833 31.8542 69 35.2188 69 39.4062C69 43.8229 67.6146 47.2292 64.8438 49.625C62.0938 52 58.1458 53.1875 53 53.1875H42.2812ZM42.2812 48.2812H53.0625C56.2708 48.2812 58.7292 47.5312 60.4375 46.0312C62.1458 44.5104 63 42.3229 63 39.4688C63 36.7604 62.1458 34.5938 60.4375 32.9688C58.7292 31.3438 56.3854 30.5 53.4062 30.4375H42.2812V48.2812Z" fill="white"/>
</g> </g>
<g filter="url(#filter1_d)">
<path d="M37.375 67H25L31.75 51.4H38.5H43.375H48.625M48.625 51.4L46.75 47H49.375H52M48.625 51.4L49.375 53.4L50.875 56.6L55 67M48.625 51.4L45.0625 57.4L42.925 61M41.5 63.4L42.925 61M34.375 55.8L38.125 64.6L30.625 47L32.875 51.8M40.375 65.4L42.925 61" stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter2_d)">
<circle cx="23" cy="67" r="9" stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter3_d)">
<circle cx="55" cy="67" r="9" stroke="white" stroke-width="2"/>
</g>
<path d="M61 77V59.0476V55.9524L62.4814 54.4851C64.4301 52.5549 67.5699 52.5549 69.5186 54.4851L71 55.9524V58.4286V77" stroke="white" stroke-width="2"/>
<line x1="66" y1="53" x2="66" y2="16" stroke="white" stroke-width="2"/>
<g filter="url(#filter4_d)">
<circle cx="66" cy="23" r="13" fill="white"/>
</g>
<g filter="url(#filter5_d)">
<circle cx="66" cy="23" r="11" fill="#496DEB"/>
</g>
<g filter="url(#filter6_d)">
<path d="M64.1729 24.9902V30H62.4854V17.2031H67.2051C68.6055 17.2031 69.7012 17.5605 70.4922 18.2754C71.2891 18.9902 71.6875 19.9365 71.6875 21.1143C71.6875 22.3564 71.2979 23.3145 70.5186 23.9883C69.7451 24.6562 68.6348 24.9902 67.1875 24.9902H64.1729ZM64.1729 23.6104H67.2051C68.1074 23.6104 68.7988 23.3994 69.2793 22.9775C69.7598 22.5498 70 21.9346 70 21.1318C70 20.3701 69.7598 19.7607 69.2793 19.3037C68.7988 18.8467 68.1396 18.6094 67.3018 18.5918H64.1729V23.6104Z" fill="white"/>
</g>
<line x1="43" y1="78" x2="72" y2="78" stroke="white" stroke-width="2"/>
<defs> <defs>
<filter id="filter0_d" x="32" y="63" width="14" height="14" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> <filter id="filter0_d" x="32.2812" y="25.5" width="40.7188" height="53.5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="19.4777" y="46" width="40.4518" height="30" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter2_d" x="9" y="57" width="28" height="28" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter3_d" x="41" y="57" width="28" height="28" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter4_d" x="49" y="10" width="34" height="34" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter5_d" x="51" y="12" width="30" height="30" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter6_d" x="58.4854" y="17.2031" width="17.2021" height="20.7969" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/> <feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/> <feOffset dy="4"/>

Before

Width:  |  Height:  |  Size: 6 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1,93 @@
<svg width="97" height="123" viewBox="0 0 97 123" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M52.1412 111.419C50.4633 115.605 44.5366 115.605 42.8588 111.419L24.7014 66.1099C23.385 62.8252 25.8039 59.25 29.3426 59.25L65.6574 59.25C69.1962 59.25 71.615 62.8252 70.2986 66.11L52.1412 111.419Z" fill="#5675DF"/>
<ellipse cx="48.5" cy="47.5" rx="48.5" ry="47.5" fill="#5675DF"/>
<g filter="url(#filter0_d)">
<circle cx="39" cy="66" r="2" stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter1_d)">
<path d="M37.375 67H25L31.75 51.4H38.5H43.375H48.625M48.625 51.4L46.75 47H49.375H52M48.625 51.4L49.375 53.4L50.875 56.6L55 67M48.625 51.4L45.0625 57.4L42.925 61M41.5 63.4L42.925 61M34.375 55.8L38.125 64.6L30.625 47L32.875 51.8M40.375 65.4L42.925 61" stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter2_d)">
<circle cx="23" cy="67" r="9" stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter3_d)">
<circle cx="55" cy="67" r="9" stroke="white" stroke-width="2"/>
</g>
<path d="M61 77V59.0476V55.9524L62.4814 54.4851C64.4301 52.5549 67.5699 52.5549 69.5186 54.4851L71 55.9524V58.4286V77" stroke="white" stroke-width="2"/>
<line x1="66" y1="53" x2="66" y2="16" stroke="white" stroke-width="2"/>
<g filter="url(#filter4_d)">
<circle cx="66" cy="23" r="13" fill="white"/>
</g>
<g filter="url(#filter5_d)">
<circle cx="66" cy="23" r="11" fill="#496DEB"/>
</g>
<g filter="url(#filter6_d)">
<path d="M64.1729 24.9902V30H62.4854V17.2031H67.2051C68.6055 17.2031 69.7012 17.5605 70.4922 18.2754C71.2891 18.9902 71.6875 19.9365 71.6875 21.1143C71.6875 22.3564 71.2979 23.3145 70.5186 23.9883C69.7451 24.6562 68.6348 24.9902 67.1875 24.9902H64.1729ZM64.1729 23.6104H67.2051C68.1074 23.6104 68.7988 23.3994 69.2793 22.9775C69.7598 22.5498 70 21.9346 70 21.1318C70 20.3701 69.7598 19.7607 69.2793 19.3037C68.7988 18.8467 68.1396 18.6094 67.3018 18.5918H64.1729V23.6104Z" fill="white"/>
</g>
<line x1="43" y1="78" x2="72" y2="78" stroke="white" stroke-width="2"/>
<defs>
<filter id="filter0_d" x="32" y="63" width="14" height="14" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="19.4777" y="46" width="40.4518" height="30" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter2_d" x="9" y="57" width="28" height="28" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter3_d" x="41" y="57" width="28" height="28" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter4_d" x="49" y="10" width="34" height="34" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter5_d" x="51" y="12" width="30" height="30" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter6_d" x="58.4854" y="17.2031" width="17.2021" height="20.7969" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6 KiB

View file

@ -1 +0,0 @@
<?xml version="1.0" ?><svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><g id="outline"><path d="M18.253,60.667a4.535,4.535,0,1,0,6.414-6.414L20.914,50.5,22,49.414l.793.793a4.539,4.539,0,0,0,6.414,0l22-22a2.535,2.535,0,1,1,3.585,3.586L36.59,50.005l-.712-.712a1,1,0,0,0-1.4-.01l-3.263,3.173a5,5,0,0,0-.049,7.12l2.131,2.131a1,1,0,0,0,1.414,0l3-3a1,1,0,0,0-.015-1.428l-1.357-1.3,2.382-2.45a1,1,0,0,0-.01-1.4l-.7-.7,18.2-18.212a4.535,4.535,0,0,0-6.414-6.414l-22,22a2.54,2.54,0,0,1-3.586,0L23.414,48,45.207,26.207a1,1,0,0,0,0-1.414L44.414,24,50.5,17.914l6.293,6.293a1,1,0,0,0,1.414,0l3.5-3.5a1,1,0,0,0,0-1.414l-17-17a1,1,0,0,0-1.414,0l-3.5,3.5a1,1,0,0,0,0,1.414L46.086,13.5,40,19.586l-.793-.793a1,1,0,0,0-1.414,0L13.5,43.086,9.747,39.333a4.535,4.535,0,1,0-6.414,6.414ZM34.2,55.3a1,1,0,0,0,.024,1.418l1.347,1.294L34,59.586l-1.424-1.424a3,3,0,0,1,.03-4.273L35.162,51.4,36.6,52.838ZM41.914,6.5,44,4.414,59.586,20,57.5,22.086l-6.293-6.293-3-3ZM47.5,14.914,49.086,16.5,43,22.586,41.414,21Zm-9,6,.793.793,3,3,.793.793L22,46.586,17.414,42ZM16,43.414,20.586,48,17.5,51.086,12.914,46.5ZM4.747,40.747a2.585,2.585,0,0,1,3.586,0L12.086,44.5l-1.293,1.293a1,1,0,0,0,0,1.414l6,6a1,1,0,0,0,1.414,0L19.5,51.914l3.753,3.753a2.525,2.525,0,0,1,0,3.586,2.585,2.585,0,0,1-3.586,0L4.747,44.333a2.525,2.525,0,0,1,0-3.586Z"/><rect height="2.828" transform="translate(-28.355 17.544) rotate(-45)" width="2" x="6" y="41.586"/><rect height="2.828" transform="translate(-34.154 31.544) rotate(-45)" width="2" x="20" y="55.586"/><rect height="2" transform="translate(-8.256 33.485) rotate(-45)" width="2.003" x="35.29" y="25.708"/><rect height="2" transform="translate(-14.485 30.905) rotate(-45)" width="11.49" x="24.317" y="31.938"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="2"
width="50"
height="50"
viewBox="0 0 50 50"
id="svg4"
sodipodi:docname="ghost_bike.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1001"
id="namedview6"
showgrid="false"
inkscape:zoom="4.72"
inkscape:cx="-40.53625"
inkscape:cy="33.532739"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="background"
sodipodi:insensitive="true">
<ellipse
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:50;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path839"
cx="25"
cy="24.894068"
rx="25"
ry="25.105932" />
</g>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="bicycle">
<path
d="m 37.198846,28.51624 c -0.865699,0 -1.688316,0.177789 -2.435717,0.497127 l -2.103385,-3.60434 1.58506,-2.71676 c 0.215399,-0.370622 0.09027,-0.846552 -0.279675,-1.063319 -0.162747,-0.09437 -0.343955,-0.265316 -0.515591,-0.237279 l -0.134709,-0.158644 h -3.109265 c -0.428746,0 -0.776803,0.596963 -0.776803,1.02571 0,0.429429 0.348057,1.025708 0.776803,1.025708 h 2.015176 l -0.90741,1.367611 h -9.079572 l 1.813452,-3.419029 h 0.718681 c 0.428746,0 0.776802,-0.254375 0.776802,-0.683806 0,-0.42943 -0.348056,-0.683806 -0.776802,-0.683806 h -3.886069 c -0.428061,0 -0.776803,0.254376 -0.776803,0.683806 0,0.429431 0.348057,0.683806 0.776803,0.683806 h 1.366929 l -4.368835,7.634691 c -0.748084,-0.319337 -1.572071,-0.423959 -2.437085,-0.423959 -3.432704,0 -6.2157926,2.820014 -6.2157926,6.252718 0,3.433389 2.7830886,6.234257 6.2164776,6.234257 3.433388,0 6.216478,-2.774199 6.216478,-6.207588 0,-2.010389 -0.958697,-3.788967 -2.441187,-4.926136 l 1.663699,-2.848735 4.768861,8.17558 0.01847,0.02598 0.02051,0.03077 0.01572,0.02325 0.06154,0.07111 0.0076,0.0089 0.0212,0.01915 0.02188,0.01777 0.06017,0.04787 0.0253,0.01641 0.01983,0.01298 0.0082,0.0048 0.0027,0.0027 0.06564,0.03214 0.0076,0.0033 0.01573,0.0082 0.0054,0.0014 0.04992,0.01778 0.0465,0.01505 0.0095,0.0027 0.01709,0.0027 0.03008,0.0062 0.139496,0.01436 6.84e-4,0.04239 0.0027,0.04034 h 4.712106 c 0.384299,2.735223 2.9937,5.398646 6.16314,5.398646 3.433388,0 6.216478,-2.804288 6.216478,-6.237676 6.83e-4,-3.432704 -2.782407,-6.236991 -6.215794,-6.236991 z m -17.095143,6.216477 c 0,2.575896 -2.086974,4.662872 -4.662187,4.662872 -2.575213,0 -4.662188,-2.087659 -4.662188,-4.662872 0,-2.574528 2.086975,-4.661503 4.662188,-4.661503 0.579183,0 1.131698,0.110088 1.643185,0.30361 l -2.314683,3.96744 c -0.216082,0.369938 -0.09027,0.845868 0.280362,1.063319 0.123084,0.07111 0.257794,0.10531 0.390451,0.10531 0.267369,0 0.527215,-0.13813 0.672182,-0.384984 l 2.315367,-3.970175 c 1.022972,0.855441 1.675323,2.140312 1.675323,3.576987 z m 6.216477,-1.708146 -4.086422,-7.004905 h 8.173529 z m 5.438991,-5.938853 1.664383,2.918483 c -1.286923,0.987416 -2.17587,2.169715 -2.38785,4.221133 h -3.362956 z m 2.452811,4.338747 1.634979,2.800869 H 32.60709 c 0.187363,-1.367612 0.769965,-2.102702 1.604892,-2.800869 z m 2.986864,8.01352 c -2.309212,0 -4.222501,-1.793624 -4.592439,-3.84504 h 4.590387 l 0.0033,-0.04035 0.138811,-0.03624 0.03145,-0.01572 0.129239,-0.04513 0.01436,-0.01089 0.07727,-0.03966 0.01847,-0.01436 0.06907,-0.04992 0.05334,-0.04513 0.05197,-0.05675 0.0465,-0.05813 0.03898,-0.06292 0.03556,-0.06496 0.02667,-0.07111 0.0212,-0.07111 0.01164,-0.07111 0.0089,-0.08411 0.002,-0.02394 -0.0033,-0.04377 -0.0095,-0.0848 -0.01573,-0.07248 -0.02257,-0.07111 -0.03556,-0.07726 -0.01847,-0.04035 -2.314683,-3.96744 c 0.512856,-0.193517 1.064686,-0.30361 1.643186,-0.30361 2.575896,0 4.662871,2.108172 4.662871,4.682701 6.83e-4,2.575896 -2.086975,4.684753 -4.662871,4.684753 z"
id="path2"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.6838057"
inkscape:connector-curvature="0" />
<g
id="g861"
transform="translate(-10.037321,-26.552854)">
<path
inkscape:connector-curvature="0"
id="path842"
d="M 25.018397,35.018924 V 47.003785"
style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path842-3"
d="M 28.86857,39.213625 H 20.748791"
style="fill:none;stroke:#ffffff;stroke-width:1.64621139;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="cross" />
</svg>

Before

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -1,3 +0,0 @@
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" transform="scale(64)" fill="#1B1F23"/>
</svg>

Before

Width:  |  Height:  |  Size: 967 B

13030
assets/map-stickered.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 469 KiB

9268
assets/map.svg Normal file

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 297 KiB

BIN
assets/nature/ANB.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
assets/nature/birdhide.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 14 14"
version="1.1"
id="svg3800"
height="14"
width="14"
sodipodi:docname="birdhide.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
inkscape:export-filename="/home/pietervdvn/git/pietervdvn.github.io/Quickmaps/Natuurgebieden/resources/birdhide.png"
inkscape:export-xdpi="3900"
inkscape:export-ydpi="3900">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview6"
showgrid="false"
inkscape:zoom="33.714286"
inkscape:cx="4.9428996"
inkscape:cy="9.0125471"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg3800" />
<defs
id="defs3802" />
<metadata
id="metadata3805">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<circle
style="fill:#ffffff;fill-opacity:1"
id="path7"
cx="7.0296612"
cy="6.9703388"
r="6.6440678" />
<path
id="rect239-1"
d="M 4.4407552,2.5108724 V 3.7529742 H 6.1739363 V 2.5108724 Z m 3.3934716,0 V 3.7529742 H 9.5701063 V 2.5108724 Z m 0,1.6309338 v 3.4292811 c 0,0.1645196 0.1324726,0.2970271 0.2969603,0.2970271 h 0.021593 0.2753652 v 3.3239706 c 0,0.15899 0.1299047,0.288924 0.2888645,0.288924 h 2.5484772 c 0.158956,0 0.288865,-0.129931 0.288865,-0.288924 V 9.123717 l 0.0053,-0.3024259 -1.104162,-4.6794849 z m -4.2870589,0.00541 -1.10686,4.6794836 0.00541,0.3051254 v 2.0683688 c 4.9e-6,0.158994 0.1299127,0.288929 0.2888686,0.288929 h 2.5484784 c 0.1617203,0 0.2915631,-0.129932 0.2915631,-0.288924 V 7.8789218 h 0.2726602 0.021597 c 0.1644843,0 0.2969623,-0.1352088 0.2969623,-0.2997246 V 4.1472067 Z m 3.002021,0 V 7.3361653 H 7.4481742 V 4.1472067 Z"
style="fill:#94bb28;fill-opacity:1;stroke-width:1.38236964"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" version="1.1" id="svg3800" height="14" width="14">
<defs id="defs3802"/>
<metadata id="metadata3805">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<path id="rect239-1" d="M 3.0710695,0.10833 V 2.015194 H 5.7318342 V 0.10833 Z m 5.2096283,0 V 2.015194 H 10.945605 V 0.10833 Z m 0,2.5037956 v 5.2646027 c 0,0.2525691 0.2033707,0.4559935 0.4558908,0.4559935 h 0.033149 0.4227382 v 5.1029302 c 0,0.244081 0.1994286,0.443555 0.4434623,0.443555 h 3.9124009 c 0.244028,0 0.443463,-0.19947 0.443463,-0.443555 v -3.17534 L 14,9.7960303 12.3049,2.6121256 Z M 1.6992419,2.6204383 0,9.8043411 0.00831104,10.272767 v 3.175343 c 7.43e-6,0.244086 0.19944083,0.44356 0.44346846,0.44356 h 3.9124021 c 0.2482716,0 0.4476051,-0.19947 0.4476051,-0.443553 V 8.3493131 h 0.4185857 0.033155 c 0.2525149,0 0.455894,-0.2075714 0.455894,-0.4601346 V 2.6204164 Z m 4.6086768,0 V 7.5160781 H 7.6880332 V 2.6204164 Z" style="fill:#0E8517;stroke-width:2.12220192"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 14 14"
version="1.1"
id="svg3800"
height="14"
width="14"
sodipodi:docname="birdshelter.inkscape.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
inkscape:export-filename="/home/pietervdvn/git/pietervdvn.github.io/Quickmaps/Natuurgebieden/resources/birdshelter.png"
inkscape:export-xdpi="3900"
inkscape:export-ydpi="3900">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview6"
showgrid="false"
inkscape:zoom="33.714286"
inkscape:cx="3.8157807"
inkscape:cy="9.0740249"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg3800" />
<defs
id="defs3802">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 7 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="14 : 7 : 1"
inkscape:persp3d-origin="7 : 4.6666667 : 1"
id="perspective4523" />
</defs>
<metadata
id="metadata3805">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<ellipse
style="fill:#ffffff;fill-opacity:1;stroke-width:0.96618801"
id="path9"
cx="7.0148306"
cy="7"
rx="6.9851694"
ry="7" />
<path
id="rect239-1"
d="M 5.0138133,4.5480237 V 5.4372271 H 6.4140719 V 4.5480237 Z m 2.7416277,0 V 5.4372271 H 9.1578797 V 4.5480237 Z m 0,1.1675628 v 2.454974 c 0,0.1177775 0.107026,0.2126385 0.2399179,0.2126385 h 0.017446 0.2224709 v 2.379583 c 0,0.113819 0.1049524,0.206837 0.2333773,0.206837 h 2.0589459 c 0.128424,0 0.233378,-0.09302 0.233378,-0.206837 V 9.282066 l 0.0044,-0.216502 -0.892066,-3.3499775 z m -3.4635679,0.00388 -0.8942459,3.3499765 0.00437,0.218434 v 1.480717 c 3.8e-6,0.113821 0.1049574,0.20684 0.2333803,0.20684 h 2.0589473 c 0.130656,0 0.2355574,-0.09302 0.2355574,-0.206836 V 8.390934 H 6.150168 6.167616 c 0.1328889,0 0.2399196,-0.096794 0.2399196,-0.2145684 V 5.7194527 Z m 2.4253699,0 v 2.282916 H 7.4435445 V 5.7194527 Z"
style="fill:#94bb28;fill-opacity:1;stroke-width:1.05130398"
inkscape:connector-curvature="0"
inkscape:export-xdpi="3900"
inkscape:export-ydpi="3900" />
<path
style="fill:#734a08;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.17624903;stroke-opacity:1"
d="M 7.0593227,0.28398607 1.0677963,4.6955391 1.704503,5.3993537 2.12961,4.9333018 v 6.6739212 0.02403 c -1.796e-4,0.238872 0.092023,0.460535 0.243178,0.584635 0.1561692,0.127456 0.351061,0.131529 0.510078,0.01067 0.1596734,-0.120634 0.2586978,-0.34824 0.2589929,-0.595296 V 4.3860404 l 3.944152,-2.6948367 4.0509051,2.7489762 v 7.2452081 c -1.81e-4,0.23887 0.09202,0.460534 0.243177,0.584634 0.15617,0.127456 0.351062,0.131531 0.51008,0.01067 0.159673,-0.120633 0.258697,-0.348239 0.258993,-0.595296 V 4.9874442 l 0.37173,0.2224238 0.529952,-0.4331167 z"
id="rect4777"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccccccc" />
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
id="svg3800"
version="1.1"
viewBox="0 0 14 14">
<defs
id="defs3802" />
<metadata
id="metadata3805">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<path
style="fill:#94bb28;fill-opacity:1;stroke-width:1.2259587"
d="M 4.7296291,5.7048034 V 6.7417316 H 6.3625149 V 5.7048034 Z m 3.1970987,0 v 1.0369282 h 1.635428 V 5.7048034 Z m 0,1.3615319 V 9.929158 c 0,0.137344 0.1248063,0.247964 0.2797758,0.247964 h 0.020344 0.2594303 v 2.774907 c 0,0.132728 0.1223883,0.2412 0.2721487,0.2412 h 2.4010024 c 0.149759,0 0.272149,-0.10847 0.272149,-0.2412 V 11.22532 l 0.0051,-0.25247 -1.040267,-3.9065147 z m -4.038976,0.00453 -1.0428083,3.9065137 0.0051,0.254723 v 1.726711 c 4.5e-6,0.13273 0.1223942,0.241202 0.2721522,0.241202 h 2.4010035 c 0.152362,0 0.2746909,-0.108471 0.2746909,-0.241198 v -2.772669 h 0.2568822 0.020347 c 0.1549659,0 0.2797778,-0.112874 0.2797778,-0.250215 V 7.0708438 Z m 2.8283005,0 v 2.662175 H 7.5630154 V 7.0708438 Z"
id="rect239-1" />
<path
id="rect4777"
d="M 7.0889837,-0.10160715 0.17796583,4.9812788 0.91238492,5.7921972 1.4027311,5.2552234 v 7.6895316 0.02769 c -2.072e-4,0.275222 0.1061456,0.530617 0.2804973,0.673602 0.1801358,0.146852 0.4049368,0.151545 0.5883574,0.01229 0.1841777,-0.138991 0.2983989,-0.401233 0.2987393,-0.685886 V 4.6246818 L 7.1197677,1.5197554 11.792346,4.6870601 v 8.3477549 c -2.08e-4,0.275221 0.106147,0.530617 0.280497,0.673602 0.180136,0.146852 0.404937,0.151547 0.588359,0.01229 0.184177,-0.138991 0.298398,-0.401233 0.298739,-0.685886 V 5.3176049 l 0.428778,0.2562714 0.611282,-0.4990267 z"
style="fill:#734a08;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.356004;stroke-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
assets/nature/info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

14
assets/nature/shelter.svg Normal file
View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" height="14" width="14" viewBox="0 0 14 14" id="svg2">
<defs id="defs3053"/>
<metadata id="metadata8">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<path id="rect4777" d="M 4.0078125 0 L 3.0078125 2 L 3.4765625 2 L 4.5234375 0 L 4.0078125 0 z M 8.0078125 0 L 7.0078125 2 L 7.4765625 2 L 8.5234375 0 L 8.0078125 0 z M 12.007812 0 L 11.007812 2 L 11.476562 2 L 12.523438 0 L 12.007812 0 z M 1 2 L 0 4 L 0.46875 4 L 1.5175781 2 L 1 2 z M 5.0078125 2 L 4.0078125 4 L 4.4765625 4 L 5.5234375 2 L 5.0078125 2 z M 9.0078125 2 L 8.0078125 4 L 8.4765625 4 L 9.5234375 2 L 9.0078125 2 z M 13.007812 2 L 12.007812 4 L 12.476562 4 L 13.523438 2 L 13.007812 2 z M 2.5 4 L 1.5 6 L 1.96875 6 L 3.0175781 4 L 2.5 4 z M 10.482422 4 L 9.4824219 6 L 9.9511719 6 L 11 4 L 10.482422 4 z M 7 5 L 0 9 L 2 9 L 3 8.5996094 L 3 13.482422 L 3 13.5 A 0.5 0.5 0 0 0 3.2402344 13.927734 A 0.5 0.5 0 0 0 3.7441406 13.935547 A 0.5 0.5 0 0 0 4 13.5 L 4 8.1992188 L 7 7 L 10 8.1992188 L 10 13.5 A 0.5 0.5 0 0 0 10.240234 13.927734 A 0.5 0.5 0 0 0 10.744141 13.935547 A 0.5 0.5 0 0 0 11 13.5 L 11 8.5996094 L 12 9 L 14 9 L 7 5 z " style="fill:#734a08;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-opacity:1"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 159 KiB

3282
assets/osm-logo-white-bg.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 156 KiB

12951
assets/streetwidths.geojson Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,167 +0,0 @@
<svg width="128" height="128" style="enable-background:new 0 0 128 128;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Layer_1">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="64" x2="64" y1="121.3333" y2="93.4158">
<stop offset="2.275410e-03" style="stop-color:#5D4037"/>
<stop offset="1" style="stop-color:#8D6E63"/>
</linearGradient>
<path d="M56.57,79.87c-0.98,0.02-1.73,0.48-1.7,1.03c0.3,5.38,1.54,31.22-1.99,36.43 c-1.49,2.2-3.69,3.82-5.55,4.9c-1.08,0.63-0.26,1.68,1.3,1.68h30.74c1.63,0,2.4-1.11,1.21-1.73c-1.97-1.02-4.19-2.62-6-5.1 c-3.32-4.54-3.2-30.92-3.14-36.53c0.01-0.57-0.84-1.03-1.86-1L56.57,79.87z" style="fill:url(#SVGID_1_);"/>
<g style="opacity:0.2;">
<path d="M67.8,83.22c-0.13,25.12,2,33.47,3.86,36c0.27,0.37,0.55,0.72,0.84,1.07H55.2 c0.24-0.3,0.46-0.61,0.68-0.92c3.41-5.04,3.44-21.75,2.75-35.92L67.8,83.22 M69.66,79.55c-0.03,0-0.05,0-0.08,0l-13.01,0.33 c-0.98,0.02-1.73,0.48-1.7,1.03c0.3,5.38,1.54,31.22-1.99,36.43c-1.49,2.2-3.69,3.82-5.55,4.9c-1.08,0.63-0.26,1.68,1.3,1.68 h30.74c1.63,0,2.4-1.11,1.21-1.73c-1.97-1.02-4.19-2.62-6-5.1c-3.32-4.54-3.2-30.92-3.14-36.53 C71.45,79.99,70.65,79.55,69.66,79.55L69.66,79.55z" style="fill:#424242;"/>
</g>
</g>
<g>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="55.2039" x2="95.8998" y1="42.6083" y2="97.3989">
<stop offset="0" style="stop-color:#9CCC65"/>
<stop offset="0.9952" style="stop-color:#689F38"/>
</linearGradient>
<path d="M56.96,100c-9.49,0-17.78-6.08-20.63-15.13c-0.2-0.63-0.78-1.05-1.43-1.05 c-0.04,0-0.08,0-0.12,0c-0.6,0.05-1.13,0.07-1.61,0.07c-11.39,0-20.66-9.59-20.66-21.38c0-7.32,3.57-14.06,9.55-18.02 c0.57-0.38,0.81-1.1,0.59-1.74c-0.76-2.18-1.14-4.46-1.14-6.77c0-11.39,9.27-20.66,20.66-20.66c1.65,0,3.31,0.2,4.93,0.6 c0.12,0.03,0.24,0.04,0.36,0.04c0.51,0,1-0.26,1.27-0.71c3.8-6.12,10.37-9.77,17.56-9.77c9.12,0,17.28,6.11,19.83,14.87 c0.19,0.65,0.78,1.08,1.44,1.08c0.09,0,0.19-0.01,0.28-0.03c1.29-0.24,2.59-0.37,3.87-0.37c11.39,0,20.66,9.27,20.66,20.66 c0,6.2-2.75,12.02-7.54,15.96c-0.33,0.27-0.53,0.68-0.55,1.11c-0.01,0.43,0.16,0.85,0.48,1.14c4.21,3.9,6.62,9.42,6.62,15.15 c0,11.39-9.27,20.66-20.66,20.66c-5.09,0-9.99-1.87-13.78-5.27c-0.28-0.25-0.63-0.38-1-0.38c-0.06,0-0.12,0-0.17,0.01 c-0.43,0.05-0.81,0.28-1.06,0.63C70.65,96.54,64.02,100,56.96,100z" style="fill:url(#SVGID_3_);"/>
<path d="M66.27,7c8.46,0,16.02,5.67,18.39,13.79c0.38,1.3,1.57,2.16,2.88,2.16c0.19,0,0.37-0.02,0.56-0.05 c1.19-0.23,2.4-0.34,3.59-0.34c10.57,0,19.16,8.6,19.16,19.16c0,5.75-2.55,11.15-7,14.8c-0.67,0.55-1.07,1.36-1.09,2.23 c-0.03,0.87,0.32,1.7,0.96,2.29c3.9,3.62,6.14,8.74,6.14,14.05c0,10.57-8.6,19.16-19.16,19.16c-4.72,0-9.26-1.74-12.78-4.89 c-0.55-0.5-1.27-0.77-2-0.77c-0.11,0-0.23,0.01-0.35,0.02c-0.85,0.1-1.62,0.56-2.11,1.26c-3.77,5.4-9.94,8.63-16.51,8.63 c-8.84,0-16.55-5.66-19.2-14.08c-0.4-1.26-1.56-2.1-2.86-2.1c-0.08,0-0.16,0-0.24,0.01c-0.56,0.04-1.05,0.07-1.49,0.07 C22.6,82.4,14,73.49,14,62.53c0-6.82,3.32-13.09,8.88-16.77c1.14-0.76,1.63-2.19,1.18-3.48C23.36,40.25,23,38.14,23,36 c0-10.57,8.6-19.16,19.16-19.16c1.53,0,3.07,0.19,4.57,0.55c0.24,0.06,0.48,0.09,0.71,0.09c1.02,0,1.99-0.52,2.55-1.42 C53.52,10.39,59.61,7,66.27,7 M66.27,4c-7.95,0-14.92,4.19-18.83,10.48c-1.69-0.41-3.46-0.64-5.28-0.64 C29.92,13.84,20,23.76,20,36c0,2.54,0.43,4.98,1.22,7.26C15.08,47.33,11,54.43,11,62.53c0,12.63,9.92,22.88,22.16,22.88 c0.58,0,1.16-0.03,1.73-0.08c2.95,9.38,11.71,16.18,22.06,16.18c7.86,0,14.79-3.92,18.97-9.91c3.92,3.51,9.1,5.65,14.78,5.65 c12.24,0,22.16-9.92,22.16-22.16c0-6.42-2.74-12.21-7.1-16.25c4.94-4.06,8.09-10.22,8.09-17.12c0-12.24-9.92-22.16-22.16-22.16 c-1.42,0-2.8,0.14-4.15,0.39C84.86,10.73,76.36,4,66.27,4L66.27,4z" style="fill:#689F38;"/>
</g>
<path d=" M22.5,44.25c0,0,7.5-5.62,19.5-5" style="fill:none;stroke:#689F38;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d=" M44.5,26.5c0,0,0.33-5,4.64-11.79" style="fill:none;stroke:#689F38;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d=" M48.16,78.85c0,0-3.84,3.21-11.73,4.8" style="fill:none;stroke:#689F38;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d=" M66.52,85.83c4.89,2.42,12.37,2.28,17.23-0.2" style="fill:none;stroke:#689F38;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d=" M79.62,61.88c5.62,1.12,12.88-3,14.87-8.2" style="fill:none;stroke:#689F38;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d=" M88.46,59.85c5.27,1.72,11.96,0.63,16.86-2.58" style="fill:none;stroke:#689F38;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
<path d=" M39.67,72.5c3.73,4.84,10.56,7.04,16.66,5.5" style="fill:none;stroke:#689F38;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;"/>
</g>
<g id="Layer_2" style="display:none;">
<g style="display:inline;">
<g style="opacity:0.6;">
<circle cx="64" cy="64" r="28" style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.2625;stroke-miterlimit:10;"/>
<line style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="84" x2="84" y1="0" y2="128"/>
<line style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="44" x2="44" y1="0" y2="128"/>
<line style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="64" x2="64" y1="0" y2="128"/>
<line style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="128" x2="0" y1="64" y2="64"/>
<line style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="128" x2="0" y1="44" y2="44"/>
<line style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="128" x2="0" y1="83.75" y2="83.75"/>
<line style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="128" x2="0" y1="128" y2="0"/>
<line style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="0" x2="128" y1="128" y2="0"/>
<g style="opacity:0.61;">
<path d="M64,4.26c32.94,0,59.74,26.8,59.74,59.74S96.94,123.74,64,123.74S4.26,96.94,4.26,64S31.06,4.26,64,4.26 M64,4 C30.86,4,4,30.86,4,64s26.86,60,60,60s60-26.86,60-60S97.14,4,64,4L64,4z"/>
</g>
<path d="M107.97,115.97H20.03 c-4.42,0-8.03-3.61-8.03-8.03V20.03c0-4.42,3.61-8.03,8.03-8.03h87.94c4.42,0,8.03,3.61,8.03,8.03v87.91 C116,112.36,112.39,115.97,107.97,115.97z" style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.2578;stroke-miterlimit:10;"/>
<path d="M100,124H28c-4.4,0-8-3.6-8-8 V12c0-4.4,3.6-8,8-8h72c4.4,0,8,3.6,8,8v104C108,120.4,104.4,124,100,124z" style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.2628;stroke-miterlimit:10;"/>
<path d="M113.77,108H14.23 C8.6,108,4,103.4,4,97.77V30.28c0-5.63,4.6-10.23,10.23-10.23h99.54c5.63,0,10.23,4.6,10.23,10.23v67.48 C124,103.4,119.4,108,113.77,108z" style="opacity:0.61;fill:none;stroke:#000000;stroke-width:0.2627;stroke-miterlimit:10;"/>
</g>
<g>
<g style="opacity:0.2;">
<defs>
<rect id="SVGID_2_" height="128" style="opacity:0.2;" width="128" x="0" y="0"/>
</defs>
<clipPath id="SVGID_4_">
<use style="overflow:visible;" xlink:href="#SVGID_2_"/>
</clipPath>
<g style="clip-path:url(#SVGID_4_);">
<g>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-28" x2="-28" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-24" x2="-24" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-20" x2="-20" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-16" x2="-16" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-12" x2="-12" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-8" x2="-8" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-4" x2="-4" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="0" x2="0" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="4" x2="4" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="8" x2="8" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="12" x2="12" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="16" x2="16" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="20" x2="20" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="24" x2="24" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="28" x2="28" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="32" x2="32" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="36" x2="36" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="40" x2="40" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="44" x2="44" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="48" x2="48" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="52" x2="52" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="56" x2="56" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="60" x2="60" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="64" x2="64" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="68" x2="68" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="72" x2="72" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="76" x2="76" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="80" x2="80" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="84" x2="84" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="88" x2="88" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="92" x2="92" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="96" x2="96" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="100" x2="100" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="104" x2="104" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="108" x2="108" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="112" x2="112" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="116" x2="116" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="120" x2="120" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="124" x2="124" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="128" x2="128" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="132" x2="132" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="136" x2="136" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="137" x2="137" y1="166.05" y2="-25.95"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="144" x2="144" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="148" x2="148" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="152" x2="152" y1="160" y2="-32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="156" x2="156" y1="160" y2="-32"/>
</g>
<g>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="-28" y2="-28"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="-24" y2="-24"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="-20" y2="-20"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="-16" y2="-16"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="-12" y2="-12"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="-8" y2="-8"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="-4" y2="-4"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="0" y2="0"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="4" y2="4"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="8" y2="8"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="12" y2="12"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="16" y2="16"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="20" y2="20"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="24" y2="24"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="28" y2="28"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="32" y2="32"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="36" y2="36"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="40" y2="40"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="44" y2="44"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="48" y2="48"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="52" y2="52"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="56" y2="56"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="60" y2="60"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="64" y2="64"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="68" y2="68"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="72" y2="72"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="76" y2="76"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="80" y2="80"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="84" y2="84"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="88" y2="88"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="92" y2="92"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="96" y2="96"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="100" y2="100"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="104" y2="104"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="108" y2="108"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="112" y2="112"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="116" y2="116"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="120" y2="120"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="124" y2="124"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="128" y2="128"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="132" y2="132"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="136" y2="136"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="140" y2="140"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="144" y2="144"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="148" y2="148"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="152" y2="152"/>
<line style="fill:none;stroke:#000000;stroke-width:0.25;stroke-miterlimit:10;" x1="-32" x2="160" y1="156" y2="156"/>
</g>
<path d="M159.75-31.75v191.5h-191.5v-191.5H159.75 M160-32H-32v192h192V-32L160-32z"/>
</g>
</g>
<g>
<rect height="128" style="opacity:0.3;fill:#F44336;" width="4" x="0" y="0"/>
<rect height="128" style="opacity:0.3;fill:#F44336;" width="4" x="124" y="0"/>
<rect height="120" style="opacity:0.3;fill:#F44336;" transform="matrix(-1.836970e-16 1 -1 -1.836970e-16 66 -62)" width="4" x="62" y="-58"/>
<rect height="120" style="opacity:0.3;fill:#F44336;" transform="matrix(-1.836970e-16 1 -1 -1.836970e-16 190 62)" width="4" x="62" y="66"/>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 37 KiB

12
clean.sh Executable file
View file

@ -0,0 +1,12 @@
#! /bin/bash
rm *.js
rm Logic/*.js
rm Logic/*.js
rm Logic/*/*.js
rm Logic/*/*/*.js
rm UI/*.js
rm UI/*/*.js
rm UI/*/*/*.js
rm Customizations/*.js
rm Customizations/*/*.js
rm Customizations/*/*/*.js

9
deploy.sh Executable file
View file

@ -0,0 +1,9 @@
#! /bin/bash
npm run build
rm -rf /home/pietervdvn/git/pietervdvn.github.io/MapComplete/*
cp -r dist/* /home/pietervdvn/git/pietervdvn.github.io/MapComplete/
cd /home/pietervdvn/git/pietervdvn.github.io/MapComplete/
git add .
git commit -m "New mapcomplete version"
git push

View file

@ -612,9 +612,9 @@ form {
padding: 0.3em; padding: 0.3em;
border-radius: 0.35em; border-radius: 0.35em;
border: solid black 1px; border: solid black 1px;
margin-left: 1em; margin-left: 0.5em;
top: 0.2em; top: 0.2em;
position: absolute; vertical-align: middle;
} }

View file

@ -28,14 +28,12 @@ import Locale from "./UI/i18n/Locale";
import { Layout } from "./Customizations/Layout"; import { Layout } from "./Customizations/Layout";
// --------------------- Read the URL parameters ----------------- // --------------------- Read the URL parameters -----------------
// @ts-ignore // @ts-ignore
if(location.href.startsWith("http://buurtnatuur.be")){ if (location.href.startsWith("http://buurtnatuur.be")) {
// Reload the https version. This is important for the 'locate me' button // Reload the https version. This is important for the 'locate me' button
window.location.replace("https://buurtnatuur.be"); window.location.replace("https://buurtnatuur.be");
} }
@ -44,10 +42,10 @@ let dryRun = false;
if (location.hostname === "localhost" || location.hostname === "127.0.0.1") { if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
// Set to true if testing and changes should NOT be saved // Set to true if testing and changes should NOT be saved
// dryRun = true; dryRun = true;
// If you have a testfile somewhere, enable this to spoof overpass // If you have a testfile somewhere, enable this to spoof overpass
// This should be hosted independantly, e.g. with `cd assets; webfsd -p 8080` + a CORS plugin to disable cors rules // This should be hosted independantly, e.g. with `cd assets; webfsd -p 8080` + a CORS plugin to disable cors rules
Overpass.testUrl = null; // "http://127.0.0.1:8080/test.json"; //Overpass.testUrl = "http://127.0.0.1:8080/streetwidths.geojson";
} }
@ -79,8 +77,6 @@ if (window.location.search) {
var kv = param.split("="); var kv = param.split("=");
paramDict[kv[0]] = kv[1]; paramDict[kv[0]] = kv[1];
} }
} }
if (paramDict.layout) { if (paramDict.layout) {
@ -88,7 +84,7 @@ if (paramDict.layout) {
} }
if (paramDict.test) { if (paramDict.test) {
dryRun = true; dryRun = paramDict.test === "true";
} }
const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout]; const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout];
@ -148,7 +144,7 @@ const bm = new Basemap("leafletDiv", locationControl, new VariableUiElement(
// ------------- Setup the layers ------------------------------- // ------------- Setup the layers -------------------------------
const controls = {};
const addButtons: { const addButtons: {
name: string, name: string,
icon: string, icon: string,
@ -178,6 +174,8 @@ for (const layer of layoutToUse.layers) {
const flayer = layer.asLayer(bm, allElements, changes, osmConnection.userDetails, selectedElement, generateInfo); const flayer = layer.asLayer(bm, allElements, changes, osmConnection.userDetails, selectedElement, generateInfo);
controls[layer.name] = flayer.isDisplayed;
const addButton = { const addButton = {
name: layer.name, name: layer.name,
icon: layer.icon, icon: layer.icon,
@ -231,7 +229,7 @@ selectedElement.addCallback((data) => {
const pendingChanges = new PendingChanges( const pendingChanges = new PendingChanges(
changes.pendingChangesES, secondsTillChangesAreSaved, changes.isSaving); changes, secondsTillChangesAreSaved,);
new UserBadge(osmConnection.userDetails, pendingChanges, bm) new UserBadge(osmConnection.userDetails, pendingChanges, bm)
.AttachTo('userbadge'); .AttachTo('userbadge');
@ -260,7 +258,9 @@ leftMessage.setData(welcomeMessage);
welcomeMessage().AttachTo("messagesbox"); welcomeMessage().AttachTo("messagesbox");
var messageBox = new MessageBoxHandler(leftMessage, () => {selectedElement.setData(undefined)}); var messageBox = new MessageBoxHandler(leftMessage, () => {
selectedElement.setData(undefined)
});
new CenterMessageBox( new CenterMessageBox(
minZoom, minZoom,

6
package-lock.json generated
View file

@ -3775,9 +3775,9 @@
} }
}, },
"lodash": { "lodash": {
"version": "4.17.15", "version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
}, },
"lodash.clone": { "lodash.clone": {
"version": "4.5.0", "version": "4.5.0",

View file

@ -4,7 +4,7 @@
"description": "A small website to edit OSM easily", "description": "A small website to edit OSM easily",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "parcel index.html land.html test.html assets/test.json assets/**/* UI/* Logic/* vendor/*", "start": "parcel index.html land.html test.html assets/test.json assets/**/* UI/* Logic/** vendor/*",
"build": "rm -rf dist/ && parcel build --public-url ./ index.html land.html assets/* assets/*/*", "build": "rm -rf dist/ && parcel build --public-url ./ index.html land.html assets/* assets/*/*",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },

13
test.ts
View file

@ -7,11 +7,14 @@ import {OsmLink} from "./Customizations/Questions/OsmLink";
import {ConfirmDialog} from "./UI/ConfirmDialog"; import {ConfirmDialog} from "./UI/ConfirmDialog";
import {Imgur} from "./Logic/Imgur"; import {Imgur} from "./Logic/Imgur";
import {VariableUiElement} from "./UI/Base/VariableUIElement"; import {VariableUiElement} from "./UI/Base/VariableUIElement";
import {CheckBox} from "./UI/Base/CheckBox";
const html = new UIEventSource<string>("Some text"); const eventSource = new UIEventSource(false);
eventSource.addCallback(console.log)
const uielement = new VariableUiElement(html); new CheckBox(eventSource)
uielement.AttachTo("maindiv") .onClick(() => {
eventSource.setData(!eventSource.data);
window.setTimeout(() => {html.setData("Different text")}, 1000) })
.AttachTo("maindiv");