Merge conflict fixed - download pdf added

This commit is contained in:
LiamSimons 2021-07-22 14:37:47 +02:00
commit 8e7114e55e
49 changed files with 1658 additions and 804 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View file

@ -0,0 +1,27 @@
import { TagsFilter } from "../../Logic/Tags/TagsFilter";
import { Translation } from "../../UI/i18n/Translation";
import Translations from "../../UI/i18n/Translations";
import FilterConfigJson from "./FilterConfigJson";
import { FromJSON } from "./FromJSON";
export default class FilterConfig {
readonly options: {
question: Translation;
osmTags: TagsFilter;
}[];
constructor(json: FilterConfigJson, context: string) {
this.options = json.options.map((option, i) => {
const question = Translations.T(
option.question,
context + ".options-[" + i + "].question"
);
const osmTags = FromJSON.Tag(
option.osmTags,
`${context}.options-[${i}].osmTags`
);
return { question: question, osmTags: osmTags };
});
}
}

View file

@ -0,0 +1,11 @@
import { AndOrTagConfigJson } from "./TagConfigJson";
export default interface FilterConfigJson {
/**
* The options for a filter
* If there are multiple options these will be a list of radio buttons
* If there is only one option this will be a checkbox
* Filtering is done based on the given osmTags that are compared to the objects in that layer.
*/
options: { question: string | any; osmTags: AndOrTagConfigJson | string }[];
}

View file

