diff --git a/AllTranslationAssets.ts b/AllTranslationAssets.ts
index 2e15891c97..ab678c827e 100644
--- a/AllTranslationAssets.ts
+++ b/AllTranslationAssets.ts
@@ -59,6 +59,7 @@ export default class AllTranslationAssets {
emailOf: new Translation( {"en":"What is the email address of {category}?","ca":"Quina és l'adreça de correu-e de {category}?","es":"¿Qué dirección de correu tiene {category}?","nl":"Wat is het email-adres van {category}?","fr":"Quel est l'adresse email de {category}?","gl":"Cal é o enderezo de correo electrónico de {category}?","de":"Wie lautet die E-Mail-Adresse der {category}?"} ),
emailIs: new Translation( {"en":"The email address of this {category} is {email}","ca":"L'adreça de correu de {category} és {email}","es":"La dirección de correo de {category} es {email}","nl":"Het email-adres van {category} is {email}","fr":"L'adresse email de {category} est {email}","gl":"O enderezo de correo electrónico de {category} é {email}","de":"Die E-Mail-Adresse dieser {category} lautet {email}"} ),
},
+ customIntro: new Translation( {"en":"
Das Projekt nutzt Daten des OpenStreetMap Projekts und basiert auf der freien Software MapComplete.
"} ),
openStreetMapIntro: new Translation( {"en":"
An Open Map
Wouldn't it be cool if there was a single map, which everyone could freely use and edit? A single place to store all geo-information? Then, all those websites with different, small and incompatible maps (which are always outdated) wouldn't be needed anymore.
OpenStreetMap is this map. The map data can be used for free (with attribution and publication of changes to that data). On top of that, everyone can freely add new data and fix errors. This website uses OpenStreetMap as well. All the data is from there, and your answers and corrections are added there as well.
A ton of people and application already use OpenStreetMap: Maps.me, OsmAnd, but also the maps at Facebook, Instagram, Apple-maps and Bing-maps are (partly) powered by OpenStreetMap.If you change something here, it'll be reflected in those applications too - after their next update!
","es":"
Un mapa abierto
¿No sería genial si hubiera un solo mapa, que todos pudieran usar y editar libremente?¿Un solo lugar para almacenar toda la información geográfica? Entonces, todos esos sitios web con mapas diferentes, pequeños e incompatibles (que siempre están desactualizados) ya no serían necesarios.
OpenStreetMap es ese mapa. Los datos del mapa se pueden utilizar de forma gratuita (con atribución y publicación de cambios en esos datos).Además de eso, todos pueden agregar libremente nuevos datos y corregir errores. Este sitio web también usa OpenStreetMap. Todos los datos provienen de allí, y tus respuestas y correcciones también se añadirán allí.
Muchas personas y aplicaciones ya usan OpenStreetMap: Maps.me, OsmAnd, pero también los mapas de Facebook, Instagram, Apple y Bing son (en parte) impulsados por OpenStreetMap .Si cambias algo aquí, también se reflejará en esas aplicaciones, en su próxima actualización
","ca":"
Un mapa obert
No seria genial si hagués un únic mapa, que tothom pogués utilitzar i editar lliurement?Un sol lloc on emmagatzemar tota la informació geogràfica? Llavors tots aquests llocs web amb mapes diferents petits i incompatibles (que sempre estaran desactulitzats) ja no serien necessaris.
OpenStreetMap és aquest mapa. Les dades del mapa es poden utilitzar de franc (amb atribució i publicació de canvis en aquestes dades).A més a més, tothom pot agregar lliurement noves dades i corregir errors. De fet, aquest lloc web també fa servir OpenStreetMap. Totes les dades provenen d'allà i les teves respostes i correccions també s'afegiran allà.
Moltes persones i aplicacions ja utilitzen OpenStreetMap: Maps.me, OsmAnd, però també els mapes de Facebook, Instagram, Apple i Bing són (en part) impulsats per OpenStreetMap.Si canvies alguna cosa aquí també es reflectirà en aquestes aplicacions en la seva propera actualització.
","nl":"
Een open kaart
Zou het niet fantastisch zijn als er een open kaart zou zijn die door iedereen aangepast én gebruikt kan worden? Een kaart waar iedereen zijn interesses aan zou kunnen toevoegen? Dan zouden er geen duizend-en-één verschillende kleine kaartjes, websites, ... meer nodig zijn
OpenStreetMap is deze open kaart. Je mag de kaartdata gratis gebruiken (mits bronvermelding en herpublicatie van aanpassingen). Daarenboven mag je de kaart ook gratis aanpassen als je een account maakt. Ook deze website is gebaseerd op OpenStreetMap. Als je hier een vraag beantwoord, gaat het antwoord daar ook naartoe
Tenslotte zijn er reeds vele gebruikers van OpenStreetMap. Denk maar Maps.me, OsmAnd, verschillende gespecialiseerde routeplanners, de achtergrondkaarten op Facebook, Instagram,... Zelfs Apple Maps en Bing-Maps gebruiken OpenStreetMap in hun kaarten!
Kortom, als je hier een punt toevoegd of een vraag beantwoord, zal dat na een tijdje ook in al dié applicaties te zien zijn.
","fr":"
Une carte ouverte
How incroyable se serait d'avoir sur une carte que tout le monde pourrait éditer ouvertement?Une seule et unique plateforme regroupant toutes les informations geographiques? Ainsi nous n'aurons plus besoin de toutes ces petites et incompatibles cartes (souvent non mises à jour).
OpenStreetMap est la carte qu'il vous faut!. Toutes les donnees de cette carte peuvent être utilisé gratuitement (avec d'attribution et de publication des changements de données). De plus tout le monde est libre d'ajouter de nouvelles données et corriger les erreurs. Ce site internet utilise également OpenStreetMap. Toutes les données y proviennent et tous les ajouts et modifications y seront également ajoutés.
De nombreux individus et d'applications utilisent déjà OpenStreetMap: Maps.me, OsmAnd, mais aussi les cartes de Facebook, Instagram, Apple-maps et Bing-maps sont(en partie) supporté par OpenStreetMap.Si vous modifié quelque chose ici, ces changement seront retranscris sur ces applications aussi - des lors de leur mise à jour!
","gl":"
Un mapa aberto
Non sería xenial se houbera un só mapa, que todos puideran empregar e editar de xeito libre?Un só lugar para almacenar toda a información xeográfica? Entón, todos eses sitios web con mapas diferentes, pequenos e incompatíbeis (que sempre están desactualizados) xa non serían necesarios.
OpenStreetMap é ese mapa. Os datos do mapa pódense empregar de balde (con atribución e publicación de modificacións neses datos).Ademais diso, todos poden engadir de xeito ceibe novos datos e corrixir erros. Este sitio web tamén emprega o OpenStreetMap. Todos os datos proveñen de alí, e as túas respostas e correccións tamén serán engadidas alí.
Moitas persoas e aplicacións xa empregan o OpenStreetMap: Maps.me, OsmAnd, pero tamén os mapas do Facebook, Instagram, Apple e Bing son (en parte) impulsados polo OpenStreetMap.Se mudas algo aquí, tamén será reflexado nesas aplicacións, na súa seguinte actualización!
","de":"
Eine offene Karte
Wäre es nicht toll, wenn es eine offene Karte gäbe, die von jedem angepasst und benutzt werden könnte? Eine Karte, zu der jeder seine Interessen hinzufügen kann? Dann bräuchte man all diese Websites mit unterschiedlichen, kleinen und inkompatiblen Karten (die immer veraltet sind) nicht mehr.
OpenStreetMap ist diese offene Karte. Die Kartendaten können kostenlos verwendet werden (mit Attribution und Veröffentlichung von Änderungen an diesen Daten). Darüber hinaus können Sie die Karte kostenlos ändern und Fehler beheben, wenn Sie ein Konto erstellen. Diese Website basiert ebenfalls auf OpenStreetMap. Wenn Sie eine Frage hier beantworten, geht die Antwort auch dorthin.
Viele Menschen und Anwendungen nutzen OpenStreetMap bereits: Maps.me, OsmAnd, verschiedene spezialisierte Routenplaner, die Hintergrundkarten auf Facebook, Instagram,... Sogar Apple Maps und Bing Maps verwenden OpenStreetMap in ihren Karten!
Wenn Sie hier einen Punkt hinzufügen oder eine Frage beantworten, wird er nach einer Weile in all diesen Anwendungen sichtbar sein.
"} ),
sharescreen: { intro: new Translation( {"en":"
Share this map
Share this map by copying the link below and sending it to friends and family:","ca":"
Comparteix aquest mapa
Comparteix aquest mapa copiant l'enllaç de sota i enviant-lo a amics i família:","es":"
Comparte este mapa
Comparte este mapa copiando el enlace de debajo y enviándolo a amigos y familia:","fr":"
Partager cette carte
Partagez cette carte en copiant le lien suivant et envoyer le à vos amis:","nl":"
Deel deze kaart
Kopieer onderstaande link om deze kaart naar vrienden en familie door te sturen:","gl":"
Comparte este mapa
Comparte este mapa copiando a ligazón de embaixo e enviándoa ás amizades e familia:","de":"
Diese Karte teilen
Sie können diese Karte teilen, indem Sie den untenstehenden Link kopieren und an Freunde und Familie schick"} ),
addToHomeScreen: new Translation( {"en":"
Add to your home screen
You can easily add this website to your smartphone home screen for a native feel. Click the 'add to home screen button' in the URL bar to do this.","ca":"
Afegir-lo a la pantalla d'inici
Pots afegir aquesta web a la pantalla d'inici del teu smartphone per a que es vegi més nadiu. Apreta al botó 'afegir a l'inici' a la barra d'adreces URL per fer-ho.","es":"
Añadir a la pantalla de inicio
Puedes añadir esta web en la pantalla de inicio de tu smartphone para que se vea más nativo. Aprieta el botón 'añadir a inicio' en la barra de direcciones URL para hacerlo.","fr":"
Ajouter à votre page d'accueil
Vous pouvez facilement ajouter la carte à votre écran d'accueil de téléphone. Cliquer sur le boutton 'ajouter à l'evran d'accueil' dans la barre d'URL pour éffecteur cette tâche","gl":"
Engadir á pantalla de inicio
Podes engadir esta web na pantalla de inicio do teu smartphone para que se vexa máis nativo. Preme o botón 'engadir ó inicio' na barra de enderezos URL para facelo.","nl":"
Voeg toe aan je thuis-scherm
Je kan deze website aan je thuisscherm van je smartphone toevoegen voor een native feel","de":"
Zum Startbildschirm hinzufügen
Sie können diese Website einfach zum Startbildschirm Ihres Smartphones hinzufügen, um ein natives Gefühl zu erhalten. Klicken Sie dazu in der URL-Leiste auf die Schaltfläche 'Zum Startbildschirm hinzufügen'."} ),
@@ -90,7 +91,7 @@ export default class AllTranslationAssets {
getStartedNewAccount: new Translation( {"en":" or create a new account","nl":" of maak een nieuwe account aan ","fr":" ou registrez vous","es":" o crea una nueva cuenta","ca":" o crea un nou compte","gl":" ou crea unha nova conta","de":" oder ein neues Konto anlegen"} ),
noTagsSelected: new Translation( {"en":"No tags selected","es":"No se han seleccionado etiquetas","ca":"No s'han seleccionat etiquetes","gl":"Non se seleccionaron etiquetas","de":"Keine Tags ausgewählt"} ),
customThemeIntro: new Translation( {"en":"
Custom themes
These are previously visited user-generated themes.","nl":"
Onofficiële themea's
Je bezocht deze thema's gemaakt door andere OpenStreetMappers eerder","gl":"
Temas personalizados
Estes son temas xerados por usuarios previamente visitados.","de":"
Kundenspezifische Themen
Dies sind zuvor besuchte benutzergenerierte Themen"} ),
- aboutMapcomplete: new Translation( {"en":"
About MapComplete
MapComplete is an OpenStreetMap editor that is meant to help everyone to easily add information on a single theme.
Only features relevant to a single theme are shown with a few predefined questions, in order to keep things simple and extremly user-friendly.The theme maintainer can also choose a language for the interface, choose to disable elements or even to embed it into a different website without any UI-element at all.
However, another important part of MapComplete is to always offer the next step to learn more about OpenStreetMap:
An iframe without UI-elements will link to a full-screen version
The fullscreen version offers information about OpenStreetMap
If you're not logged in, you're asked to log in
If you answered a single question, you are allowed to add points
At a certain point, the actual added tags appear which later get linked to the wiki...
Do you notice an issue with MapComplete? Do you have a feature request? Do you want to help translating? Head over to the source code or issue tracker.
","nl":"
Over MapComplete
MapComplete is een OpenStreetMap-editor om eenvoudig informatie toe te voegen over één enkel onderwerp.
Om de editor zo simpel en gebruiksvriendelijk mogelijk te houden, worden enkel objecten relevant voor het thema getoond.Voor deze objecten kunnen dan vragen beantwoord worden, of men kan een nieuw punt van dit thema toevoegen.De maker van het thema kan er ook voor opteren om een aantal elementen van de gebruikersinterface uit te schakelen of de taal ervan in te stellen.
Een ander belangrijk aspect is om bezoekers stap voor stap meer te leren over OpenStreetMap:
Een iframe zonder verdere uitleg linkt naar de volledige versie van MapComplete
De volledige versie heeft uitleg over OpenStreetMap
Als je niet aangemeld bent, wordt er je gevraagd dit te doen
Als je minstens één vraag hebt beantwoord, kan je punten gaan toevoegen.
Heb je genoeg changesets, dan verschijnen de tags die wat later doorlinken naar de wiki
Merk je een bug of wil je een extra feature? Wil je helpen vertalen? Bezoek dan de broncode en issue tracker
","de":"
Über MapComplete
MapComplete ist ein OpenStreetMap-Editor, der jedem helfen soll, auf einfache Weise Informationen zu einem Einzelthema hinzuzufügen.
Nur Merkmale, die für ein einzelnes Thema relevant sind, werden mit einigen vordefinierten Fragen gezeigt, um die Dinge einfach und extrem benutzerfreundlich zu halten.Der Themen-Betreuer kann auch eine Sprache für die Schnittstelle wählen, Elemente deaktivieren oder sogar in eine andere Website ohne jegliches UI-Element einbetten.
Ein weiterer wichtiger Teil von MapComplete ist jedoch, immer den nächsten Schritt anzubietenum mehr über OpenStreetMap zu erfahren:
Ein iframe ohne UI-Elemente verlinkt zu einer Vollbildversion
Die Vollbildversion bietet Informationen über OpenStreetMap
Wenn Sie nicht eingeloggt sind, werden Sie gebeten, sich einzuloggen
Wenn Sie eine einzige Frage beantwortet haben, dürfen Sie Punkte hinzufügen
An einem bestimmten Punkt erscheinen die tatsächlich hinzugefügten Tags, die später mit dem Wiki verlinkt werden...
Fällt Ihnen ein Problem mit MapComplete auf? Haben Sie einen Feature-Wunsch? Wollen Sie beim Übersetzen helfen? Gehen Sie zum Quellcode oder zur Problemverfolgung.
"} ),
+ aboutMapcomplete: new Translation( {"en":"
About MapComplete
MapComplete is an OpenStreetMap editor that is meant to help everyone to easily add information on a single theme.
Only features relevant to a single theme are shown with a few predefined questions, in order to keep things simple and extremly user-friendly.The theme maintainer can also choose a language for the interface, choose to disable elements or even to embed it into a different website without any UI-element at all.
However, another important part of MapComplete is to always offer the next step to learn more about OpenStreetMap:
An iframe without UI-elements will link to a full-screen version
The fullscreen version offers information about OpenStreetMap
If you're not logged in, you're asked to log in
If you answered a single question, you are allowed to add points
At a certain point, the actual added tags appear which later get linked to the wiki...
Do you notice an issue with MapComplete? Do you have a feature request? Do you want to help translating? Head over to the source code or issue tracker. Follow the edit count on OsmCha
","nl":"
Over MapComplete
MapComplete is een OpenStreetMap-editor om eenvoudig informatie toe te voegen over één enkel onderwerp.
Om de editor zo simpel en gebruiksvriendelijk mogelijk te houden, worden enkel objecten relevant voor het thema getoond.Voor deze objecten kunnen dan vragen beantwoord worden, of men kan een nieuw punt van dit thema toevoegen.De maker van het thema kan er ook voor opteren om een aantal elementen van de gebruikersinterface uit te schakelen of de taal ervan in te stellen.
Een ander belangrijk aspect is om bezoekers stap voor stap meer te leren over OpenStreetMap:
Een iframe zonder verdere uitleg linkt naar de volledige versie van MapComplete
De volledige versie heeft uitleg over OpenStreetMap
Als je niet aangemeld bent, wordt er je gevraagd dit te doen
Als je minstens één vraag hebt beantwoord, kan je punten gaan toevoegen.
Heb je genoeg changesets, dan verschijnen de tags die wat later doorlinken naar de wiki
Merk je een bug of wil je een extra feature? Wil je helpen vertalen? Bezoek dan de broncode en issue tracker. Volg de edits op OsmCha
","de":"
Über MapComplete
MapComplete ist ein OpenStreetMap-Editor, der jedem helfen soll, auf einfache Weise Informationen zu einem Einzelthema hinzuzufügen.
Nur Merkmale, die für ein einzelnes Thema relevant sind, werden mit einigen vordefinierten Fragen gezeigt, um die Dinge einfach und extrem benutzerfreundlich zu halten.Der Themen-Betreuer kann auch eine Sprache für die Schnittstelle wählen, Elemente deaktivieren oder sogar in eine andere Website ohne jegliches UI-Element einbetten.
Ein weiterer wichtiger Teil von MapComplete ist jedoch, immer den nächsten Schritt anzubietenum mehr über OpenStreetMap zu erfahren:
Ein iframe ohne UI-Elemente verlinkt zu einer Vollbildversion
Die Vollbildversion bietet Informationen über OpenStreetMap
Wenn Sie nicht eingeloggt sind, werden Sie gebeten, sich einzuloggen
Wenn Sie eine einzige Frage beantwortet haben, dürfen Sie Punkte hinzufügen
An einem bestimmten Punkt erscheinen die tatsächlich hinzugefügten Tags, die später mit dem Wiki verlinkt werden...
Fällt Ihnen ein Problem mit MapComplete auf? Haben Sie einen Feature-Wunsch? Wollen Sie beim Übersetzen helfen? Gehen Sie zum Quellcode oder zur Problemverfolgung.
"} ),
backgroundMap: new Translation( {"en":"Background map","ca":"Mapa de fons","es":"Mapa de fondo","nl":"Achtergrondkaart","de":"Hintergrundkarte"} ),
zoomInToSeeThisLayer: new Translation( {"en":"Zoom in to see this layer","ca":"Amplia per veure aquesta capa","es":"Amplía para ver esta capa","nl":"Vergroot de kaart om deze laag te zien","de":"Vergrößern, um diese Ebene zu sehen"} ),
weekdays: { abbreviations: { monday: new Translation( {"en":"Mon","ca":"Dil","es":"Lun","nl":"Maan","fr":"Lun"} ),
diff --git a/Customizations/JSON/LayerConfig.ts b/Customizations/JSON/LayerConfig.ts
index 6e14be6a33..61bd898631 100644
--- a/Customizations/JSON/LayerConfig.ts
+++ b/Customizations/JSON/LayerConfig.ts
@@ -100,7 +100,7 @@ export default class LayerConfig {
}
this.tagRenderings = trs(json.tagRenderings).concat(roamingRenderings);
- this.titleIcons = trs(json.titleIcons ?? ["wikipedialink","osmlink"]);
+ this.titleIcons = trs(json.titleIcons ?? ["phonelink","wikipedialink","osmlink", "sharelink"]);
function tr(key, deflt) {
diff --git a/Customizations/JSON/LayerConfigJson.ts b/Customizations/JSON/LayerConfigJson.ts
index caa19d5e3a..8e901c9994 100644
--- a/Customizations/JSON/LayerConfigJson.ts
+++ b/Customizations/JSON/LayerConfigJson.ts
@@ -121,6 +121,12 @@ export interface LayerConfigJson {
/**
* All the tag renderings.
* A tag rendering is a block that either shows the known value or asks a question.
+ *
+ * Refer to the class `TagRenderingConfigJson` to see the possibilities.
+ *
+ * Note that we can also use a string here - where the string refers to a tagrenering defined in `assets/questions/questions.json`,
+ * where a few very general questions are defined e.g. website, phone number, ...
+ *
*/
tagRenderings?: (string | TagRenderingConfigJson) []
}
\ No newline at end of file
diff --git a/Customizations/SharedLayers.ts b/Customizations/SharedLayers.ts
index 4beaa3ead5..7203faa066 100644
--- a/Customizations/SharedLayers.ts
+++ b/Customizations/SharedLayers.ts
@@ -15,6 +15,8 @@ import * as maps from "../assets/layers/maps/maps.json"
import * as information_boards from "../assets/layers/information_board/information_board.json"
import * as direction from "../assets/layers/direction/direction.json"
import * as surveillance_camera from "../assets/layers/surveillance_cameras/surveillance_cameras.json"
+import * as toilets from "../assets/layers/toilets/toilets.json"
+
import LayerConfig from "./JSON/LayerConfig";
export default class SharedLayers {
@@ -41,6 +43,7 @@ export default class SharedLayers {
new LayerConfig(maps,[], "shared_layers"),
new LayerConfig(direction,[], "shared_layers"),
new LayerConfig(information_boards,[], "shared_layers"),
+ new LayerConfig(toilets,[], "shared_layers"),
new LayerConfig(surveillance_camera,[], "shared_layers")
];
diff --git a/Customizations/SharedTagRenderings.ts b/Customizations/SharedTagRenderings.ts
index 9cd62eeed3..1b5c2812b8 100644
--- a/Customizations/SharedTagRenderings.ts
+++ b/Customizations/SharedTagRenderings.ts
@@ -1,5 +1,6 @@
-import * as questions from "../assets/questions/questions.json";
import TagRenderingConfig from "./JSON/TagRenderingConfig";
+import * as questions from "../assets/tagRenderings/questions.json";
+import * as icons from "../assets/tagRenderings/icons.json";
export default class SharedTagRenderings {
@@ -7,13 +8,24 @@ export default class SharedTagRenderings {
private static generatedSharedFields() {
const dict = {}
- for (const key in questions) {
+
+
+ function add(key, store){
try {
- dict[key] = new TagRenderingConfig(questions[key])
+ dict[key] = new TagRenderingConfig(store[key])
} catch (e) {
- console.error("COULD NOT PARSE", key, " FROM QUESTIONS:", e)
+ console.error("BUG: could not parse", key, " from questions.json or icons.json", e)
}
}
+
+
+ for (const key in questions) {
+ add(key, questions);
+ }
+ for (const key in icons) {
+ add(key, icons);
+ }
+
return dict;
}
diff --git a/InitUiElements.ts b/InitUiElements.ts
index d7438f3bcb..95d13802ac 100644
--- a/InitUiElements.ts
+++ b/InitUiElements.ts
@@ -85,6 +85,11 @@ export class InitUiElements {
throw "Incorrect layout"
}
+ const hashContent = QueryParameters.GetQueryParameter("hash_content", "", "A workaround for the share-api which doesn't share the hash...");
+ if((hashContent.data ?? "") !== ""){
+ window.location.hash = hashContent.data;
+ }
+
console.log("Using layout: ", layoutToUse.id, "LayoutFromBase64 is ", layoutFromBase64);
State.state = new State(layoutToUse);
@@ -161,7 +166,7 @@ export class InitUiElements {
if (feature === undefined) {
State.state.fullScreenMessage.setData(undefined);
}
- if (feature?.properties === undefined) {
+ if (feature?.properties === undefined) {
return;
}
const data = feature.properties;
@@ -175,7 +180,7 @@ export class InitUiElements {
continue;
}
- if(layer.title === null && layer.tagRenderings.length === 0){
+ if((layer.title ?? null) === null && layer.tagRenderings.length === 0){
continue;
}
@@ -230,7 +235,6 @@ export class InitUiElements {
});
const marker = L.marker([home.lat, home.lon], {icon: icon})
marker.addTo(State.state.bm.map)
- console.log(marker)
});
new GeoLocationHandler()
@@ -300,7 +304,7 @@ export class InitUiElements {
]
if (State.state.featureSwitchShareScreen.data) {
- tabs.push({header: Svg.share, content: new ShareScreen()});
+ tabs.push({header: Svg.share_img, content: new ShareScreen()});
}
if (State.state.featureSwitchMoreQuests.data) {
diff --git a/Logic/FilteredLayer.ts b/Logic/FilteredLayer.ts
index c978185cd7..a9f2302c51 100644
--- a/Logic/FilteredLayer.ts
+++ b/Logic/FilteredLayer.ts
@@ -184,7 +184,9 @@ export class FilteredLayer {
if (feature.properties.id.replace(/\//g, "_") === Hash.Get().data) {
const center = GeoOperations.centerpoint(feature).geometry.coordinates;
popup.setLatLng({lat: center[1], lng: center[0]});
- popup.openOn(State.state.bm.map)
+ popup.openOn(State.state.bm.map);
+ State.state.selectedElement.setData(feature);
+ uiElement.Update();
}
}
diff --git a/Logic/Leaflet/GeoLocationHandler.ts b/Logic/Leaflet/GeoLocationHandler.ts
index a668a5cdd3..d91b2bdcbb 100644
--- a/Logic/Leaflet/GeoLocationHandler.ts
+++ b/Logic/Leaflet/GeoLocationHandler.ts
@@ -33,14 +33,10 @@ export class GeoLocationHandler extends UIElement {
function onAccuratePositionProgress(e) {
- console.log(e.accuracy);
- console.log(e.latlng);
State.state.currentGPSLocation.setData({latlng: e.latlng, accuracy: e.accuracy});
}
function onAccuratePositionFound(e) {
- console.log(e.accuracy);
- console.log(e.latlng);
State.state.currentGPSLocation.setData({latlng: e.latlng, accuracy: e.accuracy});
}
diff --git a/README.md b/README.md
index f5393a60c5..8e2f015cae 100644
--- a/README.md
+++ b/README.md
@@ -260,3 +260,6 @@ Shower icon (used in 'bike_cleaning.svg'):
https://commons.wikimedia.org/wiki/File:Shower_symbol.svg
Bench icons from StreetComplete: https://github.com/westnordost/StreetComplete/tree/v25.0-beta1/res/graphics/quest%20icons, GPLv3.0
+
+
+Urinal icon: https://thenounproject.com/term/urinal/1307984/
\ No newline at end of file
diff --git a/State.ts b/State.ts
index ec61047be2..235227ac11 100644
--- a/State.ts
+++ b/State.ts
@@ -23,7 +23,7 @@ export default class State {
// The singleton of the global state
public static state: State;
- public static vNumber = "0.2.0";
+ public static vNumber = "0.2.2a";
// The user journey states thresholds when a new feature gets unlocked
public static userJourney = {
diff --git a/Svg.ts b/Svg.ts
index fbcbcdda20..1af54286c6 100644
--- a/Svg.ts
+++ b/Svg.ts
@@ -14,7 +14,7 @@ export default class Svg {
public static addSmall_svg() { return new FixedUiElement(Svg.addSmall);}
public static addSmall_ui() { return new FixedUiElement(Svg.addSmall_img);}
- public static ampersand = "e "
+ public static ampersand = " "
public static ampersand_img = Img.AsImageElement(Svg.ampersand)
public static ampersand_svg() { return new FixedUiElement(Svg.ampersand);}
public static ampersand_ui() { return new FixedUiElement(Svg.ampersand_img);}
@@ -174,6 +174,11 @@ export default class Svg {
public static pencil_svg() { return new FixedUiElement(Svg.pencil);}
public static pencil_ui() { return new FixedUiElement(Svg.pencil_img);}
+ public static phone = " "
+ public static phone_img = Img.AsImageElement(Svg.phone)
+ public static phone_svg() { return new FixedUiElement(Svg.phone);}
+ public static phone_ui() { return new FixedUiElement(Svg.phone_img);}
+
public static pop_out = " "
public static pop_out_img = Img.AsImageElement(Svg.pop_out)
public static pop_out_svg() { return new FixedUiElement(Svg.pop_out);}
@@ -189,7 +194,7 @@ export default class Svg {
public static search_svg() { return new FixedUiElement(Svg.search);}
public static search_ui() { return new FixedUiElement(Svg.search_img);}
- public static share = " "
+ public static share = " "
public static share_img = Img.AsImageElement(Svg.share)
public static share_svg() { return new FixedUiElement(Svg.share);}
public static share_ui() { return new FixedUiElement(Svg.share_img);}
@@ -219,4 +224,4 @@ export default class Svg {
public static wikipedia_svg() { return new FixedUiElement(Svg.wikipedia);}
public static wikipedia_ui() { return new FixedUiElement(Svg.wikipedia_img);}
-public static All = {"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"close.svg": Svg.close,"compass.svg": Svg.compass,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapillary.svg": Svg.mapillary,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"search.svg": Svg.search,"share.svg": Svg.share,"star.svg": Svg.star,"statistics.svg": Svg.statistics,"up.svg": Svg.up,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}
+public static All = {"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"close.svg": Svg.close,"compass.svg": Svg.compass,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapillary.svg": Svg.mapillary,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"search.svg": Svg.search,"share.svg": Svg.share,"star.svg": Svg.star,"statistics.svg": Svg.statistics,"up.svg": Svg.up,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};}
diff --git a/UI/FullScreenMessageBoxHandler.ts b/UI/FullScreenMessageBoxHandler.ts
index 412d65a178..2451495787 100644
--- a/UI/FullScreenMessageBoxHandler.ts
+++ b/UI/FullScreenMessageBoxHandler.ts
@@ -16,26 +16,15 @@ export class FullScreenMessageBox extends UIElement {
this.HideOnEmpty(true);
this.returnToTheMap =
- new Combine([Translations.t.general.returnToTheMap.Clone().SetStyle("font-size:xx-large")])
- .SetStyle("background:var(--catch-detail-color);" +
- "position: fixed;" +
- "z-index: 10000;" +
- "bottom: 0;" +
- "left: 0;" +
- `height: var(--return-to-the-map-height);` +
- "width: 100vw;" +
- "color: var(--catch-detail-color-contrast);" +
- "font-weight: bold;" +
- "pointer-events: all;" +
- "cursor: pointer;" +
- "padding-top: 1.2em;" +
- "text-align: center;" +
- "padding-bottom: 1.2em;" +
- "box-sizing:border-box")
- .onClick(() => {
- State.state.fullScreenMessage.setData(undefined);
- onClear();
- });
+ new Combine([
+ // Wrapped another time to prevent the value of 'em' to fluctuate
+ Translations.t.general.returnToTheMap.Clone()
+ ])
+ .onClick(() => {
+ State.state.fullScreenMessage.setData(undefined);
+ onClear();
+ })
+ .SetClass("to-the-map")
}
@@ -45,25 +34,18 @@ export class FullScreenMessageBox extends UIElement {
return "";
}
this._content = State.state.fullScreenMessage.data;
- const innerWrap = new Combine([this._content]).SetStyle(
- "display: block;" +
- "padding: 1em;" +
- "padding-bottom: 6em; "
- );
- const uielement = new Combine([innerWrap]).SetStyle(
- "display:block;" +
- `margin-bottom: var(--return-to-the-map-height);` +
- "box-sizing:border-box;" +
- `height:calc(100vh - var(--return-to-the-map-height));` +
- "overflow-y: auto;" +
- "max-width:100vw;" +
- "overflow-x:hidden;" +
- "background:var(--background-color);" +
- "color: var(--foreground-color);"
- );
- return new Combine([uielement, this.returnToTheMap])
+ const innerWrap = new Combine([this._content]).SetClass("fullscreenmessage-content")
+
+ return new Combine([innerWrap, this.returnToTheMap])
+ .SetStyle("display:block; height: 100%;")
.Render();
}
+ protected InnerUpdate(htmlElement: HTMLElement) {
+ super.InnerUpdate(htmlElement);
+ const height = htmlElement.getElementsByClassName("featureinfobox-titlebar")[0]?.clientHeight ?? 0;
+ htmlElement.style.setProperty("--variable-title-height", height+"px")
+ }
+
}
\ No newline at end of file
diff --git a/UI/Popup/EditableTagRendering.ts b/UI/Popup/EditableTagRendering.ts
index ea61c89260..0481eef241 100644
--- a/UI/Popup/EditableTagRendering.ts
+++ b/UI/Popup/EditableTagRendering.ts
@@ -33,7 +33,7 @@ export default class EditableTagRendering extends UIElement {
this.dumbMode = false;
if (this._configuration.question !== undefined) {
- if (State.state.featureSwitchUserbadge.data) {
+ if (State.state?.featureSwitchUserbadge?.data) {
// 2.3em total width
const self = this;
this._editButton =
diff --git a/UI/Popup/FeatureInfoBox.ts b/UI/Popup/FeatureInfoBox.ts
index 9a669dcf99..a6436277b9 100644
--- a/UI/Popup/FeatureInfoBox.ts
+++ b/UI/Popup/FeatureInfoBox.ts
@@ -44,9 +44,14 @@ export class FeatureInfoBox extends UIElement {
return new Combine([
new Combine([this._title, this._titleIcons])
.SetClass("featureinfobox-titlebar"),
- ...this._renderings,
- this._questionBox,
- ]).Render();
+ new Combine([
+ ...this._renderings,
+ this._questionBox
+ ]
+ ).SetClass("featureinfobox-content"),
+ ]).SetClass("featureinfobox")
+ .Render();
}
+
}
diff --git a/UI/ShareButton.ts b/UI/ShareButton.ts
new file mode 100644
index 0000000000..a94c55da0d
--- /dev/null
+++ b/UI/ShareButton.ts
@@ -0,0 +1,41 @@
+import {UIElement} from "./UIElement";
+
+export default class ShareButton extends UIElement{
+ private _embedded: UIElement;
+ private _shareData: { text: string; title: string; url: string };
+
+ constructor(embedded: UIElement, shareData: {
+ text: string,
+ title: string,
+ url: string
+ }) {
+ super();
+ this._embedded = embedded;
+ this._shareData = shareData;
+ if(this._shareData.url.indexOf("#")> 0){
+ this._shareData.url = this._shareData.url.replace("#","&hash_content=");
+ }
+ }
+
+ InnerRender(): string {
+ return ``
+ }
+
+ protected InnerUpdate(htmlElement: HTMLElement) {
+ super.InnerUpdate(htmlElement);
+ const self= this;
+ htmlElement.addEventListener('click', () => {
+ if (navigator.share) {
+ navigator.share(self._shareData).then(() => {
+ console.log('Thanks for sharing!');
+ })
+ .catch(err => {
+ console.log(`Couldn't share because of`, err.message);
+ });
+ } else {
+ console.log('web share not supported');
+ }
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/UI/SpecialVisualizations.ts b/UI/SpecialVisualizations.ts
index a20a1bfe2d..0afad7be6e 100644
--- a/UI/SpecialVisualizations.ts
+++ b/UI/SpecialVisualizations.ts
@@ -9,6 +9,9 @@ import {FixedUiElement} from "./Base/FixedUiElement";
import Locale from "../UI/i18n/Locale";
import {ImageUploadFlow} from "./Image/ImageUploadFlow";
import {Translation} from "./i18n/Translation";
+import State from "../State";
+import ShareButton from "./ShareButton";
+import Svg from "../Svg";
export class SubstitutedTranslation extends UIElement {
private readonly tags: UIEventSource;
@@ -183,7 +186,36 @@ export default class SpecialVisualizations {
return new VariableUiElement(source.map(data => data[neededValue] ?? "Loading..."));
}
},
+ {
+ funcName: "share_link",
+ docs: "Creates a link that (attempts to) open the native 'share'-screen",
+ example: "{share_link()} to share the current page, {share_link()} to share the given url",
+ args: [
+ {
+ name: "url",
+ doc: "The url to share (defualt: current URL)",
+ }
+ ],
+ constr: (tagSource: UIEventSource, args) => {
+ if (window.navigator.share) {
+ const title = State.state.layoutToUse.data.title.txt;
+ let name = tagSource.data.name;
+ if(name){
+ name = `${name} (${title})`
+ }else{
+ name = title;
+ }
+ return new ShareButton(Svg.share_svg(), {
+ title: name,
+ url: args[0] ?? window.location.href,
+ text: State.state.layoutToUse.data.shortDescription.txt
+ })
+ } else {
+ return new FixedUiElement("")
+ }
+ }
+ }
]
static HelpMessage: UIElement = SpecialVisualizations.GenHelpMessage();
diff --git a/UI/WelcomeMessage.ts b/UI/WelcomeMessage.ts
index 4179285f53..2afce3f532 100644
--- a/UI/WelcomeMessage.ts
+++ b/UI/WelcomeMessage.ts
@@ -53,9 +53,10 @@ export class WelcomeMessage extends UIElement {
loginStatus,
this.tail,
" ",
- this.languagePicker
+ this.languagePicker,
+ Translations.t.general.customIntro as UIElement
]).Render()
}
-}
\ No newline at end of file
+}
diff --git a/assets/layers/bike_repair_station/bike_repair_station.json b/assets/layers/bike_repair_station/bike_repair_station.json
index 4089160f4b..daa1e3dc86 100644
--- a/assets/layers/bike_repair_station/bike_repair_station.json
+++ b/assets/layers/bike_repair_station/bike_repair_station.json
@@ -89,6 +89,14 @@
}
]
},
+ "titleIcons": [
+ {
+ "render": "",
+ "condition": "operator=De Fietsambassade Gent"
+ },
+ "wikipedialink",
+ "osmlink"
+ ],
"tagRenderings": [
"images",
{
diff --git a/assets/layers/bike_shop/bike_shop.json b/assets/layers/bike_shop/bike_shop.json
index 613e5a693a..3d1d6c988f 100644
--- a/assets/layers/bike_shop/bike_shop.json
+++ b/assets/layers/bike_shop/bike_shop.json
@@ -12,6 +12,13 @@
"#": "We select all bicycle shops, sport shops (but we try to weed out non-bicycle related shops), and any shop with a bicycle related tag",
"or": [
"shop=bicycle",
+ {
+ "#": "A bicycle rental with a network is something such as villo, bluebike, ... We don't want them",
+ "and": [
+ "amenity=bicycle_rental",
+ "network="
+ ]
+ },
{
"#": "if sport is defined and is not bicycle, it is retrackted; if bicycle retail/repair is marked as 'no', it is retracted too.",
"##": "There will be a few false-positives with this. They will get filtered out by people marking both 'not selling bikes' and 'not repairing bikes'. Furthermore, the OSMers will add a sports-subcategory on it",
@@ -68,7 +75,12 @@
}
},
{
- "if": "shop!~bicycle",
+ "if": {
+ "and": [
+ "shop!~bicycle",
+ "shop~*"
+ ]
+ },
"then": "Other shop"
},
{
@@ -127,6 +139,23 @@
"de": "Fahrradgeschäft"
}
},
+ {
+ "if": {
+ "and": [
+ "name~*",
+ {
+ "or": [
+ "service:bicycle:rental=yes",
+ "amenity=bicycle_rental"
+ ]
+ }
+ ]
+ },
+ "then": {
+ "nl": "Fietsverhuur {name}",
+ "en": "Bicycle rental {name}"
+ }
+ },
{
"if": "name~*",
"then": {
@@ -141,37 +170,35 @@
},
"titleIcons": [
{
- "mappings": [
- {
- "if": "service:bicycle:pump=yes",
- "then": ""
- }
- ]
+ "render": "",
+ "condition": "operator=De Fietsambassade Gent"
},
{
- "mappings": [
- {
- "if": "service:bicycle:diy=yes",
- "then": ""
- }
- ]
+ "condition": {
+ "or": [
+ "service:bicycle:pump=yes",
+ "service:bicycle:pump=seperate"
+ ]
+ },
+ "render": ""
},
{
- "mappings": [
- {
- "if": {
- "or": [
- "service:bicycle:cleaning=yes",
- "service:bicycle:cleaning=diy"
- ]
- },
- "then": ""
- }
- ]
+ "condition": "service:bicycle:diy=yes",
+ "render": ""
},
+ {
+ "condition": {
+ "or": [
+ "service:bicycle:cleaning=yes",
+ "service:bicycle:cleaning=diy"
+ ]
+ },
+ "render": ""
+ },
+ "phonelink",
"wikipedialink",
- "osmlink"
-
+ "osmlink",
+ "sharelink"
],
"description": {
"en": "A shop specifically selling bicycles or related items",
@@ -182,6 +209,7 @@
{
"condition": {
"and": [
+ "shop~*",
"shop!~bicycle",
"shop!~sports"
]
@@ -257,6 +285,13 @@
"type": "opening_hours"
}
},
+ "description",
+ {
+ "render": "Enkel voor {access}",
+ "freeform": {
+ "key": "access"
+ }
+ },
{
"question": {
"en": "Does this shop sell bikes?",
@@ -439,6 +474,13 @@
"gl": "Esta tenda non ofrece unha bomba de ar para uso de calquera persoa",
"de": "Dieses Geschäft bietet für niemanden eine Fahrradpumpe an"
}
+ },
+ {
+ "if": "service:bicycle:pump=seperate",
+ "then": {
+ "en": "There is bicycle pump, it is shown as a seperate point ",
+ "nl": "Er is een fietspomp, deze is apart aangeduid"
+ }
}
]
},
@@ -470,6 +512,13 @@
"gl": "Non hai ferramentas aquí para arranxar a túa propia bicicleta",
"de": "Dieses Geschäft bietet keine Werkzeuge für Heimwerkerreparaturen an"
}
+ },
+ {
+ "if": "service:bicycle:diy=only_sold",
+ "then": {
+ "en": "Tools for DIY repair are only available if you bought/hire the bike in the shop",
+ "nl": "Het gereedschap aan om je fiets zelf te herstellen is enkel voor als je de fiets er kocht of huurt"
+ }
}
]
},
@@ -521,6 +570,10 @@
"icon": {
"render": "./assets/layers/bike_shop/repair_shop.svg",
"mappings": [
+ {
+ "if": "operator=De Fietsambassade Gent",
+ "then": "./assets/themes/cyclofix/fietsambassade_gent_logo_small.svg"
+ },
{
"if": "service:bicycle:retail=yes",
"then": "./assets/layers/bike_shop/shop.svg"
diff --git a/assets/layers/bike_shop/repair_station.svg b/assets/layers/bike_shop/tools.svg
similarity index 100%
rename from assets/layers/bike_shop/repair_station.svg
rename to assets/layers/bike_shop/tools.svg
diff --git a/assets/layers/cycling_themed_object/cycling_themed_objects.json b/assets/layers/cycling_themed_object/cycling_themed_objects.json
index 2f4be6eab1..7e57106d70 100644
--- a/assets/layers/cycling_themed_object/cycling_themed_objects.json
+++ b/assets/layers/cycling_themed_object/cycling_themed_objects.json
@@ -7,7 +7,7 @@
"de": "Mit Fahrrad zusammenhängendes Objekt"
},
"minzoom": 13,
- "overpassTags": "theme~cycling|bicycle",
+ "overpassTags": {"or": ["theme~cycling|bicycle", "sport=cycling"]},
"title": {
"render": {
"en": "Bike related object",
@@ -18,12 +18,13 @@
"mappings": [
{
"if": "name~*",
+ "then":"{name}"
+ },
+ {
+ "if": "leisure=track",
"then": {
- "en": "{name}",
- "nl": "{name}",
- "fr": "{name}",
- "gl": "{name}",
- "de": "{name}"
+ "nl": "Wielerpiste",
+ "en": "Cycle track"
}
}
]
diff --git a/assets/layers/toilets/toilets.json b/assets/layers/toilets/toilets.json
new file mode 100644
index 0000000000..7770573d69
--- /dev/null
+++ b/assets/layers/toilets/toilets.json
@@ -0,0 +1,305 @@
+{
+ "id": "toilets",
+ "name": {
+ "en": "Toilets",
+ "de": "Toiletten",
+ "fr": "Toilettes"
+ },
+ "overpassTags": "amenity=toilets",
+ "title": {
+ "render": {
+ "en": "Toilet",
+ "de": "Toilette",
+ "fr": "Toilettes"
+ }
+ },
+ "icon": {
+ "render": "./assets/layers/toilets/toilets.svg",
+ "mappings": [
+ {
+ "if": "wheelchair=yes",
+ "then": "./assets/layers/toilets/wheelchair.svg"
+ },
+ {
+ "if": "toilets:position=urinals",
+ "then": "./assets/layers/toilets/urinal.svg"
+ }
+ ]
+ },
+ "color": {
+ "render": "#0000ff"
+ },
+ "minzoom": 12,
+ "wayHandling": 2,
+ "presets": [
+ {
+ "title": {
+ "en": "Toilet",
+ "de": "Toilette",
+ "fr": "Toilettes"
+ },
+ "tags": [
+ "amenity=toilets"
+ ],
+ "description": {
+ "en": "A publicly accessible toilet or restroom",
+ "de": "Eine öffentlich zugängliche Toilette",
+ "fr": "Des toilettes"
+ }
+ },
+ {
+ "title": {
+ "en": "Toilets with wheelchair accessible toilet",
+ "de": "Toiletten mit rollstuhlgerechter Toilette",
+ "fr": "Toilettes accessible aux personnes à mobilité réduite"
+ },
+ "tags": [
+ "amenity=toilets",
+ "wheelchair=yes"
+ ],
+ "description": {
+ "en": "A restroom which has at least one wheelchair-accessible toilet",
+ "de": "Eine Toilettenanlage mit mindestens einer rollstuhlgerechten Toilette",
+ "fr": "Toilettes avec au moins un WC accessible aux personnes à mobilité réduite"
+ }
+ }
+ ],
+ "tagRenderings": [
+ "images",
+ {
+ "question": {
+ "en": "Are these toilets publicly accessible?",
+ "de": "Sind diese Toiletten öffentlich zugänglich?",
+ "fr": "Ces toilettes sont-elles accessibles publiquement ?"
+ },
+ "render": {
+ "en": "Access is {access}",
+ "de": "Zugang ist {access}",
+ "fr": "L'accès est {access}"
+ },
+ "freeform": {
+ "key": "access",
+ "addExtraTags": [
+ "fixme=the tag access was filled out by the user and might need refinement"
+ ]
+ },
+ "mappings": [
+ {
+ "if": "access=yes",
+ "then": {
+ "en": "Public access",
+ "de": "Öffentlicher Zugang",
+ "fr": "Accès publique"
+ }
+ },
+ {
+ "if": "access=customers",
+ "then": {
+ "en": "Only access to customers",
+ "de": "Nur Zugang für Kunden",
+ "fr": "Accès réservé aux clients"
+ }
+ },
+ {
+ "if": "access=no",
+ "then": {
+ "en": "Not accessible",
+ "de": "Nicht zugänglich",
+ "fr": "WC privés"
+ }
+ },
+ {
+ "if": "access=key",
+ "then": {
+ "en": "Accessible, but one has to ask a key to enter",
+ "de": "Zugänglich, aber man muss einen Schlüssel für die Eingabe verlangen",
+ "fr": "Accessible, mais vous devez demander la clé"
+ }
+ }
+ ]
+ },
+ {
+ "question": {
+ "en": "Are these toilets free to use?",
+ "de": "Können diese Toiletten kostenlos benutzt werden?",
+ "fr": "Ces toilettes sont-elles payantes"
+ },
+ "mappings": [
+ {
+ "then": {
+ "en": "These are paid toilets",
+ "de": "Dies sind bezahlte Toiletten",
+ "fr": "Toilettes payantes"
+ },
+ "if": "fee=yes"
+ },
+ {
+ "if": "fee=no",
+ "then": {
+ "en": "Free to use",
+ "de": "Kostenlose Nutzung",
+ "fr": "Toilettes gratuites"
+ }
+ }
+ ]
+ },
+ {
+ "question": {
+ "en": "How much does one have to pay for these toilets?",
+ "de": "Wie viel muss man für diese Toiletten bezahlen?",
+ "fr": "Quel est le prix d'accès de ces toilettes ?"
+ },
+ "render": {
+ "en": "The fee is {charge}",
+ "de": "Die Gebühr beträgt {charge}",
+ "fr": "Le prix est {charge}"
+ },
+ "condition": "fee=yes",
+ "freeform": {
+ "key": "charge",
+ "type": "string"
+ }
+ },
+ {
+ "question": {
+ "en": "Is there a dedicated toilet for wheelchair users",
+ "de": "Gibt es eine Toilette für Rollstuhlfahrer?",
+ "fr": "Un WC réservé aux personnes à mobilité réduite est-il présent ?"
+ },
+ "mappings": [
+ {
+ "then": {
+ "en": "There is a dedicated toilet for wheelchair users",
+ "de": "Es gibt eine Toilette für Rollstuhlfahrer",
+ "fr": "Il y a un WC réservé pour les personnes à mobilité réduite"
+ },
+ "if": "wheelchair=yes"
+ },
+ {
+ "if": "wheelchair=no",
+ "then": {
+ "en": "No wheelchair access",
+ "de": "Kein Zugang für Rollstuhlfahrer",
+ "fr": "Non accessible aux personnes à mobilité réduite"
+ }
+ }
+ ]
+ },
+ {
+ "question": {
+ "en": "Which kind of toilets are this?",
+ "de": "Welche Art von Toiletten sind das?",
+ "fr": "De quel type sont ces toilettes ?"
+ },
+ "mappings": [
+ {
+ "if": "toilets:position=seated",
+ "then": {
+ "en": "There are only seated toilets",
+ "de": "Es gibt nur Sitztoiletten",
+ "fr": "Il y a uniquement des WC assis"
+ }
+ },
+ {
+ "if": "toilets:position=urinals",
+ "then": {
+ "en": "There are only urinals here",
+ "de": "Hier gibt es nur Pissoirs",
+ "fr": "Il y a uniquement des urinoirs"
+ }
+ },
+ {
+ "if": "toilets:position=squat",
+ "then": {
+ "en": "There are only squat toilets here",
+ "de": "Es gibt hier nur Hocktoiletten.",
+ "fr": "Il y a uniquement des WC turques"
+ }
+ },
+ {
+ "if": "toilets:position=seated;urinals",
+ "then": {
+ "en": "Both seated toilets and urinals are available here",
+ "de": "Sowohl Sitztoiletten als auch Pissoirs sind hier verfügbar",
+ "fr": "Il y a des WC assis et des urinoirs"
+ }
+ }
+ ]
+ },
+ {
+ "question": {
+ "en": "Is a changing table (to change diapers) available?",
+ "de": "Ist ein Wickeltisch (zum Wechseln der Windeln) vorhanden?",
+ "fr": "Ces WC disposent-ils d'une table à langer ?"
+ },
+ "mappings": [
+ {
+ "then": {
+ "en": "A changing table is available",
+ "de": "Ein Wickeltisch ist verfügbar",
+ "fr": "Une table à langer est disponible"
+ },
+ "if": "changing_table=yes"
+ },
+ {
+ "if": "changing_table=no",
+ "then": {
+ "en": "No changing table is available",
+ "de": "Es ist kein Wickeltisch verfügbar",
+ "fr": "Aucune table à langer"
+ }
+ }
+ ]
+ },
+ {
+ "question": {
+ "en": "Where is the changing table located?",
+ "de": "Wo befindet sich der Wickeltisch?",
+ "fr": "Où se situe la table à langer ?"
+ },
+ "render": {
+ "en": "The changing table is located at {changing_table:location}",
+ "de": "Die Wickeltabelle befindet sich in {changing_table:location}",
+ "fr": "Emplacement de la table à langer : {changing_table:location}"
+ },
+ "condition": "changing_table=yes",
+ "freeform": {
+ "key": "changing_table:location"
+ },
+ "mappings": [
+ {
+ "then": {
+ "en": "The changing table is in the toilet for women. ",
+ "de": "Der Wickeltisch befindet sich in der Damentoilette. ",
+ "fr": "La table à langer se situe dans les WC pour femmes. "
+ },
+ "if": "changing_table:location=female_toilet"
+ },
+ {
+ "then": {
+ "en": "The changing table is in the toilet for men. ",
+ "de": "Der Wickeltisch befindet sich in der Herrentoilette. ",
+ "fr": "La table à langer se situe dans les WC pour hommes. "
+ },
+ "if": "changing_table:location=male_toilet"
+ },
+ {
+ "if": "changing_table:location=wheelchair_toilet",
+ "then": {
+ "en": "The changing table is in the toilet for wheelchair users. ",
+ "de": "Der Wickeltisch befindet sich in der Toilette für Rollstuhlfahrer. ",
+ "fr": "La table à langer se situe dans les WC pour personnes à mobilité réduite. "
+ }
+ },
+ {
+ "if": "changing_table:location=dedicated_room",
+ "then": {
+ "en": "The changing table is in a dedicated room. ",
+ "de": "Der Wickeltisch befindet sich in einem eigenen Raum. ",
+ "fr": "La table à langer se situe dans un espace dédié. "
+ }
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/assets/layers/toilets/toilets.svg b/assets/layers/toilets/toilets.svg
new file mode 100644
index 0000000000..4af924c321
--- /dev/null
+++ b/assets/layers/toilets/toilets.svg
@@ -0,0 +1,82 @@
+
+
diff --git a/assets/layers/toilets/urinal.svg b/assets/layers/toilets/urinal.svg
new file mode 100644
index 0000000000..cecba0c476
--- /dev/null
+++ b/assets/layers/toilets/urinal.svg
@@ -0,0 +1,53 @@
+
+
diff --git a/assets/themes/toilets/wheelchair.svg b/assets/layers/toilets/wheelchair.svg
similarity index 100%
rename from assets/themes/toilets/wheelchair.svg
rename to assets/layers/toilets/wheelchair.svg
diff --git a/assets/svg/ampersand.svg b/assets/svg/ampersand.svg
index f2df861c43..525a1ef740 100644
--- a/assets/svg/ampersand.svg
+++ b/assets/svg/ampersand.svg
@@ -1,4 +1,4 @@
-e
+