Add the possibility to load a custom layout with base64-encoded jsons
This commit is contained in:
parent
31ec3a7755
commit
14930e2f93
10 changed files with 296 additions and 74 deletions
221
Customizations/JSON/CustomLayoutFromJSON.ts
Normal file
221
Customizations/JSON/CustomLayoutFromJSON.ts
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
import {TagRenderingOptions} from "../TagRenderingOptions";
|
||||||
|
import {LayerDefinition, Preset} from "../LayerDefinition";
|
||||||
|
import {Layout} from "../Layout";
|
||||||
|
import Translation from "../../UI/i18n/Translation";
|
||||||
|
import {type} from "os";
|
||||||
|
import Combine from "../../UI/Base/Combine";
|
||||||
|
import {UIElement} from "../../UI/UIElement";
|
||||||
|
import {And, Tag, TagsFilter} from "../../Logic/TagsFilter";
|
||||||
|
import FixedText from "../Questions/FixedText";
|
||||||
|
import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload";
|
||||||
|
|
||||||
|
|
||||||
|
export class CustomLayoutFromJSON {
|
||||||
|
|
||||||
|
public static exampleLayer = {
|
||||||
|
id: "bookcase",
|
||||||
|
icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgaWQ9InN2ZzExMzgyIgogICBoZWlnaHQ9IjkwMCIKICAgd2lkdGg9IjkwMCIKICAgdmVyc2lvbj0iMS4wIj4KICA8bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGExMCI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgICA8ZGM6dGl0bGU+PC9kYzp0aXRsZT4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGRlZnMKICAgICBpZD0iZGVmczExMzg0IiAvPgogIDxnCiAgICAgaWQ9ImxheWVyMSIKICAgICB0cmFuc2Zvcm09Im1hdHJpeCgwLjkwMTAzMjU4LDAsMCwwLjkwMTAzMjU4LDExMi44NDA1OCwtMS45MDYwMTc3KSI+CiAgICA8ZwogICAgICAgaWQ9ImcxMTQ3NiI+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTE0NzIiCiAgICAgICAgIHN0eWxlPSJmb250LXN0eWxlOm5vcm1hbDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zaXplOjEyMDEuOTI0OTI2NzZweDtmb250LWZhbWlseTonQml0c3RyZWFtIFZlcmEgU2Fucyc7dGV4dC1hbGlnbjpjZW50ZXI7dGV4dC1hbmNob3I6bWlkZGxlO2ZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MXB4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICAgIGQ9Ik0gNDc0LjUwODg4LDcxOC4yMjg0MSBIIDMwMy40OTU0NyB2IC0yMi4zMDEzNCBjIC0yLjRlLTQsLTM3Ljk1MTA4IDQuMzAzNTIsLTY4Ljc2MjExIDEyLjkxMTMsLTkyLjQzMzE5IDguNjA3MjgsLTIzLjY3MDMyIDIzLjYzMzUyLC00NS4yODY5NSA0MC42NTMyNCwtNjQuODQ5OTYgMTcuMDE5MTQsLTE5LjU2MjExIDQxLjk4NzM0LC0yNi4zMzI2NCAxMDEuNDU3OTMsLTc1LjYzMDg1IDMxLjY5MDk1LC0yNS44MjIwMyA1NS4yODEzLC03Ny4xNTIzIDU1LjI4MTc1LC05OC42NzE3NCAyLjIxMjMyLC01Ni45MjI0NSAtMTMuOTM5ODMsLTc5LjM0MjIgLTM0LjU2Mjg3LC05OS45NjUyNCAtMjIuNjczNTUsLTE5LjY3NzE3IC02MC42NzAyNywtMzAuMDY5OTggLTkwLjk5ODkyLC0zMC4wNjk5OCAtMjcuNzc5MjEsNi45ZS00IC02OC40NjczNSw4LjA4ODcxIC04Ny43NjY2LDI1LjM3MDQ3IC0yNS45MzgxNywxNy4yODMwOCAtNjUuMjM3NDcsNzMuNzA2MTEgLTU3LjA0Njg3LDEzMC41NDU3NyBsIC0xOTQuNTE2OTQzLDEuNzAyMjIgYyAwLC0xNTcuMjEzOTkgMjkuMzkzNjk5LC0xOTguNjk0NjUgOTkuMDA0MTEzLC0yNjMuMDMwMzIgNjcuMzk3MzksLTU0LjM3NjY0MyAxMjYuNTMxMjgsLTczLjI2ODM2NSAyNDMuODQ3NTcsLTczLjI2ODM2NSA4OS43MTc5MSwwIDE2MS44OTcyOCwxNy44MDI4MSAyMTQuMzI1NTIsNTMuNDA1ODU1IDcxLjIwNzE0LDQ4LjEyNDcyIDEyMi4zMDEwNSwxMTEuMTgzNTQgMTIyLjMwMTA1LDIzMC4xMTI4MSAtNi45ZS00LDQ0LjMyMDgxIC0xOS4xNTI1Myw5MC43ODYzOCAtNDMuMDcyNiwxMjguMzMyOTkgLTE4LjM4OTQ3LDMwLjkwOTM4IC02MC4zNzUxMSw2Ni40NTIzNiAtMTE4LjIxMjM3LDEwNC40MTYyOCAtNDIuODM2MDcsMjUuNzY4NiAtNjYuNjcxOTYsNTMuMTE5MjYgLTc3LjAzOTY0LDcyLjA5NDYgLTEwLjM2ODYzLDE4Ljk3NjAzIC0xNS41NTI3MSw0My43MjI2NyAtMTUuNTUyMjUsNzQuMjM5OTkgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGgxMTQ3NCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MztzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjQ7c3Ryb2tlLWRhc2hhcnJheTpub25lO3N0cm9rZS1kYXNob2Zmc2V0OjA7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS4xMDYzODMsLTUuNTMxOTE0OSkiCiAgICAgICAgIGQ9Im0gNDgyLjM4Mjk4LDg2OS44MDkwMiBhIDk0LjA0MjU1Nyw3My4wMjEyNzggMCAxIDEgLTE4OC4wODUxMSwwIDk0LjA0MjU1Nyw3My4wMjEyNzggMCAxIDEgMTg4LjA4NTExLDAgeiIgLz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPgo=",
|
||||||
|
title: "Bookcase",
|
||||||
|
description: "A small, public cabinet with books. Anyone can leave or take a book",
|
||||||
|
minzoom: 12,
|
||||||
|
color: "#0000ff",
|
||||||
|
overpassTags: "amenity=public_bookcase",
|
||||||
|
presets: [
|
||||||
|
{
|
||||||
|
// icon: optional. Uses the layer icon by default
|
||||||
|
// title: optional. Uses the layer title by default
|
||||||
|
// description: optional. Uses the layer description by default
|
||||||
|
// tags: optional list {k:string, v:string}[]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tagRenderings: [
|
||||||
|
{
|
||||||
|
// If this key is present, then...
|
||||||
|
key: "name",
|
||||||
|
// Use this string to render
|
||||||
|
render: "{name}",
|
||||||
|
// One of string, int, nat, float, pfloat, email, phone. Default: string
|
||||||
|
type: "string",
|
||||||
|
// If it is not known (and no mapping below matches), this question is asked; a textfield is inserted in the rendering above
|
||||||
|
question: "Wat is de naam van dit boekenruilkastje?",
|
||||||
|
// If a value is added with the textfield, this extra tag is addded. Optional field
|
||||||
|
addExtraTags: [{
|
||||||
|
"k": "fixme",
|
||||||
|
"v": "Added with mapcomplete, to be checked"
|
||||||
|
}],
|
||||||
|
// Alternatively, these tags are shown if they match - even if the key above is not there
|
||||||
|
// If unknown, these become a radio button
|
||||||
|
mappings: [
|
||||||
|
{
|
||||||
|
if: "noname=yes",
|
||||||
|
then: "Dit boekenruilkastje heeft geen naam"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
public static exampleLayout = {
|
||||||
|
name: "bookcases",
|
||||||
|
title: "Custom Open bookcases map",
|
||||||
|
description: "Welcome to a custom layout",
|
||||||
|
language: "en",
|
||||||
|
layers: [CustomLayoutFromJSON.exampleLayer],
|
||||||
|
startZoom: 12,
|
||||||
|
startLat: 0,
|
||||||
|
startLon: 0,
|
||||||
|
icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgaWQ9InN2ZzExMzgyIgogICBoZWlnaHQ9IjkwMCIKICAgd2lkdGg9IjkwMCIKICAgdmVyc2lvbj0iMS4wIj4KICA8bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGExMCI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgICA8ZGM6dGl0bGU+PC9kYzp0aXRsZT4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGRlZnMKICAgICBpZD0iZGVmczExMzg0IiAvPgogIDxnCiAgICAgaWQ9ImxheWVyMSIKICAgICB0cmFuc2Zvcm09Im1hdHJpeCgwLjkwMTAzMjU4LDAsMCwwLjkwMTAzMjU4LDExMi44NDA1OCwtMS45MDYwMTc3KSI+CiAgICA8ZwogICAgICAgaWQ9ImcxMTQ3NiI+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMTE0NzIiCiAgICAgICAgIHN0eWxlPSJmb250LXN0eWxlOm5vcm1hbDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zaXplOjEyMDEuOTI0OTI2NzZweDtmb250LWZhbWlseTonQml0c3RyZWFtIFZlcmEgU2Fucyc7dGV4dC1hbGlnbjpjZW50ZXI7dGV4dC1hbmNob3I6bWlkZGxlO2ZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MXB4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICAgIGQ9Ik0gNDc0LjUwODg4LDcxOC4yMjg0MSBIIDMwMy40OTU0NyB2IC0yMi4zMDEzNCBjIC0yLjRlLTQsLTM3Ljk1MTA4IDQuMzAzNTIsLTY4Ljc2MjExIDEyLjkxMTMsLTkyLjQzMzE5IDguNjA3MjgsLTIzLjY3MDMyIDIzLjYzMzUyLC00NS4yODY5NSA0MC42NTMyNCwtNjQuODQ5OTYgMTcuMDE5MTQsLTE5LjU2MjExIDQxLjk4NzM0LC0yNi4zMzI2NCAxMDEuNDU3OTMsLTc1LjYzMDg1IDMxLjY5MDk1LC0yNS44MjIwMyA1NS4yODEzLC03Ny4xNTIzIDU1LjI4MTc1LC05OC42NzE3NCAyLjIxMjMyLC01Ni45MjI0NSAtMTMuOTM5ODMsLTc5LjM0MjIgLTM0LjU2Mjg3LC05OS45NjUyNCAtMjIuNjczNTUsLTE5LjY3NzE3IC02MC42NzAyNywtMzAuMDY5OTggLTkwLjk5ODkyLC0zMC4wNjk5OCAtMjcuNzc5MjEsNi45ZS00IC02OC40NjczNSw4LjA4ODcxIC04Ny43NjY2LDI1LjM3MDQ3IC0yNS45MzgxNywxNy4yODMwOCAtNjUuMjM3NDcsNzMuNzA2MTEgLTU3LjA0Njg3LDEzMC41NDU3NyBsIC0xOTQuNTE2OTQzLDEuNzAyMjIgYyAwLC0xNTcuMjEzOTkgMjkuMzkzNjk5LC0xOTguNjk0NjUgOTkuMDA0MTEzLC0yNjMuMDMwMzIgNjcuMzk3MzksLTU0LjM3NjY0MyAxMjYuNTMxMjgsLTczLjI2ODM2NSAyNDMuODQ3NTcsLTczLjI2ODM2NSA4OS43MTc5MSwwIDE2MS44OTcyOCwxNy44MDI4MSAyMTQuMzI1NTIsNTMuNDA1ODU1IDcxLjIwNzE0LDQ4LjEyNDcyIDEyMi4zMDEwNSwxMTEuMTgzNTQgMTIyLjMwMTA1LDIzMC4xMTI4MSAtNi45ZS00LDQ0LjMyMDgxIC0xOS4xNTI1Myw5MC43ODYzOCAtNDMuMDcyNiwxMjguMzMyOTkgLTE4LjM4OTQ3LDMwLjkwOTM4IC02MC4zNzUxMSw2Ni40NTIzNiAtMTE4LjIxMjM3LDEwNC40MTYyOCAtNDIuODM2MDcsMjUuNzY4NiAtNjYuNjcxOTYsNTMuMTE5MjYgLTc3LjAzOTY0LDcyLjA5NDYgLTEwLjM2ODYzLDE4Ljk3NjAzIC0xNS41NTI3MSw0My43MjI2NyAtMTUuNTUyMjUsNzQuMjM5OTkgeiIgLz4KICAgICAgPHBhdGgKICAgICAgICAgaWQ9InBhdGgxMTQ3NCIKICAgICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MztzdHJva2UtbGluZWNhcDpzcXVhcmU7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjQ7c3Ryb2tlLWRhc2hhcnJheTpub25lO3N0cm9rZS1kYXNob2Zmc2V0OjA7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS4xMDYzODMsLTUuNTMxOTE0OSkiCiAgICAgICAgIGQ9Im0gNDgyLjM4Mjk4LDg2OS44MDkwMiBhIDk0LjA0MjU1Nyw3My4wMjEyNzggMCAxIDEgLTE4OC4wODUxMSwwIDk0LjA0MjU1Nyw3My4wMjEyNzggMCAxIDEgMTg4LjA4NTExLDAgeiIgLz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPgo="
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static FromQueryParam(layoutFromBase64: string): Layout {
|
||||||
|
if(layoutFromBase64 === "test"){
|
||||||
|
console.log(btoa(JSON.stringify(CustomLayoutFromJSON.exampleLayout)));
|
||||||
|
return CustomLayoutFromJSON.LayoutFromJSON(CustomLayoutFromJSON.exampleLayout);
|
||||||
|
}
|
||||||
|
const spec = JSON.parse(atob(layoutFromBase64));
|
||||||
|
return CustomLayoutFromJSON.LayoutFromJSON(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TagRenderingFromJson(json: any): TagRenderingOptions {
|
||||||
|
|
||||||
|
if (typeof (json) === "string") {
|
||||||
|
return new FixedText(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
let freeform = undefined;
|
||||||
|
if (json.key !== undefined && json.render !== undefined) {
|
||||||
|
const type = json.type ?? "text";
|
||||||
|
freeform = {
|
||||||
|
key: json.key,
|
||||||
|
template: json.render.replace("{" + json.key + "}", "$" + type + "$"),
|
||||||
|
renderTemplate: json.render,
|
||||||
|
extraTags: CustomLayoutFromJSON.TagsFromJson(json.addExtraTags),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mappings = undefined;
|
||||||
|
if (json.mappings !== undefined) {
|
||||||
|
mappings = [];
|
||||||
|
for (const mapping of json.mappings) {
|
||||||
|
mappings.push({
|
||||||
|
k: new And(CustomLayoutFromJSON.TagsFromJson(mapping.if)), txt: mapping.then
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TagRenderingOptions({
|
||||||
|
question: json.question,
|
||||||
|
freeform: freeform,
|
||||||
|
mappings: mappings
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PresetFromJson(layout: any, preset: any): Preset {
|
||||||
|
const t = CustomLayoutFromJSON.MaybeTranslation;
|
||||||
|
const tags = CustomLayoutFromJSON.TagsFromJson;
|
||||||
|
return {
|
||||||
|
icon: preset.icon ?? layout.icon,
|
||||||
|
tags: tags(preset.tags) ?? tags(layout.overpassTags),
|
||||||
|
title: t(preset.title) ?? t(layout.title),
|
||||||
|
description: t(preset.description) ?? t(layout.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StyleFromJson(layout: any, styleJson: any): ((tags) => {
|
||||||
|
color: string,
|
||||||
|
weight?: number,
|
||||||
|
icon: {
|
||||||
|
iconUrl: string,
|
||||||
|
iconSize: number[],
|
||||||
|
},
|
||||||
|
}) {
|
||||||
|
return (tags) => {
|
||||||
|
return {
|
||||||
|
color: layout.color,
|
||||||
|
weight: 10,
|
||||||
|
icon: {
|
||||||
|
iconUrl: layout.icon,
|
||||||
|
iconSize: [40, 40],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TagFromJson(json: any): Tag {
|
||||||
|
if (json === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (typeof (json) === "string") {
|
||||||
|
const kv = json.split("=");
|
||||||
|
return new Tag(kv[0].trim(), kv[1].trim());
|
||||||
|
}
|
||||||
|
return new Tag(json.k.trim(), json.v.trim())
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TagsFromJson(json: any): Tag[] {
|
||||||
|
if (json === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (typeof (json) === "string") {
|
||||||
|
return json.split(",").map(CustomLayoutFromJSON.TagFromJson);
|
||||||
|
}
|
||||||
|
return json.map(CustomLayoutFromJSON.TagFromJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LayerFromJson(json: any): LayerDefinition {
|
||||||
|
const t = CustomLayoutFromJSON.MaybeTranslation;
|
||||||
|
const tr = CustomLayoutFromJSON.TagRenderingFromJson;
|
||||||
|
return new LayerDefinition(
|
||||||
|
json.id,
|
||||||
|
{
|
||||||
|
description: t(json.description),
|
||||||
|
name: t(json.title),
|
||||||
|
icon: json.icon,
|
||||||
|
minzoom: json.minzoom,
|
||||||
|
title: tr(json.title),
|
||||||
|
presets: json.presets.map((preset) => {
|
||||||
|
return CustomLayoutFromJSON.PresetFromJson(json, preset)
|
||||||
|
}),
|
||||||
|
elementsToShow:
|
||||||
|
[new ImageCarouselWithUploadConstructor()].concat(json.tagRenderings.map(tr)),
|
||||||
|
overpassFilter: new And(CustomLayoutFromJSON.TagsFromJson(json.overpassTags)),
|
||||||
|
wayHandling: LayerDefinition.WAYHANDLING_CENTER_AND_WAY,
|
||||||
|
maxAllowedOverlapPercentage: 0,
|
||||||
|
style: CustomLayoutFromJSON.StyleFromJson(json, json.style)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static MaybeTranslation(json: any): Translation | string {
|
||||||
|
if (json === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (typeof (json) === "string") {
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
return new Translation(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LayoutFromJSON(json: any) {
|
||||||
|
const t = CustomLayoutFromJSON.MaybeTranslation;
|
||||||
|
const layout = new Layout(json.name,
|
||||||
|
[json.language],
|
||||||
|
t(json.title),
|
||||||
|
json.layers.map(CustomLayoutFromJSON.LayerFromJson),
|
||||||
|
json.startZoom,
|
||||||
|
json.startLat,
|
||||||
|
json.startLon,
|
||||||
|
new Combine(['<h3>', t(json.title), '</h3><br/>', t(json.description)])
|
||||||
|
);
|
||||||
|
layout.icon = json.icon;
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static TagRenderingOptionsFromJson(spec: any): TagRenderingOptions {
|
||||||
|
return new TagRenderingOptions(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,24 +0,0 @@
|
||||||
import {TagRenderingOptions} from "../TagRenderingOptions";
|
|
||||||
import {LayerDefinition} from "../LayerDefinition";
|
|
||||||
|
|
||||||
|
|
||||||
export class CustomizationFromJSON {
|
|
||||||
|
|
||||||
public exampleLayer = {
|
|
||||||
id: "bookcases",
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
public static LayerFromJson(spec: any) : LayerDefinition{
|
|
||||||
return new LayerDefinition(spec.id,{
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
public static TagRenderingOptionsFromJson(spec: any) : TagRenderingOptions{
|
|
||||||
return new TagRenderingOptions(spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -94,14 +94,9 @@ export class LayerDefinition {
|
||||||
static WAYHANDLING_CENTER_AND_WAY = 2;
|
static WAYHANDLING_CENTER_AND_WAY = 2;
|
||||||
|
|
||||||
constructor(id: string, options: {
|
constructor(id: string, options: {
|
||||||
name: string,
|
name: string | UIElement,
|
||||||
description: string | UIElement,
|
description: string | UIElement,
|
||||||
presets: {
|
presets: Preset[],
|
||||||
tags: Tag[],
|
|
||||||
title: string | UIElement,
|
|
||||||
description?: string | UIElement,
|
|
||||||
icon?: string
|
|
||||||
}[],
|
|
||||||
icon: string,
|
icon: string,
|
||||||
minzoom: number,
|
minzoom: number,
|
||||||
overpassFilter: TagsFilter,
|
overpassFilter: TagsFilter,
|
||||||
|
|
|
@ -55,7 +55,7 @@ export class InitUiElements {
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{header: `<img src='${layoutToUse.icon}'>`, content: welcome},
|
{header: Img.AsImageElement(layoutToUse.icon), content: welcome},
|
||||||
{header: `<img src='${'./assets/osm-logo.svg'}'>`, content: Translations.t.general.openStreetMapIntro},
|
{header: `<img src='${'./assets/osm-logo.svg'}'>`, content: Translations.t.general.openStreetMapIntro},
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
15
UI/Img.ts
15
UI/Img.ts
|
@ -1,4 +1,19 @@
|
||||||
export class Img {
|
export class Img {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the source is an svg element, it is returned as is.
|
||||||
|
* If not, the source is wrapped into a 'img'-tag
|
||||||
|
* @param source
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
static AsImageElement(source: string): string{
|
||||||
|
if(source.startsWith("<svg")){
|
||||||
|
return `<img src="data:image/svg+xml;base64,${(btoa(source))}">`;
|
||||||
|
}else{
|
||||||
|
return `<img src="${source}">`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static readonly checkmark = `<svg width="26" height="18" viewBox="0 0 26 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 7.28571L10.8261 15L23 3" stroke="black" stroke-width="4" stroke-linejoin="round"/></svg>`;
|
static readonly checkmark = `<svg width="26" height="18" viewBox="0 0 26 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 7.28571L10.8261 15L23 3" stroke="black" stroke-width="4" stroke-linejoin="round"/></svg>`;
|
||||||
static readonly no_checkmark = `<svg width="26" height="18" viewBox="0 0 26 18" fill="none" xmlns="http://www.w3.org/2000/svg"></svg>`;
|
static readonly no_checkmark = `<svg width="26" height="18" viewBox="0 0 26 18" fill="none" xmlns="http://www.w3.org/2000/svg"></svg>`;
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,14 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
xmlns="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="1.0"
|
|
||||||
width="900"
|
|
||||||
height="900"
|
|
||||||
id="svg11382"
|
id="svg11382"
|
||||||
sodipodi:docname="help.svg"
|
height="900"
|
||||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
width="900"
|
||||||
|
version="1.0">
|
||||||
<metadata
|
<metadata
|
||||||
id="metadata10">
|
id="metadata10">
|
||||||
<rdf:RDF>
|
<rdf:RDF>
|
||||||
|
@ -27,45 +21,22 @@
|
||||||
</cc:Work>
|
</cc:Work>
|
||||||
</rdf:RDF>
|
</rdf:RDF>
|
||||||
</metadata>
|
</metadata>
|
||||||
<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="namedview8"
|
|
||||||
showgrid="false"
|
|
||||||
units="px"
|
|
||||||
inkscape:zoom="0.26767309"
|
|
||||||
inkscape:cx="339.73914"
|
|
||||||
inkscape:cy="440.83624"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="svg11382" />
|
|
||||||
<defs
|
<defs
|
||||||
id="defs11384" />
|
id="defs11384" />
|
||||||
<g
|
<g
|
||||||
transform="matrix(0.90103258,0,0,0.90103258,112.84058,-1.9060177)"
|
id="layer1"
|
||||||
id="layer1">
|
transform="matrix(0.90103258,0,0,0.90103258,112.84058,-1.9060177)">
|
||||||
<g
|
<g
|
||||||
id="g11476">
|
id="g11476">
|
||||||
<path
|
<path
|
||||||
d="M 474.50888,718.22841 H 303.49547 v -22.30134 c -2.4e-4,-37.95108 4.30352,-68.76211 12.9113,-92.43319 8.60728,-23.67032 23.63352,-45.28695 40.65324,-64.84996 17.01914,-19.56211 41.98734,-26.33264 101.45793,-75.63085 31.69095,-25.82203 55.2813,-77.1523 55.28175,-98.67174 2.21232,-56.92245 -13.93983,-79.3422 -34.56287,-99.96524 -22.67355,-19.67717 -60.67027,-30.06998 -90.99892,-30.06998 -27.77921,6.9e-4 -68.46735,8.08871 -87.7666,25.37047 -25.93817,17.28308 -65.23747,73.70611 -57.04687,130.54577 l -194.516943,1.70222 c 0,-157.21399 29.393699,-198.69465 99.004113,-263.03032 67.39739,-54.376643 126.53128,-73.268365 243.84757,-73.268365 89.71791,0 161.89728,17.80281 214.32552,53.405855 71.20714,48.12472 122.30105,111.18354 122.30105,230.11281 -6.9e-4,44.32081 -19.15253,90.78638 -43.0726,128.33299 -18.38947,30.90938 -60.37511,66.45236 -118.21237,104.41628 -42.83607,25.7686 -66.67196,53.11926 -77.03964,72.0946 -10.36863,18.97603 -15.55271,43.72267 -15.55225,74.23999 z"
|
|
||||||
style="font-style:normal;font-weight:normal;font-size:1201.92492676px;font-family:'Bitstream Vera Sans';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
id="path11472"
|
id="path11472"
|
||||||
inkscape:connector-curvature="0" />
|
style="font-style:normal;font-weight:normal;font-size:1201.92492676px;font-family:'Bitstream Vera Sans';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 474.50888,718.22841 H 303.49547 v -22.30134 c -2.4e-4,-37.95108 4.30352,-68.76211 12.9113,-92.43319 8.60728,-23.67032 23.63352,-45.28695 40.65324,-64.84996 17.01914,-19.56211 41.98734,-26.33264 101.45793,-75.63085 31.69095,-25.82203 55.2813,-77.1523 55.28175,-98.67174 2.21232,-56.92245 -13.93983,-79.3422 -34.56287,-99.96524 -22.67355,-19.67717 -60.67027,-30.06998 -90.99892,-30.06998 -27.77921,6.9e-4 -68.46735,8.08871 -87.7666,25.37047 -25.93817,17.28308 -65.23747,73.70611 -57.04687,130.54577 l -194.516943,1.70222 c 0,-157.21399 29.393699,-198.69465 99.004113,-263.03032 67.39739,-54.376643 126.53128,-73.268365 243.84757,-73.268365 89.71791,0 161.89728,17.80281 214.32552,53.405855 71.20714,48.12472 122.30105,111.18354 122.30105,230.11281 -6.9e-4,44.32081 -19.15253,90.78638 -43.0726,128.33299 -18.38947,30.90938 -60.37511,66.45236 -118.21237,104.41628 -42.83607,25.7686 -66.67196,53.11926 -77.03964,72.0946 -10.36863,18.97603 -15.55271,43.72267 -15.55225,74.23999 z" />
|
||||||
<path
|
<path
|
||||||
d="m 482.38298,869.80902 a 94.042557,73.021278 0 1 1 -188.08511,0 94.042557,73.021278 0 1 1 188.08511,0 z"
|
|
||||||
transform="translate(1.106383,-5.5319149)"
|
|
||||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
id="path11474"
|
id="path11474"
|
||||||
inkscape:connector-curvature="0" />
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
transform="translate(1.106383,-5.5319149)"
|
||||||
|
d="m 482.38298,869.80902 a 94.042557,73.021278 0 1 1 -188.08511,0 94.042557,73.021278 0 1 1 188.08511,0 z" />
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.5 KiB |
2
clean.sh
2
clean.sh
|
@ -16,7 +16,7 @@ rm q*.html
|
||||||
rm assets/generated/*
|
rm assets/generated/*
|
||||||
|
|
||||||
for f in ./*.html; do
|
for f in ./*.html; do
|
||||||
if [[ "$f" == "./index.html" ]] || [[ "$f" == "./land.html" ]] || [[ "$f" == "./test.html" ]]
|
if [[ "$f" == "./index.html" ]] || [[ "$f" == "./land.html" ]] || [[ "$f" == "./test.html" ]] || [[ "$f" == "./preferences.html" ]] || [[ "$f" == "./customGenerator.html" ]]
|
||||||
then
|
then
|
||||||
echo "Not removing $f"
|
echo "Not removing $f"
|
||||||
else
|
else
|
||||||
|
|
|
@ -462,6 +462,12 @@ form {
|
||||||
margin: 0 10px 0 18px;
|
margin: 0 10px 0 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#filter__selection ul svg {
|
||||||
|
width: 20px;
|
||||||
|
height: auto;
|
||||||
|
margin: 0 10px 0 18px;
|
||||||
|
}
|
||||||
|
|
||||||
.filter__label {
|
.filter__label {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
transform: translateY(75px);
|
transform: translateY(75px);
|
||||||
|
@ -1149,6 +1155,7 @@ form {
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.tab-content {
|
.tab-content {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
z-index: 5002;
|
z-index: 5002;
|
||||||
|
|
14
index.ts
14
index.ts
|
@ -18,6 +18,7 @@ import {TagRenderingOptions} from "./Customizations/TagRenderingOptions";
|
||||||
import {TagRendering} from "./Customizations/TagRendering";
|
import {TagRendering} from "./Customizations/TagRendering";
|
||||||
import {Img} from "./UI/Img";
|
import {Img} from "./UI/Img";
|
||||||
import Combine from "./UI/Base/Combine";
|
import Combine from "./UI/Base/Combine";
|
||||||
|
import {CustomLayoutFromJSON} from "./Customizations/JSON/CustomLayoutFromJSON";
|
||||||
|
|
||||||
|
|
||||||
// --------------------- Special actions based on the parameters -----------------
|
// --------------------- Special actions based on the parameters -----------------
|
||||||
|
@ -41,6 +42,7 @@ if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
|
||||||
// ----------------- SELECT THE RIGHT QUESTSET -----------------
|
// ----------------- SELECT THE RIGHT QUESTSET -----------------
|
||||||
|
|
||||||
let defaultLayout = "bookcases"
|
let defaultLayout = "bookcases"
|
||||||
|
let hash = window.location.hash;
|
||||||
|
|
||||||
const path = window.location.pathname.split("/").slice(-1)[0];
|
const path = window.location.pathname.split("/").slice(-1)[0];
|
||||||
if (path !== "index.html") {
|
if (path !== "index.html") {
|
||||||
|
@ -64,7 +66,15 @@ for (const k in AllKnownLayouts.allSets) {
|
||||||
|
|
||||||
defaultLayout = QueryParameters.GetQueryParameter("layout", defaultLayout).data;
|
defaultLayout = QueryParameters.GetQueryParameter("layout", defaultLayout).data;
|
||||||
|
|
||||||
const layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout] ?? AllKnownLayouts["all"];
|
let layoutToUse: Layout = AllKnownLayouts.allSets[defaultLayout] ?? AllKnownLayouts["all"];
|
||||||
|
|
||||||
|
|
||||||
|
const layoutFromBase64 = QueryParameters.GetQueryParameter("userlayout", "false").data;
|
||||||
|
if(layoutFromBase64 === "true"){
|
||||||
|
layoutToUse = CustomLayoutFromJSON.FromQueryParam(hash.substr(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (layoutToUse === undefined) {
|
if (layoutToUse === undefined) {
|
||||||
console.log("Incorrect layout")
|
console.log("Incorrect layout")
|
||||||
new FixedUiElement("Error: incorrect layout <i>" + defaultLayout + "</i><br/><a href='https://pietervdvn.github.io/MapComplete/index.html'>Go back</a>").AttachTo("centermessage").onClick(() => {
|
new FixedUiElement("Error: incorrect layout <i>" + defaultLayout + "</i><br/><a href='https://pietervdvn.github.io/MapComplete/index.html'>Go back</a>").AttachTo("centermessage").onClick(() => {
|
||||||
|
@ -73,8 +83,8 @@ if (layoutToUse === undefined) {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Using layout: ", layoutToUse.name);
|
console.log("Using layout: ", layoutToUse.name);
|
||||||
TagRendering.injectFunction();
|
|
||||||
|
|
||||||
|
TagRendering.injectFunction();
|
||||||
State.state = new State(layoutToUse);
|
State.state = new State(layoutToUse);
|
||||||
InitUiElements.InitBaseMap();
|
InitUiElements.InitBaseMap();
|
||||||
|
|
||||||
|
|
27
preferences.html
Normal file
27
preferences.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link href="index.css" rel="stylesheet"/>
|
||||||
|
<title>Preferences editor</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Preferences editor - developers only</h1>
|
||||||
|
Only use if you know what you're doing. To prevent newbies to make mistakes here, editing a mapcomplete-preference is only available if over 500 changes<br/>
|
||||||
|
Editing any preference -including non-mapcomplete ones- is available when you have more then 2500 changesets. Until that point, only editing mapcomplete-preferences is possible.
|
||||||
|
<div id="maindiv">'maindiv' not attached</div>
|
||||||
|
<script src="./preferences.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue