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;
|
||||
|
||||
constructor(id: string, options: {
|
||||
name: string,
|
||||
name: string | UIElement,
|
||||
description: string | UIElement,
|
||||
presets: {
|
||||
tags: Tag[],
|
||||
title: string | UIElement,
|
||||
description?: string | UIElement,
|
||||
icon?: string
|
||||
}[],
|
||||
presets: Preset[],
|
||||
icon: string,
|
||||
minzoom: number,
|
||||
overpassFilter: TagsFilter,
|
||||
|
|
|
@ -55,7 +55,7 @@ export class InitUiElements {
|
|||
}
|
||||
|
||||
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},
|
||||
|
||||
]
|
||||
|
|
15
UI/Img.ts
15
UI/Img.ts
|
@ -1,4 +1,19 @@
|
|||
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 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"?>
|
||||
<!-- 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"
|
||||
version="1.0"
|
||||
width="900"
|
||||
height="900"
|
||||
id="svg11382"
|
||||
sodipodi:docname="help.svg"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
|
||||
height="900"
|
||||
width="900"
|
||||
version="1.0">
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
|
@ -27,45 +21,22 @@
|
|||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</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
|
||||
id="defs11384" />
|
||||
<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
|
||||
id="g11476">
|
||||
<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"
|
||||
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
|
||||
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"
|
||||
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>
|
||||
</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/*
|
||||
|
||||
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
|
||||
echo "Not removing $f"
|
||||
else
|
||||
|
|
|
@ -462,6 +462,12 @@ form {
|
|||
margin: 0 10px 0 18px;
|
||||
}
|
||||
|
||||
#filter__selection ul svg {
|
||||
width: 20px;
|
||||
height: auto;
|
||||
margin: 0 10px 0 18px;
|
||||
}
|
||||
|
||||
.filter__label {
|
||||
font-size: 16px;
|
||||
transform: translateY(75px);
|
||||
|
@ -1149,6 +1155,7 @@ form {
|
|||
padding: 0.5em;
|
||||
}
|
||||
|
||||
|
||||
.tab-content {
|
||||
padding: 1em;
|
||||
z-index: 5002;
|
||||
|
|
14
index.ts
14
index.ts
|
@ -18,6 +18,7 @@ import {TagRenderingOptions} from "./Customizations/TagRenderingOptions";
|
|||
import {TagRendering} from "./Customizations/TagRendering";
|
||||
import {Img} from "./UI/Img";
|
||||
import Combine from "./UI/Base/Combine";
|
||||
import {CustomLayoutFromJSON} from "./Customizations/JSON/CustomLayoutFromJSON";
|
||||
|
||||
|
||||
// --------------------- Special actions based on the parameters -----------------
|
||||
|
@ -41,6 +42,7 @@ if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
|
|||
// ----------------- SELECT THE RIGHT QUESTSET -----------------
|
||||
|
||||
let defaultLayout = "bookcases"
|
||||
let hash = window.location.hash;
|
||||
|
||||
const path = window.location.pathname.split("/").slice(-1)[0];
|
||||
if (path !== "index.html") {
|
||||
|
@ -64,7 +66,15 @@ for (const k in AllKnownLayouts.allSets) {
|
|||
|
||||
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) {
|
||||
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(() => {
|
||||
|
@ -73,8 +83,8 @@ if (layoutToUse === undefined) {
|
|||
}
|
||||
|
||||
console.log("Using layout: ", layoutToUse.name);
|
||||
TagRendering.injectFunction();
|
||||
|
||||
TagRendering.injectFunction();
|
||||
State.state = new State(layoutToUse);
|
||||
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