Merge branch 'develop' into feature/penny-press

This commit is contained in:
Robin van der Linde 2023-07-09 18:57:06 +02:00
commit 9240faef16
No known key found for this signature in database
GPG key ID: 53956B3252478F0D
51 changed files with 534 additions and 103 deletions

View file

@ -27,20 +27,42 @@ import { DesugaringContext } from "../Models/ThemeConfig/Conversion/Conversion"
import { RewriteSpecial } from "../Models/ThemeConfig/Conversion/PrepareLayer"
import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson"
import questions from "../assets/tagRenderings/questions.json"
import Hash from "./Web/Hash"
export default class DetermineLayout {
private static readonly _knownImages = new Set(Array.from(licenses).map((l) => l.path))
private static readonly loadCustomThemeParam = QueryParameters.GetQueryParameter(
"userlayout",
"false",
"If not 'false', a custom (non-official) theme is loaded. This custom layout can be done in multiple ways: \n\n- The hash of the URL contains a base64-encoded .json-file containing the theme definition\n- The hash of the URL contains a lz-compressed .json-file, as generated by the custom theme generator\n- The parameter itself is an URL, in which case that URL will be downloaded. It should point to a .json of a theme"
)
public static getCustomDefinition(): string {
const layoutFromBase64 = decodeURIComponent(DetermineLayout.loadCustomThemeParam.data)
if (layoutFromBase64.startsWith("http")) {
return layoutFromBase64
}
if (layoutFromBase64 !== "false") {
// We have to load something from the hash (or from disk)
const hash = Hash.hash.data
try {
JSON.parse(atob(hash))
return atob(hash)
} catch (e) {
// We try to decode with lz-string
JSON.parse(Utils.UnMinify(LZString.decompressFromBase64(hash)))
return Utils.UnMinify(LZString.decompressFromBase64(hash))
}
}
return undefined
}
/**
* Gets the correct layout for this website
*/
public static async GetLayout(): Promise<LayoutConfig | undefined> {
const loadCustomThemeParam = QueryParameters.GetQueryParameter(
"userlayout",
"false",
"If not 'false', a custom (non-official) theme is loaded. This custom layout can be done in multiple ways: \n\n- The hash of the URL contains a base64-encoded .json-file containing the theme definition\n- The hash of the URL contains a lz-compressed .json-file, as generated by the custom theme generator\n- The parameter itself is an URL, in which case that URL will be downloaded. It should point to a .json of a theme"
)
const layoutFromBase64 = decodeURIComponent(loadCustomThemeParam.data)
const layoutFromBase64 = decodeURIComponent(DetermineLayout.loadCustomThemeParam.data)
if (layoutFromBase64.startsWith("http")) {
return await DetermineLayout.LoadRemoteTheme(layoutFromBase64)
@ -48,7 +70,7 @@ export default class DetermineLayout {
if (layoutFromBase64 !== "false") {
// We have to load something from the hash (or from disk)
return DetermineLayout.LoadLayoutFromHash(loadCustomThemeParam)
return DetermineLayout.LoadLayoutFromHash(DetermineLayout.loadCustomThemeParam)
}
let layoutId: string = undefined

View file

@ -179,7 +179,7 @@ export default class Wikidata {
SERVICE wikibase:mwapi {
bd:serviceParam wikibase:api "EntitySearch" .
bd:serviceParam wikibase:endpoint "www.wikidata.org" .
bd:serviceParam mwapi:search "${text}" .
bd:serviceParam mwapi:search "${text.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}" .
bd:serviceParam mwapi:language "${options.lang}" .
?item wikibase:apiOutputItem mwapi:item .
?num wikibase:apiOrdinal true .

View file

@ -145,7 +145,13 @@ export class UpdateLegacyLayer extends DesugaringStep<
continue
}
const pr = <PointRenderingConfigJson>rendering
const iconSize = pr.iconSize
let iconSize = pr.iconSize
console.log("Iconsize is", iconSize)
if (Object.keys(pr.iconSize).length === 1 && pr.iconSize["render"] !== undefined) {
iconSize = pr.iconSize["render"]
}
if (typeof iconSize === "string")
if (["bottom", "center", "top"].some((a) => (<string>iconSize).endsWith(a))) {
const parts = iconSize.split(",").map((parts) => parts.toLowerCase().trim())

View file

@ -353,9 +353,13 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
const center = map.getCenter()
if (center.lng !== loc.lon || center.lat !== loc.lat) {
if (isNaN(loc.lon) || isNaN(loc.lat)) {
console.error("Got invalid lat or lon, not setting")
} else {
map.setCenter({ lng: loc.lon, lat: loc.lat })
}
}
}
private async awaitStyleIsLoaded(): Promise<void> {
const map = this._maplibreMap.data

View file

@ -996,7 +996,7 @@
},
"mapRendering": [
{
"icon": "./assets/layers/bench/bench.svg",
"icon": "circle:white;./assets/layers/bench/bench.svg",
"iconSize": "35,35",
"iconBadges": [
{

View file

@ -203,7 +203,7 @@
],
"mapRendering": [
{
"icon": "./assets/themes/benches/bench_public_transport.svg",
"icon": "circle:white;./assets/themes/benches/bench_public_transport.svg",
"iconSize": "35,35",
"location": [
"point"

View file

@ -1285,9 +1285,9 @@
"render": {
"en": "There are <b class='text-xl'>{socket:chademo}</b> plugs of type <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div> available here",
"nl": "Hier zijn <b class='text-xl'>{socket:chademo}</b> stekkers van het type <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div>",
"ca": "Aquí hi ha <b class='text-xl'>{socket:chademo}</b> endolls del tipus <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div> disponibles",
"da": "Der er <b class='text-xl'>{socket:chademo}</b> stik af typen <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div> tilgængelig her",
"de": "Hier sind <b class='text-xl'>{socket:chademo}</b> Stecker des Typs <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div> vorhanden",
"ca": "Aquí hi ha <b class='text-xl'>{socket:chademo}</b> endolls del tipus <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div> disponibles"
"de": "Hier sind <b class='text-xl'>{socket:chademo}</b> Stecker des Typs <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div> vorhanden"
},
"freeform": {
"key": "socket:chademo",
@ -1431,8 +1431,8 @@
"render": {
"en": "There are <b class='text-xl'>{socket:type2_combo}</b> plugs of type <div style='display: inline-block'><b><b>Type 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> available here",
"nl": "Hier zijn <b class='text-xl'>{socket:type2_combo}</b> stekkers van het type <div style='display: inline-block'><b><b>Type 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>",
"de": "Hier sind <b class='text-xl'>{socket:type2_combo}</b> Stecker des Typs <div style='display: inline-block'><b><b>Typ 2 CCS</b> (Mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> vorhanden",
"ca": "Aquí hi ha <b class='text-xl'>{socket:type2_combo}</b> endolls del tipus <div style='display: inline-block'><b><b>Tipus 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> disponibles"
"ca": "Aquí hi ha <b class='text-xl'>{socket:type2_combo}</b> endolls del tipus <div style='display: inline-block'><b><b>Tipus 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> disponibles",
"de": "Hier sind <b class='text-xl'>{socket:type2_combo}</b> Stecker des Typs <div style='display: inline-block'><b><b>Typ 2 CCS</b> (Mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> vorhanden"
},
"freeform": {
"key": "socket:type2_combo",
@ -1927,9 +1927,9 @@
"question": {
"en": "What current do the plugs with <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div> offer?",
"nl": "Welke stroom levert de stekker van type <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div>?",
"ca": "Quin corrent ofereixen els endolls amb <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div>?",
"da": "Hvilken strømstyrke har stikkene med <div style='display: inline-block'><b><b> Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div> ?",
"de": "Welche Stromstärke liefern die Stecker mit <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div>?",
"ca": "Quin corrent ofereixen els endolls amb <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div>?"
"de": "Welche Stromstärke liefern die Stecker mit <div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div>?"
},
"render": {
"en": "<div style='display: inline-block'><b><b>Chademo</b></b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Chademo_type4.svg'/></div> outputs at most {socket:chademo:current}A",
@ -1946,9 +1946,9 @@
"then": {
"en": "<b>Chademo</b> outputs at most 120 A",
"nl": "<b>Chademo</b> levert een stroom van maximaal 120 A",
"ca": "<b>Chademo</b> surt com a màxim a 120 A",
"da": "<b>Chademo</b> yder højst 120 A",
"de": "<b>Chademo</b> liefert maximal 120 A",
"ca": "<b>Chademo</b> surt com a màxim a 120 A"
"de": "<b>Chademo</b> liefert maximal 120 A"
},
"icon": {
"path": "./assets/layers/charging_station/Chademo_type4.svg",
@ -1988,8 +1988,8 @@
"then": {
"en": "<b>Chademo</b> outputs at most 50 kw A",
"nl": "<b>Chademo</b> levert een vermogen van maximaal 50 kw A",
"de": "<b>Chademo</b> liefert maximal 50 kw A",
"ca": "<b>Chademo</b> surt com a màxim a 50 kw A"
"ca": "<b>Chademo</b> surt com a màxim a 50 kw A",
"de": "<b>Chademo</b> liefert maximal 50 kw A"
},
"icon": {
"path": "./assets/layers/charging_station/Chademo_type4.svg",
@ -2834,8 +2834,8 @@
"question": {
"en": "What voltage do the plugs with <div style='display: inline-block'><b><b>Type 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> offer?",
"nl": "Welke spanning levert de stekker van type <div style='display: inline-block'><b><b>Type 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>",
"de": "Welche Spannung liefern die Stecker mit <div style='display: inline-block'><b><b>Typ 2 CCS</b> (Mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>?",
"ca": "Quin voltatge ofereixen els endolls amb <div style='display: inline-block'><b><b>Tipus 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>?"
"ca": "Quin voltatge ofereixen els endolls amb <div style='display: inline-block'><b><b>Tipus 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>?",
"de": "Welche Spannung liefern die Stecker mit <div style='display: inline-block'><b><b>Typ 2 CCS</b> (Mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>?"
},
"render": {
"en": "<div style='display: inline-block'><b><b>Type 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> outputs {socket:type2_combo:voltage} volt",
@ -2852,8 +2852,8 @@
"then": {
"en": "<b>Type 2 CCS</b> (mennekes) outputs 500 volt",
"nl": "<b>Type 2 CCS</b> (mennekes) heeft een spanning van 500 volt",
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert 500 Volt",
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt a 500 volts"
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt a 500 volts",
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert 500 Volt"
},
"icon": {
"path": "./assets/layers/charging_station/Type2_CCS.svg",
@ -2865,8 +2865,8 @@
"then": {
"en": "<b>Type 2 CCS</b> (mennekes) outputs 920 volt",
"nl": "<b>Type 2 CCS</b> (mennekes) heeft een spanning van 920 volt",
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert 920 Volt",
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt a 920 volts"
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt a 920 volts",
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert 920 Volt"
},
"icon": {
"path": "./assets/layers/charging_station/Type2_CCS.svg",
@ -2889,9 +2889,9 @@
"question": {
"en": "What current do the plugs with <div style='display: inline-block'><b><b>Type 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> offer?",
"nl": "Welke stroom levert de stekker van type <div style='display: inline-block'><b><b>Type 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>?",
"ca": "Quin corrent ofereixen els endolls amb <div style='display: inline-block'><b><b>Tipus 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>?",
"da": "Hvilken strømstyrke giver stikkene med <div style='display: inline-block'><b><b> Type 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> ?",
"de": "Welche Stromstärke liefern die Stecker mit <div style='display: inline-block'><b><b>Typ 2 CCS</b> (Mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>?",
"ca": "Quin corrent ofereixen els endolls amb <div style='display: inline-block'><b><b>Tipus 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>?"
"de": "Welche Stromstärke liefern die Stecker mit <div style='display: inline-block'><b><b>Typ 2 CCS</b> (Mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div>?"
},
"render": {
"en": "<div style='display: inline-block'><b><b>Type 2 CCS</b> (mennekes)</b> <img style='width:1rem; display: inline-block' src='./assets/layers/charging_station/Type2_CCS.svg'/></div> outputs at most {socket:type2_combo:current}A",
@ -2909,9 +2909,9 @@
"then": {
"en": "<b>Type 2 CCS</b> (mennekes) outputs at most 125 A",
"nl": "<b>Type 2 CCS</b> (mennekes) levert een stroom van maximaal 125 A",
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt com a màxim a 125 A",
"da": "<b>Type 2 CCS</b> (mennekes) udgange på højst 125 A",
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert maximal 125 A",
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt com a màxim a 125 A"
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert maximal 125 A"
},
"icon": {
"path": "./assets/layers/charging_station/Type2_CCS.svg",
@ -2923,9 +2923,9 @@
"then": {
"en": "<b>Type 2 CCS</b> (mennekes) outputs at most 350 A",
"nl": "<b>Type 2 CCS</b> (mennekes) levert een stroom van maximaal 350 A",
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt com a màxim a 350 A",
"da": "<b>Type 2 CCS</b> (mennekes) udgange højst 350 A",
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert maximal 350 A",
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt com a màxim a 350 A"
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert maximal 350 A"
},
"icon": {
"path": "./assets/layers/charging_station/Type2_CCS.svg",
@ -2965,8 +2965,8 @@
"then": {
"en": "<b>Type 2 CCS</b> (mennekes) outputs at most 50 kw A",
"nl": "<b>Type 2 CCS</b> (mennekes) levert een vermogen van maximaal 50 kw A",
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert maximal 50 kw A",
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt com a màxim 50 kw A"
"ca": "<b>Tipus 2 CCS</b> (mennekes) surt com a màxim 50 kw A",
"de": "<b>Typ 2 CCS</b> (Mennekes) liefert maximal 50 kw A"
},
"icon": {
"path": "./assets/layers/charging_station/Type2_CCS.svg",
@ -4405,11 +4405,11 @@
"render": {
"en": "In case of problems, call <a href='tel:{phone}'>{phone}</a>",
"nl": "Bij problemen, bel naar <a href='tel:{phone}'>{phone}</a>",
"ca": "En cas de problemes, truqueu a <a href='tel:{phone}'>{phone}</a>",
"da": "I tilfælde af problemer, ring til <a href='tel:{phone}'>{phone}</a>",
"de": "Bei Problemen, anrufen unter <a href='tel:{phone}'>{phone}</a>",
"es": "En caso de problemas, llama a <a href='tel:{phone}'>{phone}</a>",
"fr": "En cas de problèmes, appelez le <a href='tel:{phone}'>{phone}</a>",
"ca": "En cas de problemes, truqueu a <a href='tel:{phone}'>{phone}</a>"
"fr": "En cas de problèmes, appelez le <a href='tel:{phone}'>{phone}</a>"
},
"freeform": {
"key": "phone",
@ -4462,9 +4462,9 @@
"question": {
"en": "What is the reference number of this charging station?",
"nl": "Wat is het referentienummer van dit oplaadstation?",
"ca": "Quin és el número de referència d'aquest punt de càrrega?",
"de": "Welche Kennnummer hat die Ladestation?",
"es": "¿Cual es el número de referencia de esta estación de carga?",
"ca": "Quin és el número de referència d'aquest punt de càrrega?"
"es": "¿Cual es el número de referencia de esta estación de carga?"
},
"render": {
"en": "Reference number is <b>{ref}</b>",
@ -4633,9 +4633,7 @@
]
}
},
{
"id": "questions"
},
"questions",
{
"id": "questions-technical",
"render": {

View file

@ -719,9 +719,7 @@
]
}
},
{
"id": "questions"
},
"questions",
{
"id": "questions-technical",
"render": {

View file

@ -48,6 +48,16 @@
"ca": "Bicicleta blanca"
},
"mappings": [
{
"if": "subject~*",
"then": {
"en": "Ghost bike in the remembrance of {subject}",
"nl": "Witte fiets ter nagedachtenis van {subject}",
"de": "Geisterrad im Gedenken an {subject}",
"it": "Bici fantasma in ricordo di {subject}",
"fr": "Vélo fantôme en souvenir de {subject}"
}
},
{
"if": "name~*",
"then": {
@ -111,6 +121,24 @@
"fr": "À qui est dédié ce vélo fantôme ?"
},
"render": {
"en": "In remembrance of {subject}",
"nl": "Ter nagedachtenis van {subject}",
"de": "Im Gedenken an {subject}",
"it": "In ricordo di {subject}",
"fr": "En souvenir de {subject}",
"ru": "В знак памяти о {subject}"
},
"freeform": {
"key": "subject",
"addExtraTags": [
"noname=",
"name="
]
},
"mappings": [
{
"if": "name~*",
"then": {
"en": "In remembrance of {name}",
"nl": "Ter nagedachtenis van {name}",
"de": "Im Gedenken an {name}",
@ -118,10 +146,8 @@
"fr": "En souvenir de {name}",
"ru": "В знак памяти о {name}"
},
"freeform": {
"key": "name"
"hideInAnswer": true
},
"mappings": [
{
"if": "noname=yes",
"then": {
@ -131,7 +157,11 @@
"it": "Nessun nome scritto sulla bici",
"fr": "Aucun nom n'est marqué sur le vélo",
"ca": "No hi ha cap nom marcat a la bicicleta"
}
},
"addExtraTags": [
"name=",
"subject="
]
}
],
"id": "ghost_bike-name",

View file

@ -43,6 +43,81 @@
},
"tagRenderings": [
"images",
{
"id": "map_type",
"question": {
"en": "What type of map is shown?",
"de": "Was für eine Karte ist das?"
},
"mappings": [
{
"if": "map_type=topo",
"then": {
"en": "Topographical map <p class='subtle'>The map contains contour lines. </p>"
}
},
{
"if": "map_type=street",
"then": {
"en": "A map with all streets or ways of an area. <p class='subtle'>The streets are mostly named; the angles, distances etc. are accurate</p>"
}
},
{
"if": "map_type=scheme",
"then": {
"en": "This is a schematic map. <p class='subtle'>A sketched map with only important ways and POIs. The angles, distances etc. are merely illustrative, not accurate.</p> "
}
},
{
"if": "map_type=toposcope",
"then": {
"en": "This is a toposcope. <p class='subtle'>A marker erected on high places which indicates the direction to notable landscape features which can be seen from that point<p>"
}
}
]
},
{
"id": "map_size",
"question": {
"en": "What is the size of the shown area on the map?",
"de": "Was wird von der Fläche abgedeckt?"
},
"mappings": [
{
"if": "map_size=building",
"then": {
"en": "A map of the romms within a building"
}
},
{
"if": "map_size=site",
"then": {
"en": "A map of special site, like of a historical castle, a park, a campus, a forest, ....",
"de": "Örtlichkeit (z.B. Burg)"
}
},
{
"if": "map_size=village",
"then": {
"en": "A map showing the village or town"
}
},
{
"if": "map_size=city",
"then": {
"en": " A map of a city.",
"de": "Stadt"
}
},
{
"if": "map_size=region",
"then": {
"en": "The map of an entire region, showing multiple cities and villages",
"de": "Region"
}
}
]
},
{
"labels": [
"map"

View file

@ -0,0 +1,12 @@
[
{
"path": "plaque.svg",
"license": "CC-0",
"authors": [
"OSM Carto"
],
"sources": [
"https://wiki.openstreetmap.org/wiki/File:Plaque.svg"
]
}
]

View file

@ -0,0 +1,41 @@
{
"id": "memorial",
"description": "Layer showing memorial plaques, based upon a unofficial theme. Can be expanded to have multiple types of memorials later on",
"source": {
"osmTags": "memorial=plaque"
},
"title": {
"render": {
"en": "Memorial plaque"
}
},
"tagRenderings": [
{
"id": "inscription",
"question": {
"en": "What is the inscription of this plaque?"
},
"render": {
"en": "The inscription on this plaque reads: <p><i>{inscription}<i></p>"
},
"freeform": {
"key": "inscription",
"type": "text"
}
}
],
"mapRendering": [
{
"location": [
"centroid",
"point"
],
"icon": "circle:white;./assets/layers/memorial/plaque.svg"
}
],
"deletion": true,
"allowMove": {
"enableImproveAccuracy": true,
"enableRelocation": false
}
}

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="14"
height="14"
viewBox="0 0 14 14"
id="svg2">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<rect
width="14"
height="14"
x="0"
y="0"
id="canvas"
style="fill:none;stroke:none;visibility:hidden" />
<path
style="fill:#734a08;fill-opacity:1;stroke:none"
id="plaque"
d="M 2.5,2 C 1.6887616,2 1,2.6887616 1,3.5 l 0,7 C 1,11.269291 1.667788,12 2.5,12 l 9,0 c 0.748318,0 1.5,-0.709735 1.5,-1.5 l 0,-7 C 13,2.7307086 12.269291,2 11.5,2 z m 0,1 C 2.7761424,3 3,3.2238576 3,3.5 3,3.7761424 2.7761424,4 2.5,4 2.2238576,4 2,3.7761424 2,3.5 2,3.2238576 2.2238576,3 2.5,3 z m 9,0 C 11.776142,3 12,3.2238576 12,3.5 12,3.7761424 11.776142,4 11.5,4 11.223858,4 11,3.7761424 11,3.5 11,3.2238576 11.223858,3 11.5,3 z M 5,4 6,4 6,5 5,5 z M 7,4 9,4 9,5 7,5 z M 3,6 11,6 11,7 3,7 z M 5,8 9,8 9,9 5,9 z M 2.5,10 C 2.7761424,10 3,10.223858 3,10.5 3,10.776142 2.7761424,11 2.5,11 2.2238576,11 2,10.776142 2,10.5 2,10.223858 2.2238576,10 2.5,10 z m 9,0 C 11.776142,10 12,10.223858 12,10.5 12,10.776142 11.776142,11 11.5,11 11.223858,11 11,10.776142 11,10.5 11,10.223858 11.223858,10 11.5,10 z" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,5 +1,5 @@
{
"id": "shared_questions",
"id": "questions",
"questions": {
"description": "Show the images block at this location",
"render": {

View file

@ -47,20 +47,20 @@
"_has_left_parking=(feat.properties['parking:lane:left'] ?? feat.properties['parking:lane:both']) === 'parallel'",
"_has_right_parking=(feat.properties['parking:lane:right'] ?? feat.properties['parking:lane:both']) === 'parallel'",
"_has_other_parking= ['parking:lane:left','parking:lane:right','parking:lane:both'].some(key => ['perpendicular','diagonal'].indexOf(feat.properties[key]) >= 0)",
"_parallel_parking_count=feat.get('_has_right_parking') + feat.get('_has_left_parking') /* in javascript logic: true + true == 2*/",
"_width:needed:parking=feat.get('_parallel_parking_count') * feat.get('_car_width')",
"_parallel_parking_count=get(feat)('_has_right_parking') + get(feat)('_has_left_parking') /* in javascript logic: true + true == 2*/",
"_width:needed:parking=get(feat)('_parallel_parking_count') * get(feat)('_car_width')",
"_has_sidewalk_left=['left','both'].indexOf(feat.properties['sidewalk']) >= 0",
"_has_sidewalk_right=['right','both'].indexOf(feat.properties['sidewalk']) >= 0",
"_pedestrian_flows_in_carriageway= 2 - feat.get('_has_sidewalk_left') - feat.get('_has_sidewalk_right')",
"_width:needed:pedestrians=feat.get('_pedestrianWidth') * feat.get('_pedestrian_flows_in_carriageway')",
"_pedestrian_flows_in_carriageway= 2 - get(feat)('_has_sidewalk_left') - get(feat)('_has_sidewalk_right')",
"_width:needed:pedestrians=get(feat)('_pedestrianWidth') * get(feat)('_pedestrian_flows_in_carriageway')",
"_oneway_car=(feat.properties['oneway:motor_vehicle'] ?? feat.properties['oneway']) == 'yes'",
"_width:needed:cars=feat.get('_car_width') * (2 - feat.get('_oneway_car'))",
"_width:needed:cars=get(feat)('_car_width') * (2 - get(feat)('_oneway_car'))",
"_cycling_allowed=feat.properties.bicycle != 'use_sidepath' && feat.properties.bicycle!='no'",
"_oneway_bicycle=((feat.properties['oneway:bicycle'] ?? feat.properties['oneway']) == 'yes') && feat.properties['cycleway'] != 'opposite'",
"_width:needed:cyclists=feat.get('_cycling_allowed') ? (feat.get('_cyclistWidth') * (2 - feat.get('_oneway_bicycle'))) : 0",
"_width:needed:total:=feat.get('_width:needed:cars') + feat.get('_width:needed:parking') + feat.get('_width:needed:cyclists') + feat.get('_width:needed:pedestrians')",
"_width:difference:=feat.get('_width:needed:total') - feat.get('width:carriageway')",
"_width:difference:no_pedestrians:=feat.get('_width:difference') - feat.get('_width:needed:pedestrians')"
"_width:needed:cyclists=get(feat)('_cycling_allowed') ? (get(feat)('_cyclistWidth') * (2 - get(feat)('_oneway_bicycle'))) : 0",
"_width:needed:total:=get(feat)('_width:needed:cars') + get(feat)('_width:needed:parking') + get(feat)('_width:needed:cyclists') + get(feat)('_width:needed:pedestrians')",
"_width:difference:=get(feat)('_width:needed:total') - get(feat)('width:carriageway')",
"_width:difference:no_pedestrians:=get(feat)('_width:difference') - get(feat)('_width:needed:pedestrians')"
],
"minzoom": 12,
"source": {

View file

@ -1,9 +1,12 @@
import { Utils } from "./Utils"
import DetermineLayout from "./Logic/DetermineLayout"
import ThemeViewState from "./Models/ThemeViewState"
import SvelteUIElement from "./UI/Base/SvelteUIElement"
import ThemeViewGUI from "./UI/ThemeViewGUI.svelte"
import { FixedUiElement } from "./UI/Base/FixedUiElement"
import Combine from "./UI/Base/Combine"
import { SubtleButton } from "./UI/Base/SubtleButton"
import Svg from "./Svg"
import { Utils } from "./Utils"
// @ts-ignore
try {
@ -15,7 +18,17 @@ try {
})
.catch((err) => {
console.error("Error while initializing: ", err, err.stack)
new FixedUiElement(err).SetClass("block alert").AttachTo("maindiv")
new Combine([
new FixedUiElement(err).SetClass("block alert"),
new SubtleButton(Svg.download_svg(), "Download the raw file").onClick(() =>
Utils.offerContentsAsDownloadableFile(
DetermineLayout.getCustomDefinition(),
"mapcomplete-theme.json",
{ mimetype: "application/json" }
)
),
]).AttachTo("maindiv")
})
} catch (err) {
new FixedUiElement(err).SetClass("block alert").AttachTo("maindiv")

View file

@ -3152,7 +3152,7 @@
},
"ghost_bike-name": {
"mappings": {
"0": {
"1": {
"then": "No hi ha cap nom marcat a la bicicleta"
}
},

View file

@ -5047,12 +5047,15 @@
"ghost_bike-name": {
"mappings": {
"0": {
"then": "Im Gedenken an {name}"
},
"1": {
"then": "Am Fahrrad ist kein Name angegeben"
}
},
"question": "An wen erinnert dieses Geisterrad?",
"questionHint": "Bitte respektieren Sie die Privatsphäre - geben Sie den Namen nur an, wenn er weit verbreitet oder auf dem Fahrrad markiert ist. Den Familiennamen können Sie weglassen.",
"render": "Im Gedenken an {name}"
"render": "Im Gedenken an {subject}"
},
"ghost_bike-source": {
"question": "Auf welcher Webseite kann man mehr Informationen über das Geisterrad oder den Unfall finden?",
@ -5066,6 +5069,9 @@
"title": {
"mappings": {
"0": {
"then": "Geisterrad im Gedenken an {subject}"
},
"1": {
"then": "Geisterrad im Gedenken an {name}"
}
},
@ -5624,6 +5630,23 @@
},
"question": "Auf welchen Daten basiert diese Karte?",
"render": "Diese Karte basiert auf {map_source}"
},
"map_size": {
"mappings": {
"1": {
"then": "Örtlichkeit (z.B. Burg)"
},
"3": {
"then": "Stadt"
},
"4": {
"then": "Region"
}
},
"question": "Was wird von der Fläche abgedeckt?"
},
"map_type": {
"question": "Was für eine Karte ist das?"
}
},
"title": {

View file

@ -5047,12 +5047,15 @@
"ghost_bike-name": {
"mappings": {
"0": {
"then": "In remembrance of {name}"
},
"1": {
"then": "No name is marked on the bike"
}
},
"question": "Whom is remembered by this ghost bike?",
"questionHint": "Please respect privacy - only fill out the name if it is widely published or marked on the cycle. Opt to leave out the family name.",
"render": "In remembrance of {name}"
"render": "In remembrance of {subject}"
},
"ghost_bike-source": {
"question": "On what webpage can one find more info about the ghost bike or the accident?",
@ -5066,6 +5069,9 @@
"title": {
"mappings": {
"0": {
"then": "Ghost bike in the remembrance of {subject}"
},
"1": {
"then": "Ghost bike in the remembrance of {name}"
}
},
@ -5624,6 +5630,43 @@
},
"question": "On which data is this map based?",
"render": "This map is based on {map_source}"
},
"map_size": {
"mappings": {
"0": {
"then": "A map of the romms within a building"
},
"1": {
"then": "A map of special site, like of a historical castle, a park, a campus, a forest, ...."
},
"2": {
"then": "A map showing the village or town"
},
"3": {
"then": " A map of a city."
},
"4": {
"then": "The map of an entire region, showing multiple cities and villages"
}
},
"question": "What is the size of the shown area on the map?"
},
"map_type": {
"mappings": {
"0": {
"then": "Topographical map <p class='subtle'>The map contains contour lines. </p>"
},
"1": {
"then": "A map with all streets or ways of an area. <p class='subtle'>The streets are mostly named; the angles, distances etc. are accurate</p>"
},
"2": {
"then": "This is a schematic map. <p class='subtle'>A sketched map with only important ways and POIs. The angles, distances etc. are merely illustrative, not accurate.</p> "
},
"3": {
"then": "This is a toposcope. <p class='subtle'>A marker erected on high places which indicates the direction to notable landscape features which can be seen from that point<p>"
}
},
"question": "What type of map is shown?"
}
},
"title": {
@ -5843,6 +5886,17 @@
}
}
},
"memorial": {
"tagRenderings": {
"inscription": {
"question": "What is the inscription of this plaque?",
"render": "The inscription on this plaque reads: <p><i>{inscription}<i></p>"
}
},
"title": {
"render": "Memorial plaque"
}
},
"nature_reserve": {
"description": "A nature reserve is an area where nature can take its course",
"filter": {
@ -6842,10 +6896,30 @@
"public_bookcase": {
"description": "A streetside cabinet with books, accessible to anyone",
"filter": {
"0": {
"options": {
"0": {
"question": "Has children books"
}
}
},
"1": {
"options": {
"0": {
"question": "Has books for adults"
}
}
},
"2": {
"options": {
"0": {
"question": "Indoor or outdoor"
},
"1": {
"question": "Located indoors"
},
"2": {
"question": "Located outdoors"
}
}
}

View file

@ -3533,12 +3533,15 @@
"ghost_bike-name": {
"mappings": {
"0": {
"then": "En souvenir de {name}"
},
"1": {
"then": "Aucun nom n'est marqué sur le vélo"
}
},
"question": "À qui est dédié ce vélo fantôme ?",
"questionHint": "Veuillez respecter la vie privée ajoutez le nom seulement s'il est largement publié ou marqué sur le vélo. Choisissez de ne pas indiquer le nom de famille ",
"render": "En souvenir de {name}"
"render": "En souvenir de {subject}"
},
"ghost_bike-source": {
"question": "Sur quelle page web peut-on trouver plus d'informations sur le Vélo fantôme ou l'accident ?",
@ -3552,6 +3555,9 @@
"title": {
"mappings": {
"0": {
"then": "Vélo fantôme en souvenir de {subject}"
},
"1": {
"then": "Vélo fantôme en souvenir de {name}"
}
},

View file

@ -1332,12 +1332,15 @@
"ghost_bike-name": {
"mappings": {
"0": {
"then": "In ricordo di {name}"
},
"1": {
"then": "Nessun nome scritto sulla bici"
}
},
"question": "A chi è dedicata questa bici fantasma?",
"questionHint": "Rispetta la privacy (compila solo il nome se questo è stato ampiamente pubblicato o se è scritto sulla bici). Decidi se è il caso di non inserire il cognome.",
"render": "In ricordo di {name}"
"render": "In ricordo di {subject}"
},
"ghost_bike-source": {
"question": "In quale pagina web si possono trovare informazioni sulla bici fantasma o lincidente?",
@ -1351,6 +1354,9 @@
"title": {
"mappings": {
"0": {
"then": "Bici fantasma in ricordo di {subject}"
},
"1": {
"then": "Bici fantasma in ricordo di {name}"
}
},

View file

@ -4823,12 +4823,15 @@
"ghost_bike-name": {
"mappings": {
"0": {
"then": "Ter nagedachtenis van {name}"
},
"1": {
"then": "De naam is niet aangeduid op de fiets"
}
},
"question": "Aan wie is deze witte fiets een eerbetoon?",
"questionHint": "Respecteer privacy - voeg enkel een naam toe indien die op de fiets staat of gepubliceerd is. Eventueel voeg je enkel de voornaam toe.",
"render": "Ter nagedachtenis van {name}"
"render": "Ter nagedachtenis van {subject}"
},
"ghost_bike-source": {
"question": "Op welke website kan men meer informatie vinden over de Witte fiets of over het ongeval?",
@ -4842,6 +4845,9 @@
"title": {
"mappings": {
"0": {
"then": "Witte fiets ter nagedachtenis van {subject}"
},
"1": {
"then": "Witte fiets ter nagedachtenis van {name}"
}
},
@ -6518,10 +6524,30 @@
"public_bookcase": {
"description": "Een straatkastje met boeken voor iedereen",
"filter": {
"0": {
"options": {
"0": {
"question": "Kinderboeken aanwezig"
}
}
},
"1": {
"options": {
"0": {
"question": "Boeken voor volwassenen aanwezig"
}
}
},
"2": {
"options": {
"0": {
"question": "Binnen of buiten"
},
"1": {
"question": "Bevindt zich binnen"
},
"2": {
"question": "Bevindt zich buiten"
}
}
}

View file

@ -988,7 +988,12 @@
"render": "<i>{inscription}</i>"
},
"ghost_bike-name": {
"render": "В знак памяти о {name}"
"mappings": {
"0": {
"then": "В знак памяти о {name}"
}
},
"render": "В знак памяти о {subject}"
},
"ghost_bike-source": {
"render": "<a href='{source}' target='_blank'>Доступна более подробная информация</a>"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "Er der stadig noget relevant, du ikke kunne give i de foregående spørgsmål? Tilføj det her.",
"questionHint": "Gentag ikke allerede nævnte fakta"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"dog-access": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "Mayroon pa bang mga bagay na nau-ugnay at hindi mo maibigay sa mga nakaraang tanong? Idagdag dito.",
"questionHint": "Huwag ulitin ang mga nai-saad na"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"website": {
"question": "Cal é a páxina web de {title()}?"
}

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "Van-e még valami lényeges, amit nem tudott megadni az előző kérdésekben? Itt megteheti.",
"questionHint": "Ne ismételjen meg már megadott tényeket"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "C'è ancora qualche informazione importante che non è stato possibile fornire nelle domande precedenti? Aggiungila qui.",
"questionHint": "Non ripetere informazioni già fornite"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "前の質問で伝えきれなかった関連事項がまだありますか?ここに追加してください。",
"questionHint": "今後表示しない"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"dog-access": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"denominations-coins": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "Ainda há algo de relevante que não tenha podido dar nas perguntas anteriores? Adicione-o aqui.",
"questionHint": "Não repita factos já declarados"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "Ainda há algo de relevante que não pôde dar nas perguntas anteriores? Adicione aqui.",
"questionHint": " Não repita fatos já declarados"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "Есть ли ещё что-то важное, о чём вы не смогли рассказать в предыдущих вопросах? Добавьте это здесь.",
"questionHint": "Не повторяйте уже изложенные факты"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "Ali je še kaj pomembnega, česar niste mogli povedati v prejšnjih vprašanjih? Dopišite tukaj.",
"questionHint": "Ne ponavljajte že navedenih dejstev"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "Finns det fortfarande någonting relevant som du inte kunde ge i de föregående frågorna? Lägg till det här.",
"questionHint": "Repetera inte redan angivna fakta"

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"dog-access": {
"mappings": {
"0": {

View file

@ -1,5 +1,5 @@
{
"shared_questions": {
"questions": {
"description": {
"question": "有什麼相關的資訊你無法在先前的問題回應的嗎?請加在這邊吧。",
"questionHint": "不要重覆答覆已經知道的事情"

View file

@ -408,6 +408,45 @@
}
}
}
},
"1": {
"override": {
"+tagRenderings": {
"0": {
"mappings": {
"0": {
"then": "This shop repairs climbing shoes"
},
"1": {
"then": "This shop does not repair climbing shoes"
}
},
"question": "Does this shoe repair shop repair climbing shoes?"
}
}
}
},
"2": {
"override": {
"+tagRenderings": {
"0": {
"mappings": {
"0": {
"then": "This shop repairs climbing shoes"
},
"1": {
"then": "This shop does not repair climbing shoes"
}
},
"question": "Does this shoe repair shop also repair clibming shoes?"
}
},
"=presets": {
"0": {
"title": "a shoe repair shop"
}
}
}
}
},
"title": "Climbing gyms, clubs and spots"

View file

@ -3,15 +3,30 @@ import { Utils } from "../Utils"
import * as fs from "fs"
async function main(args: string[]) {
let directory = "./langs"
{
const dirs = ["layers", "themes", "shared-questions"]
for (const dir of dirs) {
const layerIndex = args.findIndex((s) => s === "--" + dir)
if (layerIndex >= 0) {
directory = "./langs/" + dir
args.splice(layerIndex, 1)
}
}
}
if (args.length !== 1) {
console.log(
"Usage: first argument is the fully qualified key of the string to remove. Only removes translations in the core translations"
"Usage: first argument is the fully qualified key of the string to remove. Removes translations in the core translations, unless '--layers' or '--themes' is given"
)
return
}
// Path within the JSON which will be removed - not the path in the filesystem!
const path = args[0].split(".")
console.log("Removing translation string ", path, "from the general translations")
const files = ScriptUtils.readDirRecSync("./langs", 1).filter((f) => f.endsWith(".json"))
const files = ScriptUtils.readDirRecSync(directory, 1).filter((f) => f.endsWith(".json"))
for (const file of files) {
const json = JSON.parse(fs.readFileSync(file, { encoding: "utf-8" }))
Utils.WalkPath(path, json, (_) => undefined)