@ -18,19 +18,18 @@ import {Tag} from "../../Logic/Tags/Tag";
import BaseUIElement from "../../UI/BaseUIElement";
import { Unit } from "./Denomination";
import DeleteConfig from "./DeleteConfig";
import FilterConfig from "./FilterConfig";
export default class LayerConfig {
static WAYHANDLING_DEFAULT = 0;
static WAYHANDLING_CENTER_ONLY = 1;
static WAYHANDLING_CENTER_AND_WAY = 2;
id: string;
name: Translation
name: Translation;
description: Translation;
source: SourceConfig;
calculatedTags: [string, string][]
calculatedTags: [string, string][];
doNotDownload: boolean;
passAllFeatures: boolean;
isShown: TagRenderingConfig;
@ -39,7 +38,7 @@ export default class LayerConfig {
title?: TagRenderingConfig;
titleIcons: TagRenderingConfig[];
icon: TagRenderingConfig;
iconOverlays: { if: TagsFilter, then: TagRenderingConfig, badge: boolean }[]
iconOverlays: { if: TagsFilter; then: TagRenderingConfig; badge: boolean }[];
iconSize: TagRenderingConfig;
label: TagRenderingConfig;
rotation: TagRenderingConfig;
@ -48,20 +47,23 @@ export default class LayerConfig {
dashArray: TagRenderingConfig;
wayHandling: number;
public readonly units: Unit[];
public readonly deletion: DeleteConfig | null
public readonly deletion: DeleteConfig | null;
presets: {
title: Translation,
tags: Tag[],
description?: Translation,
title: Translation;
tags: Tag[];
description?: Translation;
}[];
tagRenderings: TagRenderingConfig[];
filters: FilterConfig[];
constructor(json: LayerConfigJson,
constructor(
json: LayerConfigJson,
units?: Unit[],
context?: string,
official: boolean = true,) {
official: boolean = true
) {
this.units = units ?? [];
context = context + "." + json.id;
const self = this;
@ -74,7 +76,10 @@ export default class LayerConfig {
}
}
this.description =Translations.T(json.description, context + ".description") ;
this.description = Translations.T(
json.description,
context + ".description"
);
let legacy = undefined;
if (json["overpassTags"] !== undefined) {
@ -83,45 +88,54 @@ export default class LayerConfig {
}
if (json.source !== undefined) {
if (legacy !== undefined) {
throw context + "Both the legacy 'layer.overpasstags' and the new 'layer.source'-field are defined"
throw (
context +
"Both the legacy 'layer.overpasstags' and the new 'layer.source'-field are defined"
);
}
let osmTags: TagsFilter = legacy;
if (json.source["osmTags"]) {
osmTags = FromJSON.Tag(json.source["osmTags"], context + "source.osmTags");
osmTags = FromJSON.Tag(
json.source["osmTags"],
context + "source.osmTags"
);
}
if (json.source["geoJsonSource"] !== undefined) {
throw context + "Use 'geoJson' instead of 'geoJsonSource'"
throw context + "Use 'geoJson' instead of 'geoJsonSource'";
}
this.source = new SourceConfig({
this.source = new SourceConfig(
{
osmTags: osmTags,
geojsonSource: json.source["geoJson"],
geojsonSourceLevel: json.source["geoJsonZoomLevel"],
overpassScript: json.source["overpassScript"],
isOsmCache: json.source["isOsmCache"]
}, this.id);
isOsmCache: json.source["isOsmCache"],
},
this.id
);
} else {
this.source = new SourceConfig({
osmTags: legacy
})
osmTags: legacy,
});
}
this.calculatedTags = undefined;
if (json.calculatedTags !== undefined) {
if (!official) {
console.warn(`Unofficial theme ${this.id} with custom javascript! This is a security risk`)
console.warn(
`Unofficial theme ${this.id} with custom javascript! This is a security risk`
);
}
this.calculatedTags = [];
for (const kv of json.calculatedTags) {
const index = kv.indexOf("=")
const index = kv.indexOf("=");
const key = kv.substring(0, index);
const code = kv.substring(index + 1);
this.calculatedTags.push([key, code])
this.calculatedTags.push([key, code]);
}
}
@ -130,13 +144,14 @@ export default class LayerConfig {
this.minzoom = json.minzoom ?? 0;
this.maxzoom = json.maxzoom ?? 1000;
this.wayHandling = json.wayHandling ?? 0;
this.presets = (json.presets ?? []).map((pr, i) =>
({
this.presets = (json.presets ?? []).map((pr, i) => ({
title: Translations.T(pr.title, `${context}.presets[${i}].title`),
tags: pr.tags.map(t => FromJSON.SimpleTag(t)),
description: Translations.T(pr.description, `${context}.presets[${i}].description`)
}))
tags: pr.tags.map((t) => FromJSON.SimpleTag(t)),
description: Translations.T(
pr.description,
`${context}.presets[${i}].description`
),
}));
/** Given a key, gets the corresponding property from the json (or the default if not found
*
@ -148,7 +163,11 @@ export default class LayerConfig {
if (deflt === undefined) {
return undefined;
}
return new TagRenderingConfig(deflt, self.source.osmTags, `${context}.${key}.default value`);
return new TagRenderingConfig(
deflt,
self.source.osmTags,
`${context}.${key}.default value`
);
}
if (typeof v === "string") {
const shared = SharedTagRenderings.SharedTagRendering.get(v);
@ -156,54 +175,80 @@ export default class LayerConfig {
return shared;
}
}
return new TagRenderingConfig(v, self.source.osmTags, `${context}.${key}`);
return new TagRenderingConfig(
v,
self.source.osmTags,
`${context}.${key}`
);
}
/**
* Converts a list of tagRenderingCOnfigJSON in to TagRenderingConfig
* A string is interpreted as a name to call
*/
function trs(tagRenderings?: (string | TagRenderingConfigJson)[], readOnly = false) {
function trs(
tagRenderings?: (string | TagRenderingConfigJson)[],
readOnly = false
) {
if (tagRenderings === undefined) {
return [];
}
return Utils.NoNull(tagRenderings.map(
(renderingJson, i) => {
return Utils.NoNull(
tagRenderings.map((renderingJson, i) => {
if (typeof renderingJson === "string") {
if (renderingJson === "questions") {
if (readOnly) {
throw `A tagrendering has a question, but asking a question does not make sense here: is it a title icon or a geojson-layer? ${context}. The offending tagrendering is ${JSON.stringify(renderingJson)}`
throw `A tagrendering has a question, but asking a question does not make sense here: is it a title icon or a geojson-layer? ${context}. The offending tagrendering is ${JSON.stringify(
renderingJson
)}`;
}
return new TagRenderingConfig("questions", undefined)
return new TagRenderingConfig("questions", undefined);
}
const shared = SharedTagRenderings.SharedTagRendering.get(renderingJson);
const shared =
SharedTagRenderings.SharedTagRendering.get(renderingJson);
if (shared !== undefined) {
return shared;
}
const keys = Array.from(SharedTagRenderings.SharedTagRendering.keys())
const keys = Array.from(
SharedTagRenderings.SharedTagRendering.keys()
);
if (Utils.runningFromConsole) {
return undefined;
}
throw `Predefined tagRendering ${renderingJson} not found in ${context}.\n Try one of ${(keys.join(", "))}\n If you intent to output this text literally, use {\"render\": <your text>} instead"}`;
throw `Predefined tagRendering ${renderingJson} not found in ${context}.\n Try one of ${keys.join(
", "
)}\n If you intent to output this text literally, use {\"render\": <your text>} instead"}`;
}
return new TagRenderingConfig(renderingJson, self.source.osmTags, `${context}.tagrendering[${i}]`);
}));
return new TagRenderingConfig(
renderingJson,
self.source.osmTags,
`${context}.tagrendering[${i}]`
);
})
);
}
this.tagRenderings = trs(json.tagRenderings, false);
this.filters = (json.filter ?? []).map((option, i) => {
return new FilterConfig(option, `${context}.filter-[${i}]`)
});
const titleIcons = [];
const defaultIcons = ["phonelink", "emaillink", "wikipedialink", "osmlink", "sharelink"];
for (const icon of (json.titleIcons ?? defaultIcons)) {
const defaultIcons = [
"phonelink",
"emaillink",
"wikipedialink",
"osmlink",
"sharelink",
];
for (const icon of json.titleIcons ?? defaultIcons) {
if (icon === "defaults") {
titleIcons.push(...defaultIcons);
} else {
@ -213,31 +258,37 @@ export default class LayerConfig {
this.titleIcons = trs(titleIcons, true);
this.title = tr("title", undefined);
this.icon = tr("icon", "");
this.iconOverlays = (json.iconOverlays ?? []).map((overlay, i) => {
let tr = new TagRenderingConfig(overlay.then, self.source.osmTags, `iconoverlays.${i}`);
if (typeof overlay.then === "string" && SharedTagRenderings.SharedIcons.get(overlay.then) !== undefined) {
let tr = new TagRenderingConfig(
overlay.then,
self.source.osmTags,
`iconoverlays.${i}`
);
if (
typeof overlay.then === "string" &&
SharedTagRenderings.SharedIcons.get(overlay.then) !== undefined
) {
tr = SharedTagRenderings.SharedIcons.get(overlay.then);
}
return {
if: FromJSON.Tag(overlay.if),
then: tr,
badge: overlay.badge ?? false
}
badge: overlay.badge ?? false,
};
});
const iconPath = this.icon.GetRenderValue({ id: "node/-1" }).txt;
if (iconPath.startsWith(Utils.assets_path)) {
const iconKey = iconPath.substr(Utils.assets_path.length);
if (Svg.All[iconKey] === undefined) {
throw "Builtin SVG asset not found: " + iconPath
throw "Builtin SVG asset not found: " + iconPath;
}
}
this.isShown = tr("isShown", "yes");
this.iconSize = tr("iconSize", "40,40,center");
this.label = tr("label", "")
this.label = tr("label", "");
this.color = tr("color", "#0000ff");
this.width = tr("width", "7");
this.rotation = tr("rotation", "0");
@ -245,42 +296,47 @@ export default class LayerConfig {
this.deletion = null;
if (json.deletion === true) {
json.deletion = {
}
json.deletion = {};
}
if (json.deletion !== undefined && json.deletion !== false) {
this.deletion = new DeleteConfig(json.deletion, `${context}.deletion`)
this.deletion = new DeleteConfig(json.deletion, `${context}.deletion`);
}
if (json["showIf"] !== undefined) {
throw "Invalid key on layerconfig " + this.id + ": showIf. Did you mean 'isShown' instead?";
throw (
"Invalid key on layerconfig " +
this.id +
": showIf. Did you mean 'isShown' instead?"
);
}
}
public CustomCodeSnippets(): string[] {
if (this.calculatedTags === undefined) {
return []
return [];
}
return this.calculatedTags.map(code => code[1]);
return this.calculatedTags.map((code) => code[1]);
}
public AddRoamingRenderings(addAll: {
tagRenderings: TagRenderingConfig[],
titleIcons: TagRenderingConfig[],
iconOverlays: { "if": TagsFilter, then: TagRenderingConfig, badge: boolean }[]
tagRenderings: TagRenderingConfig[];
titleIcons: TagRenderingConfig[];
iconOverlays: {
if: TagsFilter;
then: TagRenderingConfig;
badge: boolean;
}[];
}): LayerConfig {
let insertionPoint = this.tagRenderings.map(tr => tr.IsQuestionBoxElement()).indexOf(true)
let insertionPoint = this.tagRenderings
.map((tr) => tr.IsQuestionBoxElement())
.indexOf(true);
if (insertionPoint < 0) {
// No 'questions' defined - we just add them all to the end
insertionPoint = this.tagRenderings.length;
}
this.tagRenderings.splice(insertionPoint, 0, ...addAll.tagRenderings);
this.iconOverlays.push(...addAll.iconOverlays);
for (const icon of addAll.titleIcons) {
this.titleIcons.splice(0, 0, icon);
@ -289,40 +345,42 @@ export default class LayerConfig {
}
public GetRoamingRenderings(): {
tagRenderings: TagRenderingConfig[],
titleIcons: TagRenderingConfig[],
iconOverlays: { "if": TagsFilter, then: TagRenderingConfig, badge: boolean }[]
tagRenderings: TagRenderingConfig[];
titleIcons: TagRenderingConfig[];
iconOverlays: {
if: TagsFilter;
then: TagRenderingConfig;
badge: boolean;
}[];
} {
const tagRenderings = this.tagRenderings.filter(tr => tr.roaming);
const titleIcons = this.titleIcons.filter(tr => tr.roaming);
const iconOverlays = this.iconOverlays.filter(io => io.then.roaming)
const tagRenderings = this.tagRenderings.filter((tr) => tr.roaming);
const titleIcons = this.titleIcons.filter((tr) => tr.roaming);
const iconOverlays = this.iconOverlays.filter((io) => io.then.roaming);
return {
tagRenderings: tagRenderings,
titleIcons: titleIcons,
iconOverlays: iconOverlays
iconOverlays: iconOverlays,
};
}
}
public GenerateLeafletStyle(tags: UIEventSource<any>, clickable: boolean, widthHeight= "100%"):
{
icon:
{
html: BaseUIElement,
iconSize: [number, number],
iconAnchor: [number, number],
popupAnchor: [number, number],
iconUrl: string,
className: string
},
color: string,
weight: number,
dashArray: number[]
public GenerateLeafletStyle(
tags: UIEventSource<any>,
clickable: boolean,
widthHeight = "100%"
): {
icon: {
html: BaseUIElement;
iconSize: [number, number];
iconAnchor: [number, number];
popupAnchor: [number, number];
iconUrl: string;
className: string;
};
color: string;
weight: number;
dashArray: number[];
} {
function num(str, deflt = 40) {
const n = Number(str);
if (isNaN(n)) {
@ -341,7 +399,7 @@ export default class LayerConfig {
}
function render(tr: TagRenderingConfig, deflt?: string) {
const str = (tr?.GetRenderValue(tags.data)?.txt ?? deflt);
const str = tr?.GetRenderValue(tags.data)?.txt ?? deflt;
return Utils.SubstituteKeys(str, tags.data).replace(/{.*}/g, "");
}
@ -350,14 +408,16 @@ export default class LayerConfig {
let color = render(this.color, "#00f");
if (color.startsWith("--")) {
color = getComputedStyle(document.body).getPropertyValue("--catch-detail-color")
color = getComputedStyle(document.body).getPropertyValue(
"--catch-detail-color"
);
}
const weight = rendernum(this.width, 5);
const iconW = num(iconSize[0]);
let iconH = num(iconSize[1]);
const mode = iconSize[2]?.trim()?.toLowerCase() ?? "center"
const mode = iconSize[2]?.trim()?.toLowerCase() ?? "center";
let anchorW = iconW / 2;
let anchorH = iconH / 2;
@ -377,31 +437,35 @@ export default class LayerConfig {
const iconUrlStatic = render(this.icon);
const self = this;
const mappedHtml = tags.map(tgs => {
const mappedHtml = tags.map((tgs) => {
function genHtmlFromString(sourcePart: string): BaseUIElement {
const style = `width:100%;height:100%;transform: rotate( ${rotation} );display:block;position: absolute; top: 0; left: 0`;
let html: BaseUIElement = new FixedUiElement(`<img src="${sourcePart}" style="${style}" />`);
const match = sourcePart.match(/([a-zA-Z0-9_]*):([^;]*)/)
let html: BaseUIElement = new FixedUiElement(
`<img src="${sourcePart}" style="${style}" />`
);
const match = sourcePart.match(/([a-zA-Z0-9_]*):([^;]*)/);
if (match !== null && Svg.All[match[1] + ".svg"] !== undefined) {
html = new Combine([
(Svg.All[match[1] + ".svg"] as string)
.replace(/#000000/g, match[2])
(Svg.All[match[1] + ".svg"] as string).replace(
/#000000/g,
match[2]
),
]).SetStyle(style);
}
return html;
}
// What do you mean, 'tgs' is never read?
// It is read implicitly in the 'render' method
const iconUrl = render(self.icon);
const rotation = render(self.rotation, "0deg");
let htmlParts: BaseUIElement[] = [];
let sourceParts = Utils.NoNull(iconUrl.split(";").filter(prt => prt != ""));
let sourceParts = Utils.NoNull(
iconUrl.split(";").filter((prt) => prt != "")
);
for (const sourcePart of sourceParts) {
htmlParts.push(genHtmlFromString(sourcePart))
htmlParts.push(genHtmlFromString(sourcePart));
}
let badges = [];
@ -411,79 +475,88 @@ export default class LayerConfig {
}
if (iconOverlay.badge) {
const badgeParts: BaseUIElement[] = [];
const partDefs = iconOverlay.then.GetRenderValue(tgs).txt.split(";").filter(prt => prt != "");
const partDefs = iconOverlay.then
.GetRenderValue(tgs)
.txt.split(";")
.filter((prt) => prt != "");
for (const badgePartStr of partDefs) {
badgeParts.push(genHtmlFromString(badgePartStr))
badgeParts.push(genHtmlFromString(badgePartStr));
}
const badgeCompound = new Combine(badgeParts)
.SetStyle("display:flex;position:relative;width:100%;height:100%;");
badges.push(badgeCompound)
const badgeCompound = new Combine(badgeParts).SetStyle(
"display:flex;position:relative;width:100%;height:100%;"
);
badges.push(badgeCompound);
} else {
htmlParts.push(genHtmlFromString(
iconOverlay.then.GetRenderValue(tgs).txt));
htmlParts.push(
genHtmlFromString(iconOverlay.then.GetRenderValue(tgs).txt)
);
}
}
if (badges.length > 0) {
const badgesComponent = new Combine(badges)
.SetStyle("display:flex;height:50%;width:100%;position:absolute;top:50%;left:50%;");
htmlParts.push(badgesComponent)
const badgesComponent = new Combine(badges).SetStyle(
"display:flex;height:50%;width:100%;position:absolute;top:50%;left:50%;"
);
htmlParts.push(badgesComponent);
}
if (sourceParts.length == 0) {
iconH = 0
iconH = 0;
}
try {
const label = self.label?.GetRenderValue(tgs)?.Subs(tgs)
const label = self.label
?.GetRenderValue(tgs)
?.Subs(tgs)
?.SetClass("block text-center")
?.SetStyle("margin-top: " + (iconH + 2) + "px")
?.SetStyle("margin-top: " + (iconH + 2) + "px");
if (label !== undefined) {
htmlParts.push(new Combine([label]).SetClass("flex flex-col items-center"))
htmlParts.push(
new Combine([label]).SetClass("flex flex-col items-center")
);
}
} catch (e) {
console.error(e, tgs)
console.error(e, tgs);
}
return new Combine(htmlParts);
})
});
return {
icon:
{
icon: {
html: new VariableUiElement(mappedHtml),
iconSize: [iconW, iconH],
iconAnchor: [anchorW, anchorH],
popupAnchor: [0, 3 - anchorH],
iconUrl: iconUrlStatic,
className: clickable ? "leaflet-div-icon" : "leaflet-div-icon unclickable"
className: clickable
? "leaflet-div-icon"
: "leaflet-div-icon unclickable",
},
color: color,
weight: weight,
dashArray: dashArray
dashArray: dashArray,
};
}
public ExtractImages(): Set<string> {
const parts: Set<string>[] = []
parts.push(...this.tagRenderings?.map(tr => tr.ExtractImages(false)))
parts.push(...this.titleIcons?.map(tr => tr.ExtractImages(true)))
parts.push(this.icon?.ExtractImages(true))
parts.push(...this.iconOverlays?.map(overlay => overlay.then.ExtractImages(true)))
const parts: Set<string>[] = [];
parts.push(...this.tagRenderings?.map((tr) => tr.ExtractImages(false)));
parts.push(...this.titleIcons?.map((tr) => tr.ExtractImages(true)));
parts.push(this.icon?.ExtractImages(true));
parts.push(
...this.iconOverlays?.map((overlay) => overlay.then.ExtractImages(true))
);
for (const preset of this.presets) {
parts.push(new Set<string>(preset.description?.ExtractImages(false)))
parts.push(new Set<string>(preset.description?.ExtractImages(false)));
}
const allIcons = new Set<string>();
for (const part of parts) {
part?.forEach(allIcons.add, allIcons)
part?.forEach(allIcons.add, allIcons);
}
return allIcons;
}
}

View file

@ -1,6 +1,7 @@
import {TagRenderingConfigJson} from "./TagRenderingConfigJson";
import {AndOrTagConfigJson} from "./TagConfigJson";
import {DeleteConfigJson} from "./DeleteConfigJson";
import FilterConfigJson from "./FilterConfigJson";
/**
* Configuration for a single layer
@ -233,6 +234,12 @@ export interface LayerConfigJson {
*/
tagRenderings?: (string | TagRenderingConfigJson) [],
/**
* All the extra questions for filtering
*/
filter?: (FilterConfigJson) [],
/**
* This block defines under what circumstances the delete dialog is shown for objects of this layer.
* If set, a dialog is shown to the user to (soft) delete the point.

View file

@ -43,6 +43,7 @@ import LayerConfig from "./Customizations/JSON/LayerConfig";
import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
import { SimpleMapScreenshoter } from "leaflet-simple-map-screenshoter";
import jsPDF from "jspdf";
import FilterView from "./UI/BigComponents/FilterView";
export class InitUiElements {
static InitAll(
@ -380,6 +381,7 @@ export class InitUiElements {
const layerControlPanel = new LayerControlPanel(
State.state.layerControlIsOpened
).SetClass("block p-1 rounded-full");
const layerControlButton = new Toggle(
layerControlPanel,
new MapControlButton(Svg.layers_svg()),
@ -392,7 +394,31 @@ export class InitUiElements {
State.state.featureSwitchLayers
);
new Combine([copyrightButton, layerControl]).AttachTo("bottom-left");
const filterView = new FilterView(State.state.FilterIsOpened).SetClass(
"block p-1 rounded-full"
);
const filterMapControlButton = new MapControlButton(
new CenterFlexedElement(
Img.AsImageElement(Svg.filter, "", "width:1.25rem;height:1.25rem")
)
);
const filterButton = new Toggle(
filterView,
filterMapControlButton,
State.state.FilterIsOpened
).ToggleOnClick();
const filterControl = new Toggle(
filterButton,
"",
State.state.featureSwitchFilter
);
new Combine([copyrightButton, layerControl, filterControl]).AttachTo(
"bottom-left"
);
State.state.locationControl.addCallback(() => {
// Close the layer selection when the map is moved

306
State.ts
View file

@ -25,11 +25,9 @@ import OsmApiFeatureSource from "./Logic/FeatureSource/OsmApiFeatureSource";
*/
export default class State {
// The singleton of the global state
public static state: State;
public readonly layoutToUse = new UIEventSource<LayoutConfig>(undefined);
/**
@ -61,26 +59,33 @@ export default class State {
public osmApiFeatureSource: OsmApiFeatureSource;
public filteredLayers: UIEventSource<{
readonly isDisplayed: UIEventSource<boolean>,
public filteredLayers: UIEventSource<
{
readonly isDisplayed: UIEventSource<boolean>;
readonly layerDef: LayerConfig;
}[]> = new UIEventSource<{
readonly isDisplayed: UIEventSource<boolean>,
}[]
> = new UIEventSource<
{
readonly isDisplayed: UIEventSource<boolean>;
readonly layerDef: LayerConfig;
}[]>([])
}[]
>([]);
/**
The latest element that was selected
*/
public readonly selectedElement = new UIEventSource<any>(undefined, "Selected element")
public readonly selectedElement = new UIEventSource<any>(
undefined,
"Selected element"
);
/**
* Keeps track of relations: which way is part of which other way?
* Set by the overpass-updater; used in the metatagging
*/
public readonly knownRelations = new UIEventSource<Map<string, {role: string, relation: Relation}[]>>(undefined, "Relation memberships")
public readonly knownRelations = new UIEventSource<
Map<string, { role: string; relation: Relation }[]>
>(undefined, "Relation memberships");
public readonly featureSwitchUserbadge: UIEventSource<boolean>;
public readonly featureSwitchSearch: UIEventSource<boolean>;
@ -95,7 +100,7 @@ export default class State {
public readonly featureSwitchIsDebugging: UIEventSource<boolean>;
public readonly featureSwitchShowAllQuestions: UIEventSource<boolean>;
public readonly featureSwitchApiURL: UIEventSource<string>;
public readonly featureSwitchFilter: UIEventSource<boolean>;
/**
* The map location: currently centered lat, lon and zoom
@ -106,24 +111,56 @@ export default class State {
/* Last location where a click was registered
*/
public readonly LastClickLocation: UIEventSource<{ lat: number, lon: number }> = new UIEventSource<{ lat: number, lon: number }>(undefined)
public readonly LastClickLocation: UIEventSource<{
lat: number;
lon: number;
}> = new UIEventSource<{ lat: number; lon: number }>(undefined);
/**
* The location as delivered by the GPS
*/
public currentGPSLocation: UIEventSource<{
latlng: { lat: number, lng: number },
accuracy: number
}> = new UIEventSource<{ latlng: { lat: number, lng: number }, accuracy: number }>(undefined);
latlng: { lat: number; lng: number };
accuracy: number;
}> = new UIEventSource<{
latlng: { lat: number; lng: number };
accuracy: number;
}>(undefined);
public layoutDefinition: string;
public installedThemes: UIEventSource<{ layout: LayoutConfig; definition: string }[]>;
public installedThemes: UIEventSource<
{ layout: LayoutConfig; definition: string }[]
>;
public layerControlIsOpened: UIEventSource<boolean> =
QueryParameters.GetQueryParameter("layer-control-toggle", "false", "Whether or not the layer control is shown")
.map<boolean>((str) => str !== "false", [], b => "" + b)
QueryParameters.GetQueryParameter(
"layer-control-toggle",
"false",
"Whether or not the layer control is shown"
).map<boolean>(
(str) => str !== "false",
[],
(b) => "" + b
);
public welcomeMessageOpenedTab = QueryParameters.GetQueryParameter("tab", "0", `The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 = more themes, 4 = about mapcomplete (user must be logged in and have >${Constants.userJourney.mapCompleteHelpUnlock} changesets)`).map<number>(
str => isNaN(Number(str)) ? 0 : Number(str), [], n => "" + n
public FilterIsOpened: UIEventSource<boolean> =
QueryParameters.GetQueryParameter(
"filter-toggle",
"false",
"Whether or not the filter is shown"
).map<boolean>(
(str) => str !== "false",
[],
(b) => "" + b
);
public welcomeMessageOpenedTab = QueryParameters.GetQueryParameter(
"tab",
"0",
`The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 = more themes, 4 = about mapcomplete (user must be logged in and have >${Constants.userJourney.mapCompleteHelpUnlock} changesets)`
).map<number>(
(str) => (isNaN(Number(str)) ? 0 : Number(str)),
[],
(n) => "" + n
);
constructor(layoutToUse: LayoutConfig) {
@ -134,13 +171,26 @@ export default class State {
// -- Location control initialization
{
const zoom = State.asFloat(
QueryParameters.GetQueryParameter("z", "" + (layoutToUse?.startZoom ?? 1), "The initial/current zoom level")
.syncWith(LocalStorageSource.Get("zoom")));
const lat = State.asFloat(QueryParameters.GetQueryParameter("lat", "" + (layoutToUse?.startLat ?? 0), "The initial/current latitude")
.syncWith(LocalStorageSource.Get("lat")));
const lon = State.asFloat(QueryParameters.GetQueryParameter("lon", "" + (layoutToUse?.startLon ?? 0), "The initial/current longitude of the app")
.syncWith(LocalStorageSource.Get("lon")));
QueryParameters.GetQueryParameter(
"z",
"" + (layoutToUse?.startZoom ?? 1),
"The initial/current zoom level"
).syncWith(LocalStorageSource.Get("zoom"))
);
const lat = State.asFloat(
QueryParameters.GetQueryParameter(
"lat",
"" + (layoutToUse?.startLat ?? 0),
"The initial/current latitude"
).syncWith(LocalStorageSource.Get("lat"))
);
const lon = State.asFloat(
QueryParameters.GetQueryParameter(
"lon",
"" + (layoutToUse?.startLon ?? 0),
"The initial/current longitude of the app"
).syncWith(LocalStorageSource.Get("lon"))
);
this.locationControl = new UIEventSource<Loc>({
zoom: Utils.asFloat(zoom.data),
@ -152,99 +202,167 @@ export default class State {
lon.setData(latlonz.lon);
});
this.layoutToUse.addCallback(layoutToUse => {
this.layoutToUse.addCallback((layoutToUse) => {
const lcd = self.locationControl.data;
lcd.zoom = lcd.zoom ?? layoutToUse?.startZoom;
lcd.lat = lcd.lat ?? layoutToUse?.startLat;
lcd.lon = lcd.lon ?? layoutToUse?.startLon;
self.locationControl.ping();
});
}
// Helper function to initialize feature switches
function featSw(key: string, deflt: (layout: LayoutConfig) => boolean, documentation: string): UIEventSource<boolean> {
const queryParameterSource = QueryParameters.GetQueryParameter(key, undefined, documentation);
function featSw(
key: string,
deflt: (layout: LayoutConfig) => boolean,
documentation: string
): UIEventSource<boolean> {
const queryParameterSource = QueryParameters.GetQueryParameter(
key,
undefined,
documentation
);
// I'm so sorry about someone trying to decipher this
// It takes the current layout, extracts the default value for this query parameter. A query parameter event source is then retrieved and flattened
return UIEventSource.flatten(
self.layoutToUse.map((layout) => {
const defaultValue = deflt(layout);
const queryParam = QueryParameters.GetQueryParameter(key, "" + defaultValue, documentation)
return queryParam.map((str) => str === undefined ? defaultValue : (str !== "false"));
}), [queryParameterSource]);
const queryParam = QueryParameters.GetQueryParameter(
key,
"" + defaultValue,
documentation
);
return queryParam.map((str) =>
str === undefined ? defaultValue : str !== "false"
);
}),
[queryParameterSource]
);
}
// Feature switch initialization - not as a function as the UIEventSources are readonly
{
this.featureSwitchUserbadge = featSw(
"fs-userbadge",
(layoutToUse) => layoutToUse?.enableUserBadge ?? true,
"Disables/Enables the user information pill (userbadge) at the top left. Disabling this disables logging in and thus disables editing all together, effectively putting MapComplete into read-only mode."
);
this.featureSwitchSearch = featSw(
"fs-search",
(layoutToUse) => layoutToUse?.enableSearch ?? true,
"Disables/Enables the search bar"
);
this.featureSwitchLayers = featSw(
"fs-layers",
(layoutToUse) => layoutToUse?.enableLayers ?? true,
"Disables/Enables the layer control"
);
this.featureSwitchFilter = featSw(
"fs-filter",
(layoutToUse) => layoutToUse?.enableLayers ?? true,
"Disables/Enables the filter"
);
this.featureSwitchAddNew = featSw(
"fs-add-new",
(layoutToUse) => layoutToUse?.enableAddNewPoints ?? true,
"Disables/Enables the 'add new feature'-popup. (A theme without presets might not have it in the first place)"
);
this.featureSwitchWelcomeMessage = featSw(
"fs-welcome-message",
() => true,
"Disables/enables the help menu or welcome message"
);
this.featureSwitchIframe = featSw(
"fs-iframe",
() => false,
"Disables/Enables the iframe-popup"
);
this.featureSwitchMoreQuests = featSw(
"fs-more-quests",
(layoutToUse) => layoutToUse?.enableMoreQuests ?? true,
"Disables/Enables the 'More Quests'-tab in the welcome message"
);
this.featureSwitchShareScreen = featSw(
"fs-share-screen",
(layoutToUse) => layoutToUse?.enableShareScreen ?? true,
"Disables/Enables the 'Share-screen'-tab in the welcome message"
);
this.featureSwitchGeolocation = featSw(
"fs-geolocation",
(layoutToUse) => layoutToUse?.enableGeolocation ?? true,
"Disables/Enables the geolocation button"
);
this.featureSwitchShowAllQuestions = featSw(
"fs-all-questions",
(layoutToUse) => layoutToUse?.enableShowAllQuestions ?? false,
"Always show all questions"
);
this.featureSwitchUserbadge = featSw("fs-userbadge", (layoutToUse) => layoutToUse?.enableUserBadge ?? true,
"Disables/Enables the user information pill (userbadge) at the top left. Disabling this disables logging in and thus disables editing all together, effectively putting MapComplete into read-only mode.");
this.featureSwitchSearch = featSw("fs-search", (layoutToUse) => layoutToUse?.enableSearch ?? true,
"Disables/Enables the search bar");
this.featureSwitchLayers = featSw("fs-layers", (layoutToUse) => layoutToUse?.enableLayers ?? true,
"Disables/Enables the layer control");
this.featureSwitchAddNew = featSw("fs-add-new", (layoutToUse) => layoutToUse?.enableAddNewPoints ?? true,
"Disables/Enables the 'add new feature'-popup. (A theme without presets might not have it in the first place)");
this.featureSwitchWelcomeMessage = featSw("fs-welcome-message", () => true,
"Disables/enables the help menu or welcome message");
this.featureSwitchIframe = featSw("fs-iframe", () => false,
"Disables/Enables the iframe-popup");
this.featureSwitchMoreQuests = featSw("fs-more-quests", (layoutToUse) => layoutToUse?.enableMoreQuests ?? true,
"Disables/Enables the 'More Quests'-tab in the welcome message");
this.featureSwitchShareScreen = featSw("fs-share-screen", (layoutToUse) => layoutToUse?.enableShareScreen ?? true,
"Disables/Enables the 'Share-screen'-tab in the welcome message");
this.featureSwitchGeolocation = featSw("fs-geolocation", (layoutToUse) => layoutToUse?.enableGeolocation ?? true,
"Disables/Enables the geolocation button");
this.featureSwitchShowAllQuestions = featSw("fs-all-questions", (layoutToUse) => layoutToUse?.enableShowAllQuestions ?? false,
"Always show all questions");
this.featureSwitchIsTesting = QueryParameters.GetQueryParameter(
"test",
"false",
"If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org"
).map(
(str) => str === "true",
[],
(b) => "" + b
);
this.featureSwitchIsTesting = QueryParameters.GetQueryParameter("test", "false",
"If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org")
.map(str => str === "true", [], b => "" + b);
this.featureSwitchIsDebugging = QueryParameters.GetQueryParameter("debug","false",
"If true, shows some extra debugging help such as all the available tags on every object")
.map(str => str === "true", [], b => "" + b)
this.featureSwitchApiURL = QueryParameters.GetQueryParameter("backend","osm",
"The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test'")
this.featureSwitchIsDebugging = QueryParameters.GetQueryParameter(
"debug",
"false",
"If true, shows some extra debugging help such as all the available tags on every object"
).map(
(str) => str === "true",
[],
(b) => "" + b
);
this.featureSwitchApiURL = QueryParameters.GetQueryParameter(
"backend",
"osm",
"The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test'"
);
}
{
// Some other feature switches
const customCssQP = QueryParameters.GetQueryParameter("custom-css", "", "If specified, the custom css from the given link will be loaded additionaly");
const customCssQP = QueryParameters.GetQueryParameter(
"custom-css",
"",
"If specified, the custom css from the given link will be loaded additionaly"
);
if (customCssQP.data !== undefined && customCssQP.data !== "") {
Utils.LoadCustomCss(customCssQP.data);
}
this.backgroundLayerId = QueryParameters.GetQueryParameter("background",
this.backgroundLayerId = QueryParameters.GetQueryParameter(
"background",
layoutToUse?.defaultBackgroundId ?? "osm",
"The id of the background layer to start with")
"The id of the background layer to start with"
);
}
if (Utils.runningFromConsole) {
return;
}
this.osmConnection = new OsmConnection(
this.featureSwitchIsTesting.data,
QueryParameters.GetQueryParameter("oauth_token", undefined,
"Used to complete the login"),
QueryParameters.GetQueryParameter(
"oauth_token",
undefined,
"Used to complete the login"
),
layoutToUse?.id,
true,
// @ts-ignore
this.featureSwitchApiURL.data
);
this.allElements = new ElementStorage();
this.changes = new Changes();
this.osmApiFeatureSource = new OsmApiFeatureSource()
this.osmApiFeatureSource = new OsmApiFeatureSource();
new PendingChangesUploader(this.changes, this.selectedElement);
@ -252,47 +370,57 @@ export default class State {
this.osmConnection.GetLongPreference("identity", "mangrove")
);
this.installedThemes = new InstalledThemes(this.osmConnection).installedThemes;
this.installedThemes = new InstalledThemes(
this.osmConnection
).installedThemes;
// Important: the favourite layers are initialized _after_ the installed themes, as these might contain an installedTheme
this.favouriteLayers = LocalStorageSource.Get("favouriteLayers")
.syncWith(this.osmConnection.GetLongPreference("favouriteLayers"))
.map(
str => Utils.Dedup(str?.split(";")) ?? [],
[], layers => Utils.Dedup(layers)?.join(";")
(str) => Utils.Dedup(str?.split(";")) ?? [],
[],
(layers) => Utils.Dedup(layers)?.join(";")
);
Locale.language.syncWith(this.osmConnection.GetPreference("language"));
Locale.language.addCallback((currentLanguage) => {
Locale.language
.addCallback((currentLanguage) => {
const layoutToUse = self.layoutToUse.data;
if (layoutToUse === undefined) {
return;
}
if (this.layoutToUse.data.language.indexOf(currentLanguage) < 0) {
console.log("Resetting language to", layoutToUse.language[0], "as", currentLanguage, " is unsupported")
console.log(
"Resetting language to",
layoutToUse.language[0],
"as",
currentLanguage,
" is unsupported"
);
// The current language is not supported -> switch to a supported one
Locale.language.setData(layoutToUse.language[0]);
}
}).ping()
})
.ping();
new TitleHandler(this.layoutToUse, this.selectedElement, this.allElements);
}
private static asFloat(source: UIEventSource<string>): UIEventSource<number> {
return source.map(str => {
return source.map(
(str) => {
let parsed = parseFloat(str);
return isNaN(parsed) ? undefined : parsed;
}, [], fl => {
},
[],
(fl) => {
if (fl === undefined || isNaN(fl)) {
return undefined;
}
return ("" + fl).substr(0, 8);
})
}
);
}
}

22
Svg.ts
View file

@ -29,6 +29,11 @@ export default class Svg {
public static arrow_left_smooth_svg() { return new Img(Svg.arrow_left_smooth, true);}
public static arrow_left_smooth_ui() { return new FixedUiElement(Svg.arrow_left_smooth_img);}
public static arrow_left_thin = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"> <path d=\"M16 7H3.83L9.42 1.41L8 0L0 8L8 16L9.41 14.59L3.83 9H16V7Z\" fill=\"#007759\"/> </svg> "
public static arrow_left_thin_img = Img.AsImageElement(Svg.arrow_left_thin)
public static arrow_left_thin_svg() { return new Img(Svg.arrow_left_thin, true);}
public static arrow_left_thin_ui() { return new FixedUiElement(Svg.arrow_left_thin_img);}
public static arrow_right_smooth = " <!-- Created with Inkscape (http://www.inkscape.org/) --> <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\" width=\"100\" height=\"100\" viewBox=\"0 0 26.458333 26.458334\" version=\"1.1\" id=\"svg8\" sodipodi:docname=\"arrow-right-smooth.svg\" inkscape:version=\"0.92.4 (5da689c313, 2019-01-14)\"> <defs id=\"defs2\" /> <sodipodi:namedview id=\"base\" pagecolor=\"#ffffff\" bordercolor=\"#666666\" borderopacity=\"1.0\" inkscape:pageopacity=\"0.0\" inkscape:pageshadow=\"2\" inkscape:zoom=\"4\" inkscape:cx=\"-22.237738\" inkscape:cy=\"36.323203\" inkscape:document-units=\"px\" inkscape:current-layer=\"layer1\" showgrid=\"false\" units=\"px\" showguides=\"true\" inkscape:guide-bbox=\"true\" inkscape:window-width=\"1920\" inkscape:window-height=\"1001\" inkscape:window-x=\"0\" inkscape:window-y=\"0\" inkscape:window-maximized=\"1\"> <sodipodi:guide position=\"13.229167,23.859748\" orientation=\"1,0\" id=\"guide815\" inkscape:locked=\"false\" /> <sodipodi:guide position=\"14.944824,13.229167\" orientation=\"0,1\" id=\"guide817\" inkscape:locked=\"false\" /> </sodipodi:namedview> <metadata id=\"metadata5\"> <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> <g inkscape:label=\"Layer 1\" inkscape:groupmode=\"layer\" id=\"layer1\" transform=\"translate(0,-270.54165)\"> <path style=\"fill: none !important;stroke:#ffffff;stroke-width:3.59588718;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\" d=\"m 6.3128214,273.41335 c 0,0 13.7995296,7.53922 13.8484366,10.36091 0.04891,2.82169 -13.8484366,10.38607 -13.8484366,10.38607\" id=\"path821\" inkscape:connector-curvature=\"0\" /> </g> </svg> "
public static arrow_right_smooth_img = Img.AsImageElement(Svg.arrow_right_smooth)
public static arrow_right_smooth_svg() { return new Img(Svg.arrow_right_smooth, true);}
@ -49,6 +54,16 @@ export default class Svg {
public static camera_plus_svg() { return new Img(Svg.camera_plus, true);}
public static camera_plus_ui() { return new FixedUiElement(Svg.camera_plus_img);}
public static checkbox_empty = "<svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"> <rect x=\"1\" y=\"1\" width=\"16\" height=\"16\" rx=\"3\" stroke=\"#007759\" stroke-width=\"2\"/> </svg> "
public static checkbox_empty_img = Img.AsImageElement(Svg.checkbox_empty)
public static checkbox_empty_svg() { return new Img(Svg.checkbox_empty, true);}
public static checkbox_empty_ui() { return new FixedUiElement(Svg.checkbox_empty_img);}
public static checkbox_filled = "<svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"> <rect x=\"1\" y=\"1\" width=\"16\" height=\"16\" rx=\"3\" fill=\"#007759\" stroke=\"#007759\" stroke-width=\"2\"/> <path d=\"M3.5 8L8 13L14 5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\"/> </svg> "
public static checkbox_filled_img = Img.AsImageElement(Svg.checkbox_filled)
public static checkbox_filled_svg() { return new Img(Svg.checkbox_filled, true);}
public static checkbox_filled_ui() { return new FixedUiElement(Svg.checkbox_filled_img);}
public static checkmark = "<svg width=\"26\" height=\"18\" viewBox=\"0 0 26 18\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3 7.28571L10.8261 15L23 3\" stroke=\"black\" stroke-width=\"4\" stroke-linejoin=\"round\" style=\"fill:none !important;\"/></svg>"
public static checkmark_img = Img.AsImageElement(Svg.checkmark)
public static checkmark_svg() { return new Img(Svg.checkmark, true);}
@ -134,6 +149,11 @@ export default class Svg {
public static envelope_svg() { return new Img(Svg.envelope, true);}
public static envelope_ui() { return new FixedUiElement(Svg.envelope_img);}
public static filter = "<svg width=\"14\" height=\"16\" viewBox=\"0 0 14 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"> <path d=\"M8.71478 7.99533V15.0032C8.73645 15.138 8.7246 15.2762 8.68028 15.4051C8.63597 15.534 8.56056 15.6497 8.46103 15.7414C8.29711 15.907 8.07541 16 7.84428 16C7.61315 16 7.39145 15.907 7.22753 15.7414L5.47778 13.9627C5.38296 13.8675 5.31072 13.7513 5.26675 13.6234C5.22277 13.4954 5.2082 13.3591 5.22403 13.2245V8.00402L0.18473 1.44083C0.0426575 1.25543 -0.0214882 1.02037 0.0063802 0.78707C0.0342486 0.553773 0.151904 0.341292 0.333498 0.195845C0.487423 0.0703057 0.678576 0.00116361 0.875917 0H13.1242C13.3215 0.00116361 13.5127 0.0703057 13.6666 0.195845C13.8482 0.341292 13.9658 0.553773 13.9936 0.78707C14.0215 1.02037 13.9573 1.25543 13.8153 1.44083L8.77597 8.00402L8.71478 7.99533Z\" fill=\"white\"/> </svg> "
public static filter_img = Img.AsImageElement(Svg.filter)
public static filter_svg() { return new Img(Svg.filter, true);}
public static filter_ui() { return new FixedUiElement(Svg.filter_img);}
public static floppy = " <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"48\" height=\"48\"> <defs> <linearGradient id=\"d\"> <stop offset=\"0\"/> <stop offset=\"1\" stop-opacity=\"0\"/> </linearGradient> <linearGradient id=\"c\"> <stop offset=\"0\" stop-color=\"#858585\"/> <stop offset=\".5\" stop-color=\"#cbcbcb\"/> <stop offset=\"1\" stop-color=\"#6b6b6b\"/> </linearGradient> <linearGradient id=\"b\"> <stop offset=\"0\" stop-color=\"#fff\"/> <stop offset=\"1\" stop-color=\"#fff\" stop-opacity=\"0\"/> </linearGradient> <linearGradient id=\"a\"> <stop offset=\"0\" stop-color=\"#1e2d69\"/> <stop offset=\"1\" stop-color=\"#78a7e0\"/> </linearGradient> <linearGradient id=\"f\" x1=\"40.885\" x2=\"16.88\" y1=\"71.869\" y2=\"-.389\" gradientTransform=\"matrix(.97661 0 0 1.13979 .564 -3.271)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#a\"/> <linearGradient id=\"g\" x1=\"13.784\" x2=\"33.075\" y1=\"-.997\" y2=\"55.702\" gradientTransform=\"matrix(.98543 0 0 1.14818 .641 -2.934)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#b\"/> <linearGradient id=\"h\" x1=\"20.125\" x2=\"28.563\" y1=\"21.844\" y2=\"42.469\" gradientTransform=\"matrix(1.0677 0 0 1.12153 -1.369 -5.574)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#c\"/> <radialGradient id=\"e\" cx=\"24.313\" cy=\"41.156\" r=\"22.875\" fx=\"24.313\" fy=\"41.156\" gradientTransform=\"matrix(1 0 0 .26913 0 30.08)\" gradientUnits=\"userSpaceOnUse\" xlink:href=\"#d\"/> </defs> <path fill=\"url(#e)\" d=\"M47.188 41.156a22.875 6.156 0 1 1-45.75 0 22.875 6.156 0 1 1 45.75 0z\" opacity=\".506\" transform=\"matrix(.91803 0 0 .98122 1.68 .648)\"/> <path fill=\"url(#f)\" stroke=\"#25375f\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M4.558 3.568h38.89c.59 0 1.064.474 1.064 1.063v37.765c0 .59-.475 1.064-1.064 1.064H6.558l-3.064-3.064V4.631a1.06 1.06 0 0 1 1.064-1.063z\"/> <path fill=\"#fff\" d=\"M9 4h30v23H9z\"/> <rect width=\"30\" height=\"4\" x=\"9\" y=\"4\" fill=\"#d31c00\" rx=\".126\" ry=\".126\"/> <rect width=\"2\" height=\"2\" x=\"6\" y=\"6\" opacity=\".739\" rx=\".126\" ry=\".126\"/> <path stroke=\"#000\" d=\"M11 12.5h26m-26 5h26m-26 5h26\" opacity=\".131\"/> <path fill=\"none\" stroke=\"url(#g)\" stroke-linecap=\"round\" d=\"M4.619 4.528h38.768c.07 0 .127.056.127.126v37.648c0 .07-.057.126-.127.126H6.928l-2.435-2.391V4.654c0-.07.056-.126.126-.126z\" opacity=\".597\"/> <path fill=\"url(#h)\" stroke=\"#525252\" d=\"M14.114 28.562h19.75c.888 0 1.603.751 1.603 1.684v13.201H12.51V30.246c0-.933.715-1.684 1.603-1.684z\"/> <rect width=\"5.03\" height=\"10.066\" x=\"16.464\" y=\"30.457\" fill=\"#4967a2\" stroke=\"#525252\" rx=\".751\" ry=\".751\"/> </svg>"
public static floppy_img = Img.AsImageElement(Svg.floppy)
public static floppy_svg() { return new Img(Svg.floppy, true);}
@ -349,4 +369,4 @@ export default class Svg {
public static wikipedia_svg() { return new Img(Svg.wikipedia, true);}
public static wikipedia_ui() { return new FixedUiElement(Svg.wikipedia_img);}
public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"direction_masked.svg": Svg.direction_masked,"direction_outline.svg": Svg.direction_outline,"direction_stroke.svg": Svg.direction_stroke,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"location.svg": Svg.location,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min-zoom.svg": Svg.min_zoom,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus-zoom.svg": Svg.plus_zoom,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}
public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-left-thin.svg": Svg.arrow_left_thin,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkbox-empty.svg": Svg.checkbox_empty,"checkbox-filled.svg": Svg.checkbox_filled,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"direction_masked.svg": Svg.direction_masked,"direction_outline.svg": Svg.direction_outline,"direction_stroke.svg": Svg.direction_stroke,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"filter.svg": Svg.filter,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"location.svg": Svg.location,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min-zoom.svg": Svg.min_zoom,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus-zoom.svg": Svg.plus_zoom,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}

View file

@ -0,0 +1,89 @@
import { FixedUiElement } from "./../Base/FixedUiElement";
import { LayerConfigJson } from "./../../Customizations/JSON/LayerConfigJson";
import { UIEventSource } from "../../Logic/UIEventSource";
import { VariableUiElement } from "../Base/VariableUIElement";
import State from "../../State";
import Toggle from "../Input/Toggle";
import Combine from "../Base/Combine";
import Translations from "../i18n/Translations";
import LayerConfig from "../../Customizations/JSON/LayerConfig";
import BaseUIElement from "../BaseUIElement";
import { Translation } from "../i18n/Translation";
import ScrollableFullScreen from "../Base/ScrollableFullScreen";
import Svg from "../../Svg";
/**
* Shows the filter
*/
export default class FilterView extends ScrollableFullScreen {
constructor(isShown: UIEventSource<boolean>) {
super(FilterView.GenTitle, FilterView.Generatecontent, "filter", isShown);
}
private static GenTitle(): BaseUIElement {
return new FixedUiElement(`Filter`).SetClass(
"text-2xl break-words font-bold p-2"
);
}
private static Generatecontent(): BaseUIElement {
let filterPanel: BaseUIElement = new FixedUiElement("");
if (State.state.filteredLayers.data.length > 1) {
let activeLayers = State.state.filteredLayers;
if (activeLayers === undefined) {
throw "ActiveLayers should be defined...";
}
const checkboxes: BaseUIElement[] = [];
for (const layer of activeLayers.data) {
const iconStyle = "width:1.5rem;height:1.5rem;margin-left:1.25rem";
const icon = new Combine([Svg.checkbox_filled]).SetStyle(iconStyle);
const iconUnselected = new Combine([Svg.checkbox_empty]).SetStyle(
iconStyle
);
if (layer.layerDef.name === undefined) {
continue;
}
const style = "display:flex;align-items:center;color:#007759";
const name: Translation = Translations.WT(layer.layerDef.name)?.Clone();
const styledNameChecked = name
.Clone()
.SetStyle("font-size:large;padding-left:1.25rem");
const styledNameUnChecked = name
.Clone()
.SetStyle("font-size:large;padding-left:1.25rem");
const layerChecked = new Combine([icon, styledNameChecked]).SetStyle(
style
);
const layerNotChecked = new Combine([
iconUnselected,
styledNameUnChecked,
]).SetStyle(style);
checkboxes.push(
new Toggle(layerChecked, layerNotChecked, layer.isDisplayed)
.ToggleOnClick()
.SetStyle("margin:0.3em;")
);
}
let combinedCheckboxes = new Combine(checkboxes);
combinedCheckboxes.SetStyle("display:flex;flex-direction:column;");
filterPanel = new Combine([combinedCheckboxes]);
return filterPanel;
}
}
}

BIN
assets/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -520,11 +520,7 @@
],
"hideUnderlayingFeaturesMinPercentage": 0,
"icon": {
"render": "./assets/themes/benches/bench_poi.svg",
"mappings": []
},
"width": {
"render": "8"
"render": "circle:#FE6F32;./assets/layers/bench/bench.svg"
},
"iconSize": {
"render": "35,35,center"

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23.18 10.85"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M20.29,10.85h1.28V6.77h1.61V5.65H21.23v-1h.93V3.1h-.93V1.85h.93V0H1V1.85H2V3.1H1V4.63H2v1H0V6.77H1.61v4.08H2.89V6.77h17.4Zm-17.63-9H20.52V3.1H2.66Zm0,3.8v-1H20.52v1Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 391 B

View file

@ -0,0 +1,8 @@
[
{
"authors": [],
"path": "bench.svg",
"license": "CC0",
"sources": []
}
]

View file

@ -241,5 +241,5 @@
}
}
],
"wayHandling": 2
"wayHandling": 1
}

View file

@ -33,9 +33,6 @@
"icon": {
"render": "./assets/layers/information_board/board.svg"
},
"width": {
"render": "8"
},
"iconSize": {
"render": "40,40,center"
},

View file

@ -1,7 +1,7 @@
{
"id": "parking",
"name": {
"nl": "parking"
"nl": "Parking"
},
"minzoom": 12,
"source": {
@ -10,7 +10,8 @@
{
"or": [
"amenity=parking",
"amenity=motorcycle_parking"
"amenity=motorcycle_parking",
"amenity=bicycle_parking"
]
}
]
@ -22,23 +23,21 @@
},
"mappings": [
{
"if": {
"and": [
"name:nl~*"
]
},
"if": "amenity=parking",
"then": {
"nl": "{name:nl}"
"nl": "Auto Parking"
}
},
{
"if": {
"and": [
"name~*"
]
},
"if": "amenity=motorcycle_parking",
"then": {
"nl": "{name}"
"nl": "Motorfiets Parking"
}
},
{
"if": "amenity=bicycle_parking",
"then": {
"nl": "Fietsenstalling"
}
}
]
@ -167,13 +166,9 @@
]
}
],
"hideUnderlayingFeaturesMinPercentage": 10,
"wayHandling": 2,
"width": {
"render": "5"
},
"wayHandling": 1,
"iconSize": {
"render": "50,50,center"
"render": "36,36,center"
},
"color": {
"render": "#E1AD01"
@ -183,6 +178,7 @@
"tags": [
"amenity=parking",
"amenity=motorcycle_parking",
"amenity=bicycle_parking",
"fixme=Toegevoegd met MapComplete, geometry nog uit te tekenen"
],
"title": {

View file

@ -72,13 +72,9 @@
]
}
],
"hideUnderlayingFeaturesMinPercentage": 0,
"icon": {
"render": "circle:#e6cf39;./assets/layers/picnic_table/picnic_table.svg"
},
"width": {
"render": "8"
},
"iconSize": {
"render": "35,35,center"
},

View file

@ -38,7 +38,7 @@
"color": {
"render": "#0000ff"
},
"wayHandling": 2,
"wayHandling": 1,
"presets": [
{
"title": {

View file

@ -393,7 +393,7 @@
},
"wayHandling": 2,
"width": {
"render": "5"
"render": "3"
},
"iconSize": {
"render": "35,35,center"
@ -401,6 +401,9 @@
"color": {
"render": "#335D9F"
},
"dashArray": {
"render": "5 5"
},
"presets": [
{
"tags": [

View file

@ -51,13 +51,9 @@
"nl": "Een bezoekerscentrum biedt informatie over een specifieke attractie of bezienswaardigheid waar het is gevestigd."
},
"tagRenderings": [],
"hideUnderlayingFeaturesMinPercentage": 0,
"icon": {
"render": "./assets/layers/visitor_information_centre/information.svg"
},
"width": {
"render": "8"
},
"iconSize": {
"render": "40,40,center"
},

View file

@ -0,0 +1,8 @@
[
{
"authors": [],
"path": "watermill.svg",
"license": "CC0",
"sources": []
}
]

View file

@ -1,7 +1,7 @@
{
"id": "watermill",
"name": {
"nl": "watermolens"
"nl": "Watermolens"
},
"minzoom": 12,
"source": {
@ -160,9 +160,9 @@
}
],
"hideUnderlayingFeaturesMinPercentage": 10,
"wayHandling": 2,
"width": {
"render": "10"
"wayHandling": 1,
"icon": {
"render": "./assets/layers/watermill/watermill.svg"
},
"iconSize": {
"render": "50,50,center"

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.18 19.74"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M9.35,7.69l5.83-5.82-.6-.6L13.92.6,8.64,5.89a1.56,1.56,0,0,0-1.05-.43l-.24,0L1.87,0l-.6.6L.6,1.26,6,6.67a1.6,1.6,0,0,0-.11.39h0l-.1.48L0,13.31l.6.6.66.67,3.87-3.87L3.57,18.27H2.44v1.47H13V18.27H11.83l-1.4-6,2.88,2.88.6-.6.67-.66L9.66,9ZM8.8,18.16H6.6V15.29A1.09,1.09,0,0,1,7.69,14.2h0A1.09,1.09,0,0,1,8.8,15.29Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 537 B

View file

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 7H3.83L9.42 1.41L8 0L0 8L8 16L9.41 14.59L3.83 9H16V7Z" fill="#007759"/>
</svg>

After

Width:  |  Height:  |  Size: 188 B

View file

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="16" height="16" rx="3" stroke="#007759" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 187 B

View file

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="16" height="16" rx="3" fill="#007759" stroke="#007759" stroke-width="2"/>
<path d="M3.5 8L8 13L14 5" stroke="white" stroke-width="2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 286 B

3
assets/svg/filter.svg Normal file
View file

@ -0,0 +1,3 @@
<svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.71478 7.99533V15.0032C8.73645 15.138 8.7246 15.2762 8.68028 15.4051C8.63597 15.534 8.56056 15.6497 8.46103 15.7414C8.29711 15.907 8.07541 16 7.84428 16C7.61315 16 7.39145 15.907 7.22753 15.7414L5.47778 13.9627C5.38296 13.8675 5.31072 13.7513 5.26675 13.6234C5.22277 13.4954 5.2082 13.3591 5.22403 13.2245V8.00402L0.18473 1.44083C0.0426575 1.25543 -0.0214882 1.02037 0.0063802 0.78707C0.0342486 0.553773 0.151904 0.341292 0.333498 0.195845C0.487423 0.0703057 0.678576 0.00116361 0.875917 0H13.1242C13.3215 0.00116361 13.5127 0.0703057 13.6666 0.195845C13.8482 0.341292 13.9658 0.553773 13.9936 0.78707C14.0215 1.02037 13.9573 1.25543 13.8153 1.44083L8.77597 8.00402L8.71478 7.99533Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 813 B

View file

@ -1,36 +1,50 @@
[
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "direction_masked.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "direction_outline.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "direction_stroke.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "SocialImageForeground.svg",
"license": "CC-BY-SA",
"sources": ["https://mapcomplete.osm.be"]
"sources": [
"https://mapcomplete.osm.be"
]
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "add.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "addSmall.svg",
"license": "CC0",
"sources": []
@ -42,25 +56,33 @@
"sources": []
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "arrow-left-smooth.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "arrow-right-smooth.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "back.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Github"],
"authors": [
"Github"
],
"path": "bug.svg",
"license": "MIT",
"sources": [
@ -71,26 +93,35 @@
{
"path": "camera-plus.svg",
"license": "CC-BY-SA 3.0",
"authors": ["Dave Gandy", "Pieter Vander Vennet"],
"authors": [
"Dave Gandy",
"Pieter Vander Vennet"
],
"sources": [
"https://fontawesome.com/",
"https://commons.wikimedia.org/wiki/File:Camera_font_awesome.svg"
]
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "checkmark.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "circle.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Pieter Vander Vennet"],
"authors": [
"Pieter Vander Vennet"
],
"path": "clock.svg",
"license": "CC0",
"sources": []
@ -132,7 +163,9 @@
"sources": []
},
{
"authors": ["Dave Gandy"],
"authors": [
"Dave Gandy"
],
"path": "delete_icon.svg",
"license": "CC-BY-SA",
"sources": [
@ -164,7 +197,9 @@
"sources": []
},
{
"authors": ["The Tango Desktop Project"],
"authors": [
"The Tango Desktop Project"
],
"path": "floppy.svg",
"license": "CC0",
"sources": [
@ -185,19 +220,29 @@
"sources": []
},
{
"authors": ["Timothy Miller"],
"authors": [
"Timothy Miller"
],
"path": "home.svg",
"license": "CC-BY-SA 3.0",
"sources": ["https://commons.wikimedia.org/wiki/File:Home-icon.svg"]
"sources": [
"https://commons.wikimedia.org/wiki/File:Home-icon.svg"
]
},
{
"authors": ["Timothy Miller"],
"authors": [
"Timothy Miller"
],
"path": "home_white_bg.svg",
"license": "CC-BY-SA 3.0",
"sources": ["https://commons.wikimedia.org/wiki/File:Home-icon.svg"]
"sources": [
"https://commons.wikimedia.org/wiki/File:Home-icon.svg"
]
},
{
"authors": ["JOSM Team"],
"authors": [
"JOSM Team"
],
"path": "josm_logo.svg",
"license": "CC0",
"sources": [
@ -220,7 +265,9 @@
{
"path": "Ornament-Horiz-0.svg",
"license": "CC-BY",
"authors": ["Nightwolfdezines"],
"authors": [
"Nightwolfdezines"
],
"sources": [
"https://www.vecteezy.com/vector-art/226361-ornaments-and-flourishes"
]
@ -228,7 +275,9 @@
{
"path": "Ornament-Horiz-1.svg",
"license": "CC-BY",
"authors": ["Nightwolfdezines"],
"authors": [
"Nightwolfdezines"
],
"sources": [
"https://www.vecteezy.com/vector-art/226361-ornaments-and-flourishes"
]
@ -236,7 +285,9 @@
{
"path": "Ornament-Horiz-2.svg",
"license": "CC-BY",
"authors": ["Nightwolfdezines"],
"authors": [
"Nightwolfdezines"
],
"sources": [
"https://www.vecteezy.com/vector-art/226361-ornaments-and-flourishes"
]
@ -244,7 +295,9 @@
{
"path": "Ornament-Horiz-3.svg",
"license": "CC-BY",
"authors": ["Nightwolfdezines"],
"authors": [
"Nightwolfdezines"
],
"sources": [
"https://www.vecteezy.com/vector-art/226361-ornaments-and-flourishes"
]
@ -252,7 +305,9 @@
{
"path": "Ornament-Horiz-4.svg",
"license": "CC-BY",
"authors": ["Nightwolfdezines"],
"authors": [
"Nightwolfdezines"
],
"sources": [
"https://www.vecteezy.com/vector-art/226361-ornaments-and-flourishes"
]
@ -260,7 +315,9 @@
{
"path": "Ornament-Horiz-5.svg",
"license": "CC-BY",
"authors": ["Nightwolfdezines"],
"authors": [
"Nightwolfdezines"
],
"sources": [
"https://www.vecteezy.com/vector-art/226361-ornaments-and-flourishes"
]
@ -268,7 +325,9 @@
{
"path": "Ornament-Horiz-6.svg",
"license": "CC-BY",
"authors": ["Nightwolfdezines"],
"authors": [
"Nightwolfdezines"
],
"sources": [
"https://www.vecteezy.com/vector-art/226361-ornaments-and-flourishes"
]
@ -310,16 +369,25 @@
"sources": []
},
{
"authors": ["Pieter Vander Vennet", " OSM"],
"authors": [
"Pieter Vander Vennet",
" OSM"
],
"path": "mapcomplete_logo.svg",
"license": "Logo; CC-BY-SA",
"sources": ["https://mapcomplete.osm.be"]
"sources": [
"https://mapcomplete.osm.be"
]
},
{
"authors": ["Mapillary"],
"authors": [
"Mapillary"
],
"path": "mapillary.svg",
"license": "Logo; All rights reserved",
"sources": ["https://mapillary.com/"]
"sources": [
"https://mapillary.com/"
]
},
{
"authors": [],
@ -343,22 +411,32 @@
"authors": [],
"path": "osm-copyright.svg",
"license": "logo; all rights reserved",
"sources": ["https://www.OpenStreetMap.org"]
"sources": [
"https://www.OpenStreetMap.org"
]
},
{
"authors": ["OpenStreetMap U.S. Chapter"],
"authors": [
"OpenStreetMap U.S. Chapter"
],
"path": "osm-logo-us.svg",
"license": "Logo",
"sources": ["https://www.openstreetmap.us/"]
"sources": [
"https://www.openstreetmap.us/"
]
},
{
"authors": [],
"path": "osm-logo.svg",
"license": "logo; all rights reserved",
"sources": ["https://www.OpenStreetMap.org"]
"sources": [
"https://www.OpenStreetMap.org"
]
},
{
"authors": ["GitHub Octicons"],
"authors": [
"GitHub Octicons"
],
"path": "pencil.svg",
"license": "MIT",
"sources": [
@ -367,10 +445,14 @@
]
},
{
"authors": ["@ tyskrat"],
"authors": [
"@ tyskrat"
],
"path": "phone.svg",
"license": "CC-BY 3.0",
"sources": ["https://www.onlinewebfonts.com/icon/1059"]
"sources": [
"https://www.onlinewebfonts.com/icon/1059"
]
},
{
"authors": [],
@ -385,10 +467,14 @@
"sources": []
},
{
"authors": ["@fatih"],
"authors": [
"@fatih"
],
"path": "pop-out.svg",
"license": "CC-BY 3.0",
"sources": ["https://www.onlinewebfonts.com/icon/2151"]
"sources": [
"https://www.onlinewebfonts.com/icon/2151"
]
},
{
"authors": [],
@ -403,7 +489,9 @@
"sources": []
},
{
"authors": ["OOjs UI Team and other contributors"],
"authors": [
"OOjs UI Team and other contributors"
],
"path": "search.svg",
"license": "MIT",
"sources": [
@ -430,13 +518,19 @@
"sources": []
},
{
"authors": ["@felpgrc"],
"authors": [
"@felpgrc"
],
"path": "statistics.svg",
"license": "CC-BY 3.0",
"sources": ["https://www.onlinewebfonts.com/icon/197818"]
"sources": [
"https://www.onlinewebfonts.com/icon/197818"
]
},
{
"authors": ["MGalloway (WMF)"],
"authors": [
"MGalloway (WMF)"
],
"path": "translate.svg",
"license": "CC-BY-SA 3.0",
"sources": [
@ -450,45 +544,99 @@
"sources": []
},
{
"authors": ["Wikidata"],
"authors": [
"Wikidata"
],
"path": "wikidata.svg",
"license": "Logo; All rights reserved",
"sources": ["https://www.wikidata.org"]
"sources": [
"https://www.wikidata.org"
]
},
{
"authors": ["Wikimedia"],
"authors": [
"Wikimedia"
],
"path": "wikimedia-commons-white.svg",
"license": "Logo; All rights reserved",
"sources": ["https://commons.wikimedia.org"]
"sources": [
"https://commons.wikimedia.org"
]
},
{
"authors": ["Wikipedia"],
"authors": [
"Wikipedia"
],
"path": "wikipedia.svg",
"license": "Logo; All rights reserved",
"sources": ["https://www.wikipedia.org/"]
"sources": [
"https://www.wikipedia.org/"
]
},
{
"authors": ["Mapillary"],
"authors": [
"Mapillary"
],
"path": "mapillary_black.svg",
"license": "Logo; All rights reserved",
"sources": ["https://www.mapillary.com/"]
"sources": [
"https://www.mapillary.com/"
]
},
{
"authors": ["Hannah Declerck"],
"authors": [
"Hannah Declerck"
],
"path": "location.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Hannah Declerck"],
"authors": [
"Hannah Declerck"
],
"path": "min-zoom.svg",
"license": "CC0",
"sources": []
},
{
"authors": ["Hannah Declerck"],
"authors": [
"Hannah Declerck"
],
"path": "plus-zoom.svg",
"license": "CC0",
"sources": []
},
{
"authors": [
"Hannah Declerck"
],
"path": "filter.svg",
"license": "CC0",
"sources": []
},
{
"authors": [
"Hannah Declerck"
],
"path": "checkbox-empty.svg",
"license": "CC0",
"sources": []
},
{
"authors": [
"Hannah Declerck"
],
"path": "checkbox-filled.svg",
"license": "CC0",
"sources": []
},
{
"authors": [
"Hannah Declerck"
],
"path": "arrow-left-thin.svg",
"license": "CC0",
"sources": []
}
]

BIN
assets/themes/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-6.5 5 35 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M20.29,10.85h1.28V6.77h1.61V5.65H21.23v-1h.93V3.1h-.93V1.85h.93V0H1V1.85H2V3.1H1V4.63H2v1H0V6.77H1.61v4.08H2.89V6.77h17.4Zm-17.63-9H20.52V3.1H2.66Zm0,3.8v-1H20.52v1Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 387 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-8.5 7 40 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M22.76,7.59h0l-.14-.21-3.74-5.6h0A3.1,3.1,0,0,0,13,3.09a3.51,3.51,0,0,0,.07.66h0v.38l0-.54-.7.45v.6H11.26V4l-.7-.45,0,.54V3.75h0a3.51,3.51,0,0,0,.07-.66A3.1,3.1,0,0,0,4.7,1.78h0L1,7.38l-.14.21h0a5.3,5.3,0,1,0,9.76,3.25l0,0v-.33s0-.08,0-.12,0-.19,0-.28l0-1.66.88-.78,0-1.06h.6l0,1.06.88.78,0,1.66c0,.09,0,.18,0,.28s0,.08,0,.12v.33l0,0a5.3,5.3,0,1,0,9.76-3.25Zm-17.46,6a3.16,3.16,0,1,1,3.15-3.15A3.16,3.16,0,0,1,5.3,13.57Zm13,0a3.16,3.16,0,1,1,3.16-3.15A3.16,3.16,0,0,1,18.28,13.57Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 702 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-11 5 35 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M12.52,0H1.27A1.27,1.27,0,0,0,0,1.48L2.14,13.89A1.28,1.28,0,0,0,3.39,15h7a1.29,1.29,0,0,0,1.26-1.06L13.77,1.48A1.27,1.27,0,0,0,12.52,0ZM9.08,8.38s0,.06,0,.09a1.71,1.71,0,0,1-.09.3l0,.1a2.15,2.15,0,0,1-.14.26.41.41,0,0,1-.07.11,1.84,1.84,0,0,1-.17.22l-.11.11-.2.17-.1.07L8,9.88H8a2.17,2.17,0,0,1-1.09.26A2.13,2.13,0,0,1,4.85,8.36a2.06,2.06,0,0,1,.33-1.53C5.73,6,6.28,5.15,6.84,4.31a.15.15,0,0,1,.27,0c.55.83,1.11,1.67,1.65,2.5l.08.13a1.33,1.33,0,0,1,.09.21l0,.09a1.68,1.68,0,0,1,.09.32.24.24,0,0,1,0,.08,1.84,1.84,0,0,1,0,.33v.09A1.73,1.73,0,0,1,9.08,8.38Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 776 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-17.5 7 40 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M6.37,15H.28v-.74l.49,0a1.45,1.45,0,0,0,.41-.1.79.79,0,0,0,.43-.33,1.2,1.2,0,0,0,.13-.57V7.61A1.16,1.16,0,0,0,1.58,7a1.36,1.36,0,0,0-.39-.4,2,2,0,0,0-.54-.23A3.55,3.55,0,0,0,0,6.26V5.52l4.78-.26.14.15v7.67a1.05,1.05,0,0,0,.15.57.79.79,0,0,0,.41.35,2.85,2.85,0,0,0,.42.16,3.55,3.55,0,0,0,.47.09ZM5,1.78A1.65,1.65,0,0,1,4.41,3a1.92,1.92,0,0,1-1.33.52A2,2,0,0,1,1.73,3a1.64,1.64,0,0,1-.56-1.26A1.64,1.64,0,0,1,1.73.52,1.92,1.92,0,0,1,3.08,0,1.88,1.88,0,0,1,4.42.52,1.68,1.68,0,0,1,5,1.78Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 708 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-8.5 7 35 1"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:none;stroke:#fff;stroke-miterlimit:10;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_8" data-name="Layer 8"><path class="cls-1" d="M10.79,10.67H7.51v-.4l.26,0A.64.64,0,0,0,8,10.19.42.42,0,0,0,8.22,10a.57.57,0,0,0,.07-.31v-3a.66.66,0,0,0-.08-.32A.88.88,0,0,0,8,6.16,1.41,1.41,0,0,0,7.71,6L7.36,6v-.4l2.57-.13.07.07V9.64a.62.62,0,0,0,.08.31.51.51,0,0,0,.22.19l.23.08.26,0ZM10,3.56a.91.91,0,0,1-.31.68,1.07,1.07,0,0,1-1.44,0A.91.91,0,0,1,8,3.56a.88.88,0,0,1,.31-.67,1,1,0,0,1,1.44,0A.88.88,0,0,1,10,3.56Z"/><rect class="cls-2" x="0.5" y="0.5" width="17.14" height="12.57"/><line class="cls-2" x1="0.5" y1="13.07" x2="0.5" y2="18.79"/><line class="cls-2" x1="17.64" y1="13.07" x2="17.64" y2="18.79"/></g></g></svg>

After

Width:  |  Height:  |  Size: 833 B

View file

@ -8,5 +8,113 @@
"sources": [
"https://www.natuurpunt.be/"
]
},
{
"authors": [],
"path": "bench.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "watermill.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "information.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "trail.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "toilets.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "urinal.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "wheelchair.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "walk_wheelchair.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "information_board.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "pushchair.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "picnic_table.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "parking.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "parkingbike.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "parkingmotor.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "parkingwheels.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "nature_reserve.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "drips.svg",
"license": "CC0",
"sources": []
},
{
"authors": [],
"path": "birdhide.svg",
"license": "CC0",
"sources": []
}
]

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-12.5 8 40 1"><defs><style>.cls-1{fill:#fff}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M14.17,7.65a3.38,3.38,0,0,0,.18-1.1,3.43,3.43,0,0,0-2.84-3.38,3.44,3.44,0,0,0-6.85,0A3.44,3.44,0,0,0,1.42,6.55a3.38,3.38,0,0,0,.18,1.1,3.44,3.44,0,1,0,4,5.56,3.25,3.25,0,0,0,1,.7v5.93H9.17V14.08a3.65,3.65,0,0,0,1.21-.7,3.44,3.44,0,1,0,3.79-5.73Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 467 B

View file

@ -21,14 +21,34 @@
"version": "0",
"startLat": 51.20875,
"startLon": 3.22435,
"startZoom": 12,
"startZoom": 15,
"widenFactor": 0.05,
"socialImage": "",
"defaultBackgroundId": "CartoDB.Positron",
"layers": [
{
"builtin": [
"nature_reserve",
"trail",
"nature_reserve"
],
"override": {
"source": {
"osmTags": {
"+and": [
"operator~.*[nN]atuurpunt.*"
]
},
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"minzoom": "10",
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/nature_reserve.svg"
}
}
},
{
"builtin": [
"visitor_information_centre"
],
"override": {
@ -39,31 +59,195 @@
]
},
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 8,
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"minzoom": "10",
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/information.svg"
}
}
},
{
"builtin": [
"trail"
],
"override": {
"source": {
"osmTags": {
"+and": [
"operator~.*[nN]atuurpunt.*"
]
},
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"minzoom": "13",
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/trail.svg",
"mappings": [
{
"if": "wheelchair=yes",
"then": "circle:#FE6F32;./assets/themes/natuurpunt/walk_wheelchair.svg"
},
{
"if": "pushchair=yes",
"then": "circle:#FE6F32;./assets/themes/natuurpunt/pushchair.svg"
}
]
}
}
},
{
"builtin": [
"toilet"
],
"override": {
"minzoom": "15",
"source": {
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/toilets.svg",
"mappings": [
{
"if": "wheelchair=yes",
"then": "circle:#FE6F32;./assets/themes/natuurpunt/wheelchair.svg"
},
{
"if": "toilets:position=urinals",
"then": "circle:#FE6F32;./assets/themes/natuurpunt/urinal.svg"
}
]
}
}
},
{
"builtin": [
"birdhide"
],
"override": {
"minzoom": "15",
"source": {
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/birdhide.svg"
}
}
},
{
"builtin": [
"birdhide",
"toilet",
"drinking_water",
"picnic_table"
],
"override": {
"minzoom": "14"
"minzoom": "16",
"source": {
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/picnic_table.svg"
}
}
},
{
"builtin": [
"drinking_water"
],
"override": {
"minzoom": "16",
"source": {
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/drips.svg"
}
}
},
{
"builtin": [
"parking"
],
"override": {
"minzoom": "16",
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/parking.svg",
"mappings": [
{
"if": "amenity=bicycle_parking",
"then": "circle:#FE6F32;./assets/themes/natuurpunt/parkingbike.svg"
}
]
},
"iconOverlays": [
{
"if": "amenity=motorcycle_parking",
"then": "circle:#335D9F;./assets/themes/natuurpunt/parkingmotor.svg",
"badge": true
},
{
"if": "capacity:disabled=yes",
"then": "circle:#335D9F;./assets/themes/natuurpunt/parkingwheels.svg",
"badge": true
}
]
}
},
{
"builtin": [
"bench",
"watermill",
"parking",
"information_board"
],
"override": {
"minzoom": "17"
"minzoom": "16",
"source": {
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/information_board.svg"
}
}
},
{
"builtin": [
"bench"
],
"override": {
"minzoom": "18",
"source": {
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/bench.svg"
}
}
},
{
"builtin": [
"watermill"
],
"override": {
"minzoom": "18",
"source": {
"geoJson": "https://pietervdvn.github.io/natuurpunt_cache/natuurpunt_{layer}_{z}_{x}_{y}.geojson",
"geoJsonZoomLevel": 12,
"isOsmCache": true
},
"icon": {
"render": "circle:#FE6F32;./assets/themes/natuurpunt/watermill.svg"
}
}
}
],

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-12.5 7 35 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M11.74,3.18h0a3.82,3.82,0,0,0-1-1.65A5.2,5.2,0,0,0,8.79.41a9.55,9.55,0,0,0-3-.41H.57A.58.58,0,0,0,0,.57V15.39A.58.58,0,0,0,.57,16H3.13a.58.58,0,0,0,.58-.57v-4.9a0,0,0,0,1,0,0H5.86a9,9,0,0,0,3-.43,4.85,4.85,0,0,0,1.91-1.18,4.2,4.2,0,0,0,1-1.74,7.47,7.47,0,0,0,.28-2A6.39,6.39,0,0,0,11.74,3.18Zm-3,3h0a1.85,1.85,0,0,1-.52.87,2.38,2.38,0,0,1-1,.53,4.8,4.8,0,0,1-1.48.19h-2a.57.57,0,0,1-.57-.57v-4a.57.57,0,0,1,.57-.57h2a5.59,5.59,0,0,1,1.47.16,2.33,2.33,0,0,1,1,.49,1.71,1.71,0,0,1,.54.81,3.56,3.56,0,0,1,.14,1A3.83,3.83,0,0,1,8.72,6.18Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 757 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-11 8 36 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M9.25,2.5h0a3,3,0,0,0-.8-1.29A4,4,0,0,0,6.92.33,7.23,7.23,0,0,0,4.55,0H.45A.45.45,0,0,0,0,.45V12.12a.45.45,0,0,0,.45.45h2a.45.45,0,0,0,.45-.45V8.26a0,0,0,0,1,0,0H4.62a7,7,0,0,0,2.32-.34A3.92,3.92,0,0,0,8.45,7a3.23,3.23,0,0,0,.8-1.37A5.55,5.55,0,0,0,9.47,4,5,5,0,0,0,9.25,2.5ZM6.87,4.87h0a1.36,1.36,0,0,1-.41.68A2,2,0,0,1,5.69,6a3.84,3.84,0,0,1-1.16.15H3a.45.45,0,0,1-.45-.45V2.54A.45.45,0,0,1,3,2.09H4.51a4.7,4.7,0,0,1,1.16.13,2.22,2.22,0,0,1,.77.38,1.43,1.43,0,0,1,.42.64A2.88,2.88,0,0,1,7,4.05,3.54,3.54,0,0,1,6.87,4.87Z"/><path class="cls-1" d="M9.64,16.78a.29.29,0,0,0,.22-.12l3-3.82a.29.29,0,0,0-.47-.35l-2.85,3.7-3.61-.07,1.65-3.48,4.74-.25a.3.3,0,1,0,0-.59l-4.92.27a.3.3,0,0,0-.25.17l-1.92,4a.28.28,0,0,0,0,.28.27.27,0,0,0,.24.14l4.21.09Z"/><path class="cls-1" d="M5.46,19A2.62,2.62,0,1,1,8,16.35,2.61,2.61,0,0,1,5.46,19Zm-.08-4.65a2,2,0,1,0,2.07,2,2,2,0,0,0-2.07-2Z"/><path class="cls-1" d="M14.16,18.88a2.62,2.62,0,1,1,2.57-2.66,2.62,2.62,0,0,1-2.57,2.66Zm-.08-4.65a2,2,0,1,0,2.07,2,2,2,0,0,0-2.07-2Z"/><path class="cls-1" d="M14.12,17h.09a.31.31,0,0,0,.18-.38L12,10,10.52,9.8a.28.28,0,0,0-.32.25.29.29,0,0,0,.26.33l1.15.13,2.22,6.26a.29.29,0,0,0,.29.19Z"/><line class="cls-1" x1="9.54" y1="16.31" x2="6.79" y2="11.31"/><polygon class="cls-1" points="9.28 16.45 9.8 16.17 7.05 11.17 6.53 11.45 9.28 16.45 9.28 16.45"/><path class="cls-1" d="M8.61,11.23s0-.18-.36-.26a17.6,17.6,0,0,0-2.17,0l0,.57,2.39.05S8.74,11.4,8.61,11.23Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-23 6 60 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M9.25,2.5h0a3,3,0,0,0-.8-1.29A4,4,0,0,0,6.92.33,7.23,7.23,0,0,0,4.55,0H.45A.45.45,0,0,0,0,.45V12.12a.45.45,0,0,0,.45.45h2a.45.45,0,0,0,.45-.45V8.26a0,0,0,0,1,0,0H4.62a7,7,0,0,0,2.32-.34A3.92,3.92,0,0,0,8.45,7a3.23,3.23,0,0,0,.8-1.37A5.55,5.55,0,0,0,9.47,4,5,5,0,0,0,9.25,2.5ZM6.87,4.87h0a1.36,1.36,0,0,1-.41.68A2,2,0,0,1,5.69,6a3.84,3.84,0,0,1-1.16.15H3a.45.45,0,0,1-.45-.45V2.54A.45.45,0,0,1,3,2.09H4.51a4.7,4.7,0,0,1,1.16.13,2.22,2.22,0,0,1,.77.38,1.43,1.43,0,0,1,.42.64A2.88,2.88,0,0,1,7,4.05,3.54,3.54,0,0,1,6.87,4.87Z"/><path id="Icon_awesome-motorcycle" data-name="Icon awesome-motorcycle" class="cls-1" d="M15.37,12.93a2.38,2.38,0,0,0-.84.13L13.88,12h1.63a.47.47,0,0,0,.47-.47h0v-.63a.48.48,0,0,0-.47-.48h-.9a.48.48,0,0,0-.35.16l-.74.82-.44-.75a.5.5,0,0,0-.41-.23H11.09a.33.33,0,0,0-.32.32V11a.33.33,0,0,0,.32.32H12.4l.38.63h-3a2.22,2.22,0,0,0-2-.79H6.68a.48.48,0,0,0-.48.48h0a.48.48,0,0,0,.47.47H7.78a1,1,0,0,1,.94.49L8.5,13a2.52,2.52,0,1,0,1.7,3.14.29.29,0,0,0,0-.09h1.66a.48.48,0,0,0,.48-.47v0a3,3,0,0,1,1.1-2.47l.25.41a2.53,2.53,0,1,0,3.56.28A2.5,2.5,0,0,0,15.37,12.93ZM7.78,17a1.58,1.58,0,1,1,0-3.16l.24,0-.81,1.49a.47.47,0,0,0,.41.7h1.6A1.57,1.57,0,0,1,7.78,17Zm9.15-1.49a1.58,1.58,0,0,1-3.16-.09,1.61,1.61,0,0,1,.44-1.09l1,1.63a.32.32,0,0,0,.44.11l.27-.16a.32.32,0,0,0,.1-.44l-1-1.59a1.55,1.55,0,0,1,.31,0,1.57,1.57,0,0,1,1.58,1.57Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-24 7 60 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M7.54,11.73a1,1,0,1,1,1-1A.95.95,0,0,1,7.54,11.73Zm3.37,4.9H7.82a1,1,0,0,1-1-.86l-.16-2.89a.92.92,0,1,1,1.83-.11l.06,1h1.78a.44.44,0,0,1,.44.43.44.44,0,0,1-.44.43H8.63l0,.54H11a.56.56,0,0,1,.46.27l1.73,2.92a.56.56,0,0,1-.19.76.57.57,0,0,1-.77-.19Zm0,.86.53.89A3.58,3.58,0,1,1,6.35,14l0,.87A2.83,2.83,0,1,0,11,17.49Z"/><path class="cls-1" d="M9.25,2.5h0a3,3,0,0,0-.8-1.29A4,4,0,0,0,6.92.33,7.23,7.23,0,0,0,4.55,0H.45A.45.45,0,0,0,0,.45V12.12a.45.45,0,0,0,.45.45h2a.45.45,0,0,0,.45-.45V8.26a0,0,0,0,1,0,0H4.62a7,7,0,0,0,2.32-.34A3.92,3.92,0,0,0,8.45,7a3.23,3.23,0,0,0,.8-1.37A5.55,5.55,0,0,0,9.47,4,5,5,0,0,0,9.25,2.5ZM6.87,4.87h0a1.36,1.36,0,0,1-.41.68A2,2,0,0,1,5.69,6a3.84,3.84,0,0,1-1.16.15H3a.45.45,0,0,1-.45-.45V2.54A.45.45,0,0,1,3,2.09H4.51a4.7,4.7,0,0,1,1.16.13,2.22,2.22,0,0,1,.77.38,1.43,1.43,0,0,1,.42.64A2.88,2.88,0,0,1,7,4.05,3.54,3.54,0,0,1,6.87,4.87Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-7 5 35 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><rect class="cls-1" x="4.26" width="13.55" height="1.98"/><rect class="cls-1" y="7.4" width="22.07" height="1.98"/><polygon class="cls-1" points="4.21 12.9 2 12.9 7.79 0.57 9.58 1.41 4.21 12.9"/><polygon class="cls-1" points="17.85 12.9 12.49 1.41 14.28 0.57 20.11 12.9 17.85 12.9"/></g></g></svg>

After

Width:  |  Height:  |  Size: 477 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-7 6 35 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M8.75,3.42A1.81,1.81,0,0,1,10.57,1.6a1.93,1.93,0,0,1,1.82,1.82,1.82,1.82,0,0,1-3.64,0ZM15.48,8c.91-.26,1.26.11,1.26.11l3.18,2.49A.83.83,0,0,1,20,11.79a1,1,0,0,1-1.32.12l-2.56-2-2-1.59Zm2.6,7.13a2.23,2.23,0,1,1-2.23-2.23,2.42,2.42,0,0,1,.46.06,1.13,1.13,0,0,0,.06-.68,1.22,1.22,0,0,0-.4-.65L15.16,11,11,12.31a1.59,1.59,0,0,1-2-1L9,11.08,8.07,13.2a2.21,2.21,0,0,1,1,1.89,2.23,2.23,0,1,1-2.23-2.23,2.32,2.32,0,0,1,.46.06L8.57,10l-2-5.89L2.65,1A1.2,1.2,0,0,0,1.93.75,1.18,1.18,0,0,0,.75,1.93a1.17,1.17,0,0,0,.47,1,.39.39,0,0,1,.05.54.36.36,0,0,1-.53,0A1.91,1.91,0,0,1,0,1.93,1.93,1.93,0,0,1,3.09.39L16.48,11.05a1.94,1.94,0,0,1,.64,1A1.92,1.92,0,0,1,17,13.18,2.22,2.22,0,0,1,18.08,15.09Zm-2.23,1a1,1,0,1,0-1-1A1,1,0,0,0,15.85,16.05Zm-9,0a1,1,0,1,0-1-1A1,1,0,0,0,6.88,16.05Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 988 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-6 3 30 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M2,8.6,0,.14H1.75L3,6,4.57.14h2L8.08,6.05,9.38.14H11.1l-2,8.46H7.23L5.55,2.28,3.87,8.6Z"/><path class="cls-1" d="M17.38,5.49,19,6a3.72,3.72,0,0,1-1.27,2.05,3.61,3.61,0,0,1-2.25.68A3.64,3.64,0,0,1,12.76,7.6a4.39,4.39,0,0,1-1.09-3.15,4.61,4.61,0,0,1,1.09-3.28A3.74,3.74,0,0,1,15.63,0a3.54,3.54,0,0,1,2.52.92A3.45,3.45,0,0,1,19,2.47l-1.7.41a1.76,1.76,0,0,0-.62-1,1.82,1.82,0,0,0-1.16-.38A1.92,1.92,0,0,0,14,2.13a3.32,3.32,0,0,0-.59,2.19A3.54,3.54,0,0,0,14,6.61a1.87,1.87,0,0,0,1.5.68,1.72,1.72,0,0,0,1.17-.44A2.44,2.44,0,0,0,17.38,5.49Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 753 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 8 30 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M11.49,8h0l0-.76H10.9V7.9L8.63,7.42,6.92,4.5a.65.65,0,0,0-.27-.25,2.46,2.46,0,0,0-.89-.53C4.43,3.27,3.84,5.29,3.84,5.29A26.9,26.9,0,0,0,3.06,9.6L3,9.94A.36.36,0,0,0,3,10l-.49,2.84L.24,16c-.2.29-.48.86.14,1.16a1,1,0,0,0,.68.09,2.5,2.5,0,0,0,.81-.7L3.92,14,4,13.92l.14-.25a1.56,1.56,0,0,0,.22-.59l.23-1.39,2.2,1.52L8,16.91a.92.92,0,0,0,1.14.62.72.72,0,0,0,.2-.09.9.9,0,0,0,.41-1.05L8.39,12.25a.91.91,0,0,0-.56-.59L6.09,10.52l.19-.7.53-3.1.91,1.54a.57.57,0,0,0,.4.29l2.78.59v8.44h.17l.34-8.35a.79.79,0,0,0,.26-.08.66.66,0,0,0,.29-.4A.62.62,0,0,0,11.49,8Z"/><path class="cls-1" d="M7,3.18a1.71,1.71,0,1,0-2.33-.61A1.7,1.7,0,0,0,7,3.18Z"/><path class="cls-1" d="M2.17,10a27.71,27.71,0,0,1,1.39-6s-.15-.63-1.25-.21S.1,7.77.45,9,2.17,10,2.17,10Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 960 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10.5 9 35 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M13,6.17c-.29-2.06-1.36-3.72-3.64-3.71H4.93c-2.27,0-3.35,1.65-3.63,3.71L0,17A4.07,4.07,0,0,0,4.07,21h6.16A4.07,4.07,0,0,0,14.3,17ZM9.36,18.43H4.93A2.93,2.93,0,0,1,2,15.5l.94-7.77c.2-1.48,1-2.68,2.61-2.67H8.74c1.64,0,2.41,1.19,2.62,2.67l.93,7.77A2.93,2.93,0,0,1,9.36,18.43Z"/><rect class="cls-1" x="5.75" width="2.79" height="3.41" rx="0.64"/><circle class="cls-1" cx="6.55" cy="14.81" r="0.22"/><circle class="cls-1" cx="7.75" cy="14.81" r="0.22"/><circle class="cls-1" cx="8.35" cy="15.74" r="0.22"/><circle class="cls-1" cx="7.16" cy="15.74" r="0.22"/><circle class="cls-1" cx="5.95" cy="15.74" r="0.22"/><circle class="cls-1" cx="6.55" cy="16.66" r="0.22"/><circle class="cls-1" cx="7.74" cy="16.66" r="0.22"/></g></g></svg>

After

Width:  |  Height:  |  Size: 933 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-8 8 40 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M11.49,8h0l0-.76H10.9V7.9L8.63,7.42,6.92,4.5a.65.65,0,0,0-.27-.25,2.46,2.46,0,0,0-.89-.53C4.43,3.27,3.84,5.29,3.84,5.29A26.9,26.9,0,0,0,3.06,9.6L3,9.94A.36.36,0,0,0,3,10l-.49,2.84L.24,16c-.2.29-.48.86.14,1.16a1,1,0,0,0,.68.09,2.5,2.5,0,0,0,.81-.7L3.92,14,4,13.92l.14-.25a1.56,1.56,0,0,0,.22-.59l.23-1.39,2.2,1.52L8,16.91a.92.92,0,0,0,1.14.62.72.72,0,0,0,.2-.09.9.9,0,0,0,.41-1.05L8.39,12.25a.91.91,0,0,0-.56-.59L6.09,10.52l.19-.7.53-3.1.91,1.54a.57.57,0,0,0,.4.29l2.78.59v8.44h.17l.34-8.35a.79.79,0,0,0,.26-.08.66.66,0,0,0,.29-.4A.62.62,0,0,0,11.49,8Z"/><path class="cls-1" d="M7,3.18a1.71,1.71,0,1,0-2.33-.61A1.7,1.7,0,0,0,7,3.18Z"/><path class="cls-1" d="M2.17,10a27.71,27.71,0,0,1,1.39-6s-.15-.63-1.25-.21S.1,7.77.45,9,2.17,10,2.17,10Z"/><path class="cls-1" d="M17.57,4.27A1.41,1.41,0,1,1,19.07,3,1.41,1.41,0,0,1,17.57,4.27Zm4.49,7.56-4.55-.3a1.42,1.42,0,0,1-1.35-1.37l0-4.28a1.38,1.38,0,0,1,1.38-1.35,1.37,1.37,0,0,1,1.34,1.38V7.38l2.63.17a.64.64,0,0,1,.59.69.65.65,0,0,1-.68.59L18.9,8.66v.8l3.5.23a.84.84,0,0,1,.66.45l2.26,4.47a.82.82,0,0,1-1.46.74Zm0,1.27.7,1.37a5.29,5.29,0,1,1-7.14-7V8.77a4.14,4.14,0,0,0-1.8,3.17A4.18,4.18,0,0,0,22,13.1Z"/><polyline class="cls-1" points="20.99 9.14 20.99 17.59 21.15 17.59 21.57 7.26 20.99 7.26 20.99 7.9"/><path class="cls-1" d="M15.57,7.12a12.06,12.06,0,0,1,.11-1.77,2,2,0,0,1,.47-.75,1,1,0,0,0-.9-.09,1.65,1.65,0,0,0-1.11,1.77A1.09,1.09,0,0,0,15.57,7.12Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 8 35 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M9.35,7.69l5.83-5.82-.6-.6L13.92.6,8.64,5.89a1.56,1.56,0,0,0-1.05-.43l-.24,0L1.87,0l-.6.6L.6,1.26,6,6.67a1.6,1.6,0,0,0-.11.39h0l-.1.48L0,13.31l.6.6.66.67,3.87-3.87L3.57,18.27H2.44v1.47H13V18.27H11.83l-1.4-6,2.88,2.88.6-.6.67-.66L9.66,9ZM8.8,18.16H6.6V15.29A1.09,1.09,0,0,1,7.69,14.2h0A1.09,1.09,0,0,1,8.8,15.29Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 532 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-11.5 11 35 1"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M2.52,23.73l-1-4.07h.84L3,22.45l.75-2.79h1l.71,2.84.63-2.84h.82l-1,4.07H5l-.81-3-.81,3Z"/><path class="cls-1" d="M9.9,22.23l.79.26a1.75,1.75,0,0,1-.6,1A1.74,1.74,0,0,1,9,23.8a1.75,1.75,0,0,1-1.33-.56,2.1,2.1,0,0,1-.52-1.51,2.2,2.2,0,0,1,.52-1.57,1.78,1.78,0,0,1,1.38-.56,1.67,1.67,0,0,1,1.21.44,1.59,1.59,0,0,1,.41.74l-.81.2a.88.88,0,0,0-.3-.5A.87.87,0,0,0,9,20.3a.91.91,0,0,0-.74.32A1.65,1.65,0,0,0,8,21.67a1.69,1.69,0,0,0,.28,1.1.88.88,0,0,0,.72.32.8.8,0,0,0,.56-.2A1.22,1.22,0,0,0,9.9,22.23Z"/><path class="cls-1" d="M4.8,3.08A1.54,1.54,0,1,1,6.34,1.54,1.54,1.54,0,0,1,4.8,3.08ZM10.25,11h-5a1.54,1.54,0,0,1-1.57-1.4L3.42,4.94a1.49,1.49,0,1,1,3-.17l.1,1.61H9.37a.7.7,0,0,1,.7.7.71.71,0,0,1-.7.69H6.57l0,.88h3.85a.92.92,0,0,1,.75.44L14,13.8A.9.9,0,0,1,13.69,15a.91.91,0,0,1-1.23-.31Zm.06,1.39.86,1.44a5.78,5.78,0,1,1-8.3-7.11l.07,1.41a4.58,4.58,0,1,0,7.37,4.26Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB