chore: automated housekeeping...

This commit is contained in:
Pieter Vander Vennet 2024-08-14 13:53:56 +02:00
parent f77570589d
commit 9b8a9337fd
111 changed files with 2911 additions and 1280 deletions

View file

@ -61,7 +61,6 @@
- grave - grave
- guidepost - guidepost
- hackerspace - hackerspace
- hotel
- hydrant - hydrant
- ice_cream - ice_cream
- indoors - indoors
@ -112,6 +111,7 @@
- toilet - toilet
- toilet_at_amenity - toilet_at_amenity
- tool_library - tool_library
- tourism_accomodation
- trail - trail
- transit_stops - transit_stops
- tree_node - tree_node
@ -168,13 +168,13 @@
- food - food
- food_courts - food_courts
- hackerspace - hackerspace
- hotel
- ice_cream - ice_cream
- love_hotel - love_hotel
- pharmacy - pharmacy
- playground - playground
- shops - shops
- stripclub - stripclub
- tourism_accomodation
- veterinary - veterinary
### website ### website
@ -198,7 +198,6 @@
- food_courts - food_courts
- governments - governments
- hackerspace - hackerspace
- hotel
- kindergarten_childcare - kindergarten_childcare
- nature_reserve - nature_reserve
- observation_tower - observation_tower
@ -234,7 +233,6 @@
- food_courts - food_courts
- governments - governments
- hackerspace - hackerspace
- hotel
- kindergarten_childcare - kindergarten_childcare
- pharmacy - pharmacy
- physiotherapist - physiotherapist
@ -263,7 +261,6 @@
- food - food
- governments - governments
- hackerspace - hackerspace
- hotel
- kindergarten_childcare - kindergarten_childcare
- pharmacy - pharmacy
- physiotherapist - physiotherapist
@ -313,6 +310,7 @@
- love_hotel - love_hotel
- stripclub - stripclub
- tool_library - tool_library
- tourism_accomodation
### mastodon ### mastodon
@ -417,12 +415,12 @@
- food - food
- food_courts - food_courts
- hackerspace - hackerspace
- hotel
- ice_cream - ice_cream
- observation_tower - observation_tower
- outdoor_seating - outdoor_seating
- playground_equipment - playground_equipment
- sports_centre - sports_centre
- tourism_accomodation
- transit_stops - transit_stops
### smoking ### smoking
@ -441,13 +439,13 @@
- cafe_pub - cafe_pub
- food - food
- tourism_accomodation
### internet ### internet
- cafe_pub - cafe_pub
- climbing_gym - climbing_gym
- food - food
- hotel
- shops - shops
### internet-fee ### internet-fee
@ -455,7 +453,6 @@
- cafe_pub - cafe_pub
- climbing_gym - climbing_gym
- food - food
- hotel
- shops - shops
### internet-ssid ### internet-ssid
@ -463,7 +460,6 @@
- cafe_pub - cafe_pub
- climbing_gym - climbing_gym
- food - food
- hotel
- shops - shops
### questions ### questions
@ -596,6 +592,7 @@
- hackerspace - hackerspace
- outdoor_seating - outdoor_seating
- tourism_accomodation
### diets ### diets
@ -675,6 +672,14 @@
- toilet_at_amenity - toilet_at_amenity
### {preset_type_select()}
- tourism_accomodation
### brand
- tourism_accomodation
This document is autogenerated from [assets/layers/*.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/*.json) This document is autogenerated from [assets/layers/*.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/*.json)

View file

@ -74,6 +74,7 @@ This is a special layer - data is not sourced from OpenStreetMap
49. [seasonal](#seasonal) 49. [seasonal](#seasonal)
50. [shower](#shower) 50. [shower](#shower)
51. [preset_description](#preset_description) 51. [preset_description](#preset_description)
52. [brand](#brand)
## Supported attributes ## Supported attributes
@ -112,6 +113,7 @@ This is a special layer - data is not sourced from OpenStreetMap
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/diet:vegan#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/diet%3Avegan/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [diet:vegan](https://wiki.openstreetmap.org/wiki/Key:diet:vegan) | Multiple choice | [only](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Donly) [yes](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dno) | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/diet:vegan#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/diet%3Avegan/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [diet:vegan](https://wiki.openstreetmap.org/wiki/Key:diet:vegan) | Multiple choice | [only](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Donly) [yes](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:diet:vegan%3Dno) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/seasonal#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/seasonal/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [seasonal](https://wiki.openstreetmap.org/wiki/Key:seasonal) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:seasonal%3Dno) [summer](https://wiki.openstreetmap.org/wiki/Tag:seasonal%3Dsummer) [spring;summer;autumn](https://wiki.openstreetmap.org/wiki/Tag:seasonal%3Dspring;summer;autumn) | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/seasonal#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/seasonal/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [seasonal](https://wiki.openstreetmap.org/wiki/Key:seasonal) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:seasonal%3Dno) [summer](https://wiki.openstreetmap.org/wiki/Tag:seasonal%3Dsummer) [spring;summer;autumn](https://wiki.openstreetmap.org/wiki/Tag:seasonal%3Dspring;summer;autumn) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/shower#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/shower/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [shower](https://wiki.openstreetmap.org/wiki/Key:shower) | Multiple choice | [hot](https://wiki.openstreetmap.org/wiki/Tag:shower%3Dhot) [cold](https://wiki.openstreetmap.org/wiki/Tag:shower%3Dcold) [yes](https://wiki.openstreetmap.org/wiki/Tag:shower%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:shower%3Dno) | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/shower#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/shower/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [shower](https://wiki.openstreetmap.org/wiki/Key:shower) | Multiple choice | [hot](https://wiki.openstreetmap.org/wiki/Tag:shower%3Dhot) [cold](https://wiki.openstreetmap.org/wiki/Tag:shower%3Dcold) [yes](https://wiki.openstreetmap.org/wiki/Tag:shower%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:shower%3Dno) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/brand#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/brand/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [brand](https://wiki.openstreetmap.org/wiki/Key:brand) | [string](../SpecialInputElements.md#string) | |
@ -135,7 +137,7 @@ _This tagrendering has no question and is thus read-only_
### mapillary ### mapillary
Shows a button to open Mapillary on this location Shows a button to open Mapillary on this location
_This tagrendering has no question and is thus read-only_ _This tagrendering has no question and is thus read-only_
*{mapillary()}* *{mapillary_link()}*
@ -201,7 +203,7 @@ The question is `What is the Mastodon-handle of {title()}?`
### facebook ### facebook
Shows and asks for the facebook handle Shows and asks for the facebook handle
The question is `What is the facebook page of of {title()}?` The question is `What is the facebook page of of {title()}?`
*{link(Facebook page,&LBRACEcontact:facebook&RBRACE,,,)}<div class='subtle text-sm'>Facebook is known to harm mental health, manipulate public opinion and cause hate. Try to use healthier alternatives</div>* is shown if `contact:facebook` is set *{link(Facebook page,&LBRACEcontact:facebook&RBRACE,,,,)}<div class='subtle text-sm'>Facebook is known to harm mental health, manipulate public opinion and cause hate. Try to use healthier alternatives</div>* is shown if `contact:facebook` is set
@ -728,4 +730,16 @@ _This tagrendering has no question and is thus read-only_
### brand
The question is `Is {title()} part of a bigger brand?`
*Part of {brand}* is shown if `brand` is set
- *Not part of a bigger brand* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:nobrand' target='_blank'>nobrand</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:nobrand%3Dyes' target='_blank'>yes</a>
This document is autogenerated from [assets/layers/questions/questions.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/questions/questions.json) This document is autogenerated from [assets/layers/questions/questions.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/questions/questions.json)

View file

@ -147,7 +147,7 @@ This tagrendering has labels
### artwork-website ### artwork-website
The question is `Is there a website with more information about this artwork?` The question is `Is there a website with more information about this artwork?`
*{link(More information on this website,&LBRACEwebsite&RBRACE,,,)}* is shown if `website` is set *{link(More information on this website,&LBRACEwebsite&RBRACE,,,,)}* is shown if `website` is set
This tagrendering has labels This tagrendering has labels

View file

@ -0,0 +1,458 @@
[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources)
# artwork_on_wall
This layer is based on [artwork](../Layers/artwork.md)
An open map of statues, busts, graffitis and other artwork all over the world
- This layer is shown at zoomlevel **16** and higher
## Table of contents
1. [Themes using this layer](#themes-using-this-layer)
2. [Basic tags for this layer](#basic-tags-for-this-layer)
3. [Supported attributes](#supported-attributes)
- [historic_or_not](#historic_or_not)
- [images](#images)
- [artwork-artwork_type](#artwork-artwork_type)
- [artwork-artist-wikidata](#artwork-artist-wikidata)
- [artwork-artist_name](#artwork-artist_name)
- [artwork-website](#artwork-website)
- [wikipedia](#wikipedia)
- [artwork_subject](#artwork_subject)
- [doubles_as_memorial](#doubles_as_memorial)
- [memorial-type](#memorial-type)
- [inscription](#inscription)
- [doubles_as_bench](#doubles_as_bench)
- [bench-backrest](#bench-backrest)
- [bench-armrest](#bench-armrest)
- [bench-seats](#bench-seats)
- [bench-material](#bench-material)
- [bench-direction](#bench-direction)
- [bench-colour](#bench-colour)
- [bench-survey:date](#bench-surveydate)
- [bench-inscription](#bench-inscription)
- [bench-memorial](#bench-memorial)
- [leftover-questions](#leftover-questions)
- [move-button](#move-button)
- [delete-button](#delete-button)
- [lod](#lod)
4. [Filters](#filters)
## Themes using this layer
- [ghostsigns](https://mapcomplete.org/ghostsigns)
## Basic tags for this layer
Elements must match **all** of the following expressions:
0. <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dartwork' target='_blank'>artwork</a>
1. <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmural' target='_blank'>mural</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dgraffiti' target='_blank'>graffiti</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmosaic' target='_blank'>mosaic</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Drelief' target='_blank'>relief</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dpainting' target='_blank'>painting</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmural_painting' target='_blank'>mural_painting</a>
[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B%28%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22mural%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22graffiti%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22mosaic%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22relief%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22painting%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22mural_painting%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%29%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B)
## Supported attributes
**Warning:**,this quick overview is incomplete,
| attribute | type | values which are supported by this layer |
-----|-----|----- |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/historic#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/historic/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [historic](https://wiki.openstreetmap.org/wiki/Key:historic) | Multiple choice | [advertising](https://wiki.openstreetmap.org/wiki/Tag:historic%3Dadvertising) [](https://wiki.openstreetmap.org/wiki/Tag:historic%3D) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/artwork_type#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/artwork_type/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [artwork_type](https://wiki.openstreetmap.org/wiki/Key:artwork_type) | [string](../SpecialInputElements.md#string) | [architecture](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Darchitecture) [mural](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmural) [painting](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dpainting) [sculpture](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dsculpture) [statue](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dstatue) [bust](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dbust) [stone](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dstone) [installation](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dinstallation) [graffiti](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dgraffiti) [relief](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Drelief) [azulejo](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dazulejo) [tilework](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dtilework) [woodcarving](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dwoodcarving) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/artist:wikidata#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/artist%3Awikidata/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [artist:wikidata](https://wiki.openstreetmap.org/wiki/Key:artist:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/artist_name#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/artist_name/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [artist_name](https://wiki.openstreetmap.org/wiki/Key:artist_name) | [string](../SpecialInputElements.md#string) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/website#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/website/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/wikidata#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/wikidata/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [wikidata](https://wiki.openstreetmap.org/wiki/Key:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/subject:wikidata#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/subject%3Awikidata/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [subject:wikidata](https://wiki.openstreetmap.org/wiki/Key:subject:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/historic#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/historic/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [historic](https://wiki.openstreetmap.org/wiki/Key:historic) | Multiple choice | [memorial](https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial) [](https://wiki.openstreetmap.org/wiki/Tag:historic%3D) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/memorial#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/memorial/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [memorial](https://wiki.openstreetmap.org/wiki/Key:memorial) | [string](../SpecialInputElements.md#string) | [statue](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstatue) [plaque](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dplaque) [bench](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbench) [ghost_bike](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dghost_bike) [stolperstein](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstolperstein) [stele](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstele) [stone](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstone) [bust](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbust) [sculpture](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dsculpture) [obelisk](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dobelisk) [cross](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dcross) [blue_plaque](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dblue_plaque) [tank](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dtank) [tree](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dtree) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/inscription#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/inscription/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [text](../SpecialInputElements.md#text) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/amenity#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/amenity/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [bench](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench) [](https://wiki.openstreetmap.org/wiki/Tag:amenity%3D) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/backrest#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/backrest/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [backrest](https://wiki.openstreetmap.org/wiki/Key:backrest) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes) [yes](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dno) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/armrest#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/armrest/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [armrest](https://wiki.openstreetmap.org/wiki/Key:armrest) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:armrest%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:armrest%3Dno) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/seats#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/seats/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [seats](https://wiki.openstreetmap.org/wiki/Key:seats) | [nat](../SpecialInputElements.md#nat) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/material#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/material/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [material](https://wiki.openstreetmap.org/wiki/Key:material) | [string](../SpecialInputElements.md#string) | [wood](https://wiki.openstreetmap.org/wiki/Tag:material%3Dwood) [metal](https://wiki.openstreetmap.org/wiki/Tag:material%3Dmetal) [stone](https://wiki.openstreetmap.org/wiki/Tag:material%3Dstone) [concrete](https://wiki.openstreetmap.org/wiki/Tag:material%3Dconcrete) [plastic](https://wiki.openstreetmap.org/wiki/Tag:material%3Dplastic) [steel](https://wiki.openstreetmap.org/wiki/Tag:material%3Dsteel) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/direction#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/direction/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [direction](https://wiki.openstreetmap.org/wiki/Key:direction) | [direction](../SpecialInputElements.md#direction) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/colour#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/colour/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [colour](https://wiki.openstreetmap.org/wiki/Key:colour) | [color](../SpecialInputElements.md#color) | [brown](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dbrown) [green](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dgreen) [gray](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dgray) [white](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dwhite) [red](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dred) [black](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dblack) [blue](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dblue) [yellow](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dyellow) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/survey:date#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/survey%3Adate/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [survey:date](https://wiki.openstreetmap.org/wiki/Key:survey:date) | [date](../SpecialInputElements.md#date) | [](https://wiki.openstreetmap.org/wiki/Tag:survey:date%3D) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/inscription#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/inscription/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [text](../SpecialInputElements.md#text) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/historic#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/historic/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [historic](https://wiki.openstreetmap.org/wiki/Key:historic) | Multiple choice | [memorial](https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial) [](https://wiki.openstreetmap.org/wiki/Tag:historic%3D) |
### historic_or_not
The question is `Is this artwork a historic advertisement?`
- *This artwork is a historic advertisement* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dadvertising' target='_blank'>advertising</a>
- *This artwork is not a historic advertisement* is shown if with historic=
### images
This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` and shows the button to upload new images
_This tagrendering has no question and is thus read-only_
*{image_carousel()}{image_upload()}*
### artwork-artwork_type
The question is `What is the type of this artwork?`
*This is a {artwork_type}* is shown if `artwork_type` is set
- *Architecture* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Darchitecture' target='_blank'>architecture</a>
- *Mural* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmural' target='_blank'>mural</a>
- *Painting* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dpainting' target='_blank'>painting</a>
- *Sculpture* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dsculpture' target='_blank'>sculpture</a>
- *Statue* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dstatue' target='_blank'>statue</a>
- *Bust* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dbust' target='_blank'>bust</a>
- *Stone* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dstone' target='_blank'>stone</a>
- *Installation* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dinstallation' target='_blank'>installation</a>
- *Graffiti* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dgraffiti' target='_blank'>graffiti</a>
- *Relief* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Drelief' target='_blank'>relief</a>
- *Azulejo (Spanish decorative tilework)* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dazulejo' target='_blank'>azulejo</a>
- *Tilework* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dtilework' target='_blank'>tilework</a>
- *Woodcarving* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dwoodcarving' target='_blank'>woodcarving</a>
This tagrendering has labels
`artwork-question`
### artwork-artist-wikidata
The question is `Who made this artwork?`
*This artwork was made by {wikidata_label(artist:wikidata):font-weight:bold}<br/>{wikipedia(artist:wikidata)}* is shown if `artist:wikidata` is set
This tagrendering has labels
`artwork-question`
### artwork-artist_name
The question is `Which artist created this?`
*Created by {artist_name}* is shown if `artist_name` is set
This tagrendering has labels
`artwork-question`
### artwork-website
The question is `Is there a website with more information about this artwork?`
*{link(More information on this website,&LBRACEwebsite&RBRACE,,,,)}* is shown if `website` is set
This tagrendering has labels
`artwork-question`
### wikipedia
Shows a wikipedia box with the corresponding wikipedia article; the wikidata-item link can be changed by a contributor
The question is `What is the corresponding Wikidata entity?`
*{wikipedia():max-height:25rem}* is shown if `wikidata` is set
- *{wikipedia():max-height:25rem}* is shown if with wikipedia~.+. _This option cannot be chosen as answer_
- *No Wikipedia page has been linked yet* is shown if with wikidata=. _This option cannot be chosen as answer_
### artwork_subject
The question is `What does this artwork depict?`
*This artwork depicts {wikidata_label(subject:wikidata)}{wikipedia(subject:wikidata)}* is shown if `subject:wikidata` is set
This tagrendering is only visible in the popup if the following condition is met: subject:wikidata~.+
This tagrendering has labels
`artwork-question`
### doubles_as_memorial
The question is `Does this artwork serve as a memorial?`
- *This artwork also serves as a memorial* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a>
- *This artwork does not serve as a bench* is shown if with historic=
### memorial-type
The question is `What type of memorial is this?`
*This is a {memorial}* is shown if `memorial` is set
- *This is a statue* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstatue' target='_blank'>statue</a>
- *This is a plaque* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dplaque' target='_blank'>plaque</a>
- *This is a commemorative bench* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbench' target='_blank'>bench</a>
- *This is a ghost bike - a bicycle painted white to remember a cyclist whom deceased because of a car crash* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dghost_bike' target='_blank'>ghost_bike</a>
- *This is a stolperstein (stumbing stone)* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstolperstein' target='_blank'>stolperstein</a>
- *This is a stele* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstele' target='_blank'>stele</a>
- *This is a memorial stone* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstone' target='_blank'>stone</a>
- *This is a bust* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbust' target='_blank'>bust</a>
- *This is a sculpture* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dsculpture' target='_blank'>sculpture</a>
- *This is an obelisk* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dobelisk' target='_blank'>obelisk</a>
- *This is a cross* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dcross' target='_blank'>cross</a>
- *This is a blue plaque* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dblue_plaque' target='_blank'>blue_plaque</a>
- *This is a historic tank, permanently placed in public space as memorial* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dtank' target='_blank'>tank</a>
- *This is a memorial tree* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dtree' target='_blank'>tree</a>
- *This is a gravestone; the person is buried here* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dtomb' target='_blank'>tomb</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a>
This tagrendering has labels
`memorial-questions`
### inscription
The question is `What is the inscription on this memorial?`
*The inscription on this memorial reads: <p><i>{inscription}<i></p>* is shown if `inscription` is set
- *This memorial does not have an inscription* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:not:inscription' target='_blank'>not:inscription</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:not:inscription%3Dyes' target='_blank'>yes</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a> & memorial!=bench
This tagrendering has labels
`memorial-questions`
### doubles_as_bench
The question is `Does this artwork serve as a bench?`
- *This artwork also serves as a bench* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
- *This artwork does not serve as a bench* is shown if with amenity=
- *This artwork does not serve as a bench* is shown if with amenity!=bench. _This option cannot be chosen as answer_
### bench-backrest
The question is `Does this bench have a backrest?`
- <img src='https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/./assets/layers/bench/two_sided.svg' style='width: 3rem; height: 3rem'> *This bench is two-sided and shares the backrest* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:backrest' target='_blank'>backrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes' target='_blank'>yes</a> & <a href='https://wiki.openstreetmap.org/wiki/Key:two_sided' target='_blank'>two_sided</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:two_sided%3Dyes' target='_blank'>yes</a>
- *This bench does have a backrest* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:backrest' target='_blank'>backrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes' target='_blank'>yes</a>
- *This bench does <b>not</b> have a backrest* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:backrest' target='_blank'>backrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dno' target='_blank'>no</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-armrest
The question is `Does this bench have one or more armrests?`
- *This bench does have one or more armrests* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:armrest' target='_blank'>armrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:armrest%3Dyes' target='_blank'>yes</a>
- *This bench does <b>not</b> have any armrests* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:armrest' target='_blank'>armrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:armrest%3Dno' target='_blank'>no</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-seats
The question is `How many seats does this bench have?`
*This bench has {seats} seats* is shown if `seats` is set
- *This bench does not have separated seats* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:seats:separated' target='_blank'>seats:separated</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:seats:separated%3Dno' target='_blank'>no</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-material
The question is `What is the bench (seating) made from?`
*Material: {material}* is shown if `material` is set
- *The seating is made from wood* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dwood' target='_blank'>wood</a>
- *The seating is made from metal* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dmetal' target='_blank'>metal</a>
- *The seating is made from stone* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dstone' target='_blank'>stone</a>
- *The seating is made from concrete* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dconcrete' target='_blank'>concrete</a>
- *The seating is made from plastic* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dplastic' target='_blank'>plastic</a>
- *The seating is made from steel* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dsteel' target='_blank'>steel</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-direction
The question is `In which direction are you looking when sitting on the bench?`
*When sitting on the bench, one looks towards {direction}°.* is shown if `direction` is set
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a> & two_sided!=yes
This tagrendering has labels
`bench-questions`
### bench-colour
The question is `Which colour does this bench have?`
*Colour: {colour}* is shown if `colour` is set
- *Colour: brown* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dbrown' target='_blank'>brown</a>
- *Colour: green* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dgreen' target='_blank'>green</a>
- *Colour: gray* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dgray' target='_blank'>gray</a>
- *Colour: white* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dwhite' target='_blank'>white</a>
- *Colour: red* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dred' target='_blank'>red</a>
- *Colour: black* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dblack' target='_blank'>black</a>
- *Colour: blue* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dblue' target='_blank'>blue</a>
- *Colour: yellow* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dyellow' target='_blank'>yellow</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-survey:date
The question is `When was this bench last surveyed?`
*This bench was last surveyed on {survey:date}* is shown if `survey:date` is set
- *Surveyed today!* is shown if with survey:date=
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-inscription
The question is `Does this bench have an inscription?`
*This bench has the following inscription:<br/><p><i>{inscription}</i></p>* is shown if `inscription` is set
- *This bench does not have an inscription* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:not:inscription' target='_blank'>not:inscription</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:not:inscription%3Dyes' target='_blank'>yes</a>
- *This bench <span class='subtle'>probably</span> does not not have an inscription* is shown if with inscription=. _This option cannot be chosen as answer_
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-memorial
The question is `Does this bench act as memorial for someone or something?`
- *This bench is a memorial for someone or something* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a>
- *This bench is a <b>not</b> a memorial for someone or something* is shown if with historic= & <a href='https://wiki.openstreetmap.org/wiki/Key:not:historic' target='_blank'>not:historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:not:historic%3Dmemorial' target='_blank'>memorial</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a> & (<a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbench' target='_blank'>bench</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dartwork' target='_blank'>artwork</a> | inscription~.+)
This tagrendering has labels
`bench-questions`
### leftover-questions
_This tagrendering has no question and is thus read-only_
*{questions( ,)}*
### move-button
_This tagrendering has no question and is thus read-only_
*{move_button()}*
### delete-button
_This tagrendering has no question and is thus read-only_
*{delete_button()}*
### lod
_This tagrendering has no question and is thus read-only_
*{linked_data_from_website()}*
This tagrendering has labels
`added_by_default`
## Filters
| id | question | osmTags |
-----|-----|----- |
| has_image.0 | *With and without images* (default) | |
| has_image.1 | Has at least one image | image~.+ | image:0~.+ | image:1~.+ | image:2~.+ | image:3~.+ | mapillary~.+ |
| has_image.2 | Probably does not have an image | image= & image:0= & image:1= & image:2= & image:3= & mapillary= |
| id | question | osmTags |
-----|-----|----- |
| artwork-artwork_type.0 | *What is the type of this artwork?* (default) | |
| artwork-artwork_type.1 | Architecture | artwork_type=architecture |
| artwork-artwork_type.2 | Mural | artwork_type=mural |
| artwork-artwork_type.3 | Painting | artwork_type=painting |
| artwork-artwork_type.4 | Sculpture | artwork_type=sculpture |
| artwork-artwork_type.5 | Statue | artwork_type=statue |
| artwork-artwork_type.6 | Bust | artwork_type=bust |
| artwork-artwork_type.7 | Stone | artwork_type=stone |
| artwork-artwork_type.8 | Installation | artwork_type=installation |
| artwork-artwork_type.9 | Graffiti | artwork_type=graffiti |
| artwork-artwork_type.10 | Relief | artwork_type=relief |
| artwork-artwork_type.11 | Azulejo (Spanish decorative tilework) | artwork_type=azulejo |
| artwork-artwork_type.12 | Tilework | artwork_type=tilework |
| artwork-artwork_type.13 | Woodcarving | artwork_type=woodcarving |
This document is autogenerated from [assets/themes/ghostsigns/ghostsigns.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/ghostsigns/ghostsigns.json)

View file

@ -158,7 +158,7 @@ The question is `What is the Mastodon-handle of {title()}?`
### facebook ### facebook
Shows and asks for the facebook handle Shows and asks for the facebook handle
The question is `What is the facebook page of of {title()}?` The question is `What is the facebook page of of {title()}?`
*{link(Facebook page,&LBRACEcontact:facebook&RBRACE,,,)}<div class='subtle text-sm'>Facebook is known to harm mental health, manipulate public opinion and cause hate. Try to use healthier alternatives</div>* is shown if `contact:facebook` is set *{link(Facebook page,&LBRACEcontact:facebook&RBRACE,,,,)}<div class='subtle text-sm'>Facebook is known to harm mental health, manipulate public opinion and cause hate. Try to use healthier alternatives</div>* is shown if `contact:facebook` is set

View file

@ -286,7 +286,7 @@ This tagrendering has labels
### artwork-website ### artwork-website
The question is `Is there a website with more information about this artwork?` The question is `Is there a website with more information about this artwork?`
*{link(More information on this website,&LBRACEwebsite&RBRACE,,,)}* is shown if `website` is set *{link(More information on this website,&LBRACEwebsite&RBRACE,,,,)}* is shown if `website` is set
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dartwork' target='_blank'>artwork</a> This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dartwork' target='_blank'>artwork</a>
This tagrendering has labels This tagrendering has labels

View file

@ -312,7 +312,7 @@ _This tagrendering has no question and is thus read-only_
### menu-website ### menu-website
The question is `On what webpage is the menu published?` The question is `On what webpage is the menu published?`
*{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,)}* is shown if `website:menu` is set *{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,,)}* is shown if `website:menu` is set

View file

@ -238,7 +238,7 @@ This tagrendering has labels
### artwork-website ### artwork-website
The question is `Is there a website with more information about this artwork?` The question is `Is there a website with more information about this artwork?`
*{link(More information on this website,&LBRACEwebsite&RBRACE,,,)}* is shown if `website` is set *{link(More information on this website,&LBRACEwebsite&RBRACE,,,,)}* is shown if `website` is set
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dartwork' target='_blank'>artwork</a> This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dartwork' target='_blank'>artwork</a>
This tagrendering has labels This tagrendering has labels

View file

@ -320,7 +320,7 @@ _This tagrendering has no question and is thus read-only_
### menu-website ### menu-website
The question is `On what webpage is the menu published?` The question is `On what webpage is the menu published?`
*{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,)}* is shown if `website:menu` is set *{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,,)}* is shown if `website:menu` is set

View file

@ -329,7 +329,7 @@ _This tagrendering has no question and is thus read-only_
### menu-website ### menu-website
The question is `On what webpage is the menu published?` The question is `On what webpage is the menu published?`
*{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,)}* is shown if `website:menu` is set *{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,,)}* is shown if `website:menu` is set

View file

@ -329,7 +329,7 @@ _This tagrendering has no question and is thus read-only_
### menu-website ### menu-website
The question is `On what webpage is the menu published?` The question is `On what webpage is the menu published?`
*{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,)}* is shown if `website:menu` is set *{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,,)}* is shown if `website:menu` is set

View file

@ -312,7 +312,7 @@ _This tagrendering has no question and is thus read-only_
### menu-website ### menu-website
The question is `On what webpage is the menu published?` The question is `On what webpage is the menu published?`
*{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,)}* is shown if `website:menu` is set *{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,,)}* is shown if `website:menu` is set

View file

@ -96,7 +96,7 @@ The question is `Whom is remembered by this ghost bike?`
### ghost_bike-source ### ghost_bike-source
The question is `On what webpage can one find more info about the ghost bike or the accident?` The question is `On what webpage can one find more info about the ghost bike or the accident?`
*{link(More info available,&LBRACEsource&RBRACE,,,)}* is shown if `source` is set *{link(More info available,&LBRACEsource&RBRACE,,,,)}* is shown if `source` is set

View file

@ -185,7 +185,7 @@ The question is `When was this public bookcase installed?`
### public_bookcase-website ### public_bookcase-website
The question is `Is there a website with more information about this public bookcase?` The question is `Is there a website with more information about this public bookcase?`
*{link(More info on the website,&LBRACEwebsite&RBRACE,,,)}* is shown if `website` is set *{link(More info on the website,&LBRACEwebsite&RBRACE,,,,)}* is shown if `website` is set

View file

@ -120,7 +120,7 @@ This tagrendering has labels
### facebook ### facebook
Shows and asks for the facebook handle Shows and asks for the facebook handle
The question is `What is the facebook page of of {title()}?` The question is `What is the facebook page of of {title()}?`
*{link(Facebook page,&LBRACEcontact:facebook&RBRACE,,,)}<div class='subtle text-sm'>Facebook is known to harm mental health, manipulate public opinion and cause hate. Try to use healthier alternatives</div>* is shown if `contact:facebook` is set *{link(Facebook page,&LBRACEcontact:facebook&RBRACE,,,,)}<div class='subtle text-sm'>Facebook is known to harm mental health, manipulate public opinion and cause hate. Try to use healthier alternatives</div>* is shown if `contact:facebook` is set

View file

@ -1,18 +1,18 @@
[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources) [//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources)
# hotel # tourism_accomodation
Layer showing all hotels
- This layer is shown at zoomlevel **13** and higher
- This layer is shown at zoomlevel **12** and higher
@ -24,6 +24,8 @@ Layer showing all hotels
- [images](#images) - [images](#images)
- [reviews](#reviews) - [reviews](#reviews)
- [name](#name) - [name](#name)
- [presettypeselect](#presettypeselect)
- [brand](#brand)
- [phone](#phone) - [phone](#phone)
- [email](#email) - [email](#email)
- [website](#website) - [website](#website)
@ -31,6 +33,7 @@ Layer showing all hotels
- [internet](#internet) - [internet](#internet)
- [internet-fee](#internet-fee) - [internet-fee](#internet-fee)
- [internet-ssid](#internet-ssid) - [internet-ssid](#internet-ssid)
- [dog-access](#dog-access)
- [leftover-questions](#leftover-questions) - [leftover-questions](#leftover-questions)
- [move-button](#move-button) - [move-button](#move-button)
- [lod](#lod) - [lod](#lod)
@ -48,9 +51,12 @@ Layer showing all hotels
## Basic tags for this layer ## Basic tags for this layer
Elements must match the expression **<a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dhotel' target='_blank'>hotel</a>** Elements must match **any** of the following expressions:
[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B%28%20%20%20%20nwr%5B%22tourism%22%3D%22hotel%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%29%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dhostel' target='_blank'>hostel</a>
- <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dhotel' target='_blank'>hotel</a>
[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B%28%20%20%20%20nwr%5B%22tourism%22%3D%22hostel%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22hotel%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%29%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B)
## Supported attributes ## Supported attributes
@ -59,6 +65,7 @@ Elements must match the expression **<a href='https://wiki.openstreetmap.org/wik
| attribute | type | values which are supported by this layer | | attribute | type | values which are supported by this layer |
-----|-----|----- | -----|-----|----- |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/name#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/name/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/name#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/name/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/brand#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/brand/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [brand](https://wiki.openstreetmap.org/wiki/Key:brand) | [string](../SpecialInputElements.md#string) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/phone#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/phone/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/phone#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/phone/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/email#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/email/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/email#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/email/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/website#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/website/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/website#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/website/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | |
@ -66,6 +73,7 @@ Elements must match the expression **<a href='https://wiki.openstreetmap.org/wik
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/internet_access#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/internet_access/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [internet_access](https://wiki.openstreetmap.org/wiki/Key:internet_access) | Multiple choice | [wlan](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dwlan) [no](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dno) [terminal](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dterminal) [wired](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dwired) | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/internet_access#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/internet_access/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [internet_access](https://wiki.openstreetmap.org/wiki/Key:internet_access) | Multiple choice | [wlan](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dwlan) [no](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dno) [terminal](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dterminal) [wired](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dwired) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/internet_access:fee#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/internet_access%3Afee/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [internet_access:fee](https://wiki.openstreetmap.org/wiki/Key:internet_access:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dno) [customers](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dcustomers) | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/internet_access:fee#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/internet_access%3Afee/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [internet_access:fee](https://wiki.openstreetmap.org/wiki/Key:internet_access:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dno) [customers](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dcustomers) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/internet_access:ssid#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/internet_access%3Assid/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [internet_access:ssid](https://wiki.openstreetmap.org/wiki/Key:internet_access:ssid) | [string](../SpecialInputElements.md#string) | [Telekom](https://wiki.openstreetmap.org/wiki/Tag:internet_access:ssid%3DTelekom) | | <a target="_blank" href='https://taginfo.openstreetmap.org/keys/internet_access:ssid#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/internet_access%3Assid/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [internet_access:ssid](https://wiki.openstreetmap.org/wiki/Key:internet_access:ssid) | [string](../SpecialInputElements.md#string) | [Telekom](https://wiki.openstreetmap.org/wiki/Tag:internet_access:ssid%3DTelekom) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/dog#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/dog/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [dog](https://wiki.openstreetmap.org/wiki/Key:dog) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:dog%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:dog%3Dno) [leashed](https://wiki.openstreetmap.org/wiki/Tag:dog%3Dleashed) [unleashed](https://wiki.openstreetmap.org/wiki/Tag:dog%3Dunleashed) [outside](https://wiki.openstreetmap.org/wiki/Tag:dog%3Doutside) |
@ -88,8 +96,28 @@ _This tagrendering has no question and is thus read-only_
### name ### name
The question is `What is the name of this hotel?` The question is `What is the name of this {title()}?`
*This hotel is called {name}* is shown if `name` is set *{name}* is shown if `name` is set
### presettypeselect
_This tagrendering has no question and is thus read-only_
*{preset_type_select()}*
### brand
The question is `Is {title()} part of a bigger brand?`
*Part of {brand}* is shown if `brand` is set
- *Not part of a bigger brand* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:nobrand' target='_blank'>nobrand</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:nobrand%3Dyes' target='_blank'>yes</a>
@ -194,6 +222,22 @@ This tagrendering is only visible in the popup if the following condition is met
This tagrendering has labels This tagrendering has labels
`internet-all` `internet-all`
### dog-access
The question is `Are dogs allowed in this business?`
- <img src='https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/./assets/layers/questions/dogs_allowed.svg' style='width: 3rem; height: 3rem'> *Dogs are allowed* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:dog' target='_blank'>dog</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:dog%3Dyes' target='_blank'>yes</a>
- <img src='https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/./assets/layers/questions/no_dogs.svg' style='width: 3rem; height: 3rem'> *Dogs are <b>not</b> allowed* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:dog' target='_blank'>dog</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:dog%3Dno' target='_blank'>no</a>
- <img src='https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/./assets/layers/questions/dogs_leashed.svg' style='width: 3rem; height: 3rem'> *Dogs are allowed, but they have to be leashed* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:dog' target='_blank'>dog</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:dog%3Dleashed' target='_blank'>leashed</a>
- <img src='https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/./assets/layers/questions/dogs_allowed.svg' style='width: 3rem; height: 3rem'> *Dogs are allowed and can run around freely* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:dog' target='_blank'>dog</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:dog%3Dunleashed' target='_blank'>unleashed</a>
- <img src='https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/./assets/layers/questions/dogs_outside.svg' style='width: 3rem; height: 3rem'> *Dogs are allowed only outside* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:dog' target='_blank'>dog</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:dog%3Doutside' target='_blank'>outside</a>
### leftover-questions ### leftover-questions
_This tagrendering has no question and is thus read-only_ _This tagrendering has no question and is thus read-only_
@ -220,4 +264,4 @@ This tagrendering has labels
`added_by_default` `added_by_default`
This document is autogenerated from [assets/layers/hotel/hotel.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/hotel/hotel.json) This document is autogenerated from [assets/layers/tourism_accomodation/tourism_accomodation.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/tourism_accomodation/tourism_accomodation.json)

View file

@ -20,79 +20,79 @@ General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_nam
- [Example usage of questions](#example-usage-of-questions) - [Example usage of questions](#example-usage-of-questions)
2. [add_new_point](#add_new_point) 2. [add_new_point](#add_new_point)
- [Example usage of add_new_point](#example-usage-of-add_new_point) - [Example usage of add_new_point](#example-usage-of-add_new_point)
3. [user_profile](#user_profile) 3. [language_picker](#language_picker)
- [Example usage of user_profile](#example-usage-of-user_profile)
4. [language_picker](#language_picker)
- [Example usage of language_picker](#example-usage-of-language_picker) - [Example usage of language_picker](#example-usage-of-language_picker)
5. [logout](#logout) 4. [logout](#logout)
- [Example usage of logout](#example-usage-of-logout) - [Example usage of logout](#example-usage-of-logout)
6. [histogram](#histogram) 5. [histogram](#histogram)
- [Example usage of histogram](#example-usage-of-histogram) - [Example usage of histogram](#example-usage-of-histogram)
7. [steal](#steal) 6. [steal](#steal)
- [Example usage of steal](#example-usage-of-steal) - [Example usage of steal](#example-usage-of-steal)
8. [minimap](#minimap) 7. [minimap](#minimap)
- [Example usage of minimap](#example-usage-of-minimap) - [Example usage of minimap](#example-usage-of-minimap)
9. [split_button](#split_button) 8. [split_button](#split_button)
- [Example usage of split_button](#example-usage-of-split_button) - [Example usage of split_button](#example-usage-of-split_button)
10. [move_button](#move_button) 9. [move_button](#move_button)
- [Example usage of move_button](#example-usage-of-move_button) - [Example usage of move_button](#example-usage-of-move_button)
11. [delete_button](#delete_button) 10. [delete_button](#delete_button)
- [Example usage of delete_button](#example-usage-of-delete_button) - [Example usage of delete_button](#example-usage-of-delete_button)
12. [share_link](#share_link) 11. [share_link](#share_link)
- [Example usage of share_link](#example-usage-of-share_link) - [Example usage of share_link](#example-usage-of-share_link)
13. [export_as_gpx](#export_as_gpx) 12. [export_as_gpx](#export_as_gpx)
- [Example usage of export_as_gpx](#example-usage-of-export_as_gpx) - [Example usage of export_as_gpx](#example-usage-of-export_as_gpx)
14. [upload_to_osm](#upload_to_osm) 13. [upload_to_osm](#upload_to_osm)
- [Example usage of upload_to_osm](#example-usage-of-upload_to_osm) - [Example usage of upload_to_osm](#example-usage-of-upload_to_osm)
15. [multi_apply](#multi_apply) 14. [multi_apply](#multi_apply)
- [Example usage of multi_apply](#example-usage-of-multi_apply) - [Example usage of multi_apply](#example-usage-of-multi_apply)
16. [add_note_comment](#add_note_comment) 15. [add_note_comment](#add_note_comment)
- [Example usage of add_note_comment](#example-usage-of-add_note_comment) - [Example usage of add_note_comment](#example-usage-of-add_note_comment)
17. [open_note](#open_note) 16. [open_note](#open_note)
- [Example usage of open_note](#example-usage-of-open_note) - [Example usage of open_note](#example-usage-of-open_note)
18. [close_note](#close_note) 17. [close_note](#close_note)
- [Example usage of close_note](#example-usage-of-close_note) - [Example usage of close_note](#example-usage-of-close_note)
19. [plantnet_detection](#plantnet_detection) 18. [plantnet_detection](#plantnet_detection)
- [Example usage of plantnet_detection](#example-usage-of-plantnet_detection) - [Example usage of plantnet_detection](#example-usage-of-plantnet_detection)
20. [tag_apply](#tag_apply) 19. [tag_apply](#tag_apply)
- [Example usage of tag_apply](#example-usage-of-tag_apply) - [Example usage of tag_apply](#example-usage-of-tag_apply)
21. [import_button](#import_button) 20. [import_button](#import_button)
- [Specifying which tags to copy or add](#specifying-which-tags-to-copy-or-add) - [Specifying which tags to copy or add](#specifying-which-tags-to-copy-or-add)
- [Importing a dataset into OpenStreetMap: requirements](#importing-a-dataset-into-openstreetmap-requirements) - [Importing a dataset into OpenStreetMap: requirements](#importing-a-dataset-into-openstreetmap-requirements)
- [Disabled in unofficial themes](#disabled-in-unofficial-themes) - [Disabled in unofficial themes](#disabled-in-unofficial-themes)
- [Example usage of import_button](#example-usage-of-import_button) - [Example usage of import_button](#example-usage-of-import_button)
22. [import_way_button](#import_way_button) 21. [import_way_button](#import_way_button)
- [Specifying which tags to copy or add](#specifying-which-tags-to-copy-or-add) - [Specifying which tags to copy or add](#specifying-which-tags-to-copy-or-add)
- [Importing a dataset into OpenStreetMap: requirements](#importing-a-dataset-into-openstreetmap-requirements) - [Importing a dataset into OpenStreetMap: requirements](#importing-a-dataset-into-openstreetmap-requirements)
- [Disabled in unofficial themes](#disabled-in-unofficial-themes) - [Disabled in unofficial themes](#disabled-in-unofficial-themes)
- [Example usage of import_way_button](#example-usage-of-import_way_button) - [Example usage of import_way_button](#example-usage-of-import_way_button)
23. [conflate_button](#conflate_button) 22. [conflate_button](#conflate_button)
- [Specifying which tags to copy or add](#specifying-which-tags-to-copy-or-add) - [Specifying which tags to copy or add](#specifying-which-tags-to-copy-or-add)
- [Importing a dataset into OpenStreetMap: requirements](#importing-a-dataset-into-openstreetmap-requirements) - [Importing a dataset into OpenStreetMap: requirements](#importing-a-dataset-into-openstreetmap-requirements)
- [Disabled in unofficial themes](#disabled-in-unofficial-themes) - [Disabled in unofficial themes](#disabled-in-unofficial-themes)
- [Example usage of conflate_button](#example-usage-of-conflate_button) - [Example usage of conflate_button](#example-usage-of-conflate_button)
24. [nearby_images](#nearby_images) 23. [nearby_images](#nearby_images)
- [Example usage of nearby_images](#example-usage-of-nearby_images) - [Example usage of nearby_images](#example-usage-of-nearby_images)
25. [wikipedia](#wikipedia) 24. [wikipedia](#wikipedia)
- [Example usage of wikipedia](#example-usage-of-wikipedia) - [Example usage of wikipedia](#example-usage-of-wikipedia)
26. [wikidata_label](#wikidata_label) 25. [wikidata_label](#wikidata_label)
- [Example usage of wikidata_label](#example-usage-of-wikidata_label) - [Example usage of wikidata_label](#example-usage-of-wikidata_label)
27. [mapillary_link](#mapillary_link) 26. [mapillary_link](#mapillary_link)
- [Example usage of mapillary_link](#example-usage-of-mapillary_link) - [Example usage of mapillary_link](#example-usage-of-mapillary_link)
28. [language_chooser](#language_chooser) 27. [language_chooser](#language_chooser)
- [Example usage of language_chooser](#example-usage-of-language_chooser) - [Example usage of language_chooser](#example-usage-of-language_chooser)
29. [all_tags](#all_tags) 28. [all_tags](#all_tags)
- [Example usage of all_tags](#example-usage-of-all_tags) - [Example usage of all_tags](#example-usage-of-all_tags)
30. [image_carousel](#image_carousel) 29. [image_carousel](#image_carousel)
- [Example usage of image_carousel](#example-usage-of-image_carousel) - [Example usage of image_carousel](#example-usage-of-image_carousel)
31. [image_upload](#image_upload) 30. [image_upload](#image_upload)
- [Example usage of image_upload](#example-usage-of-image_upload) - [Example usage of image_upload](#example-usage-of-image_upload)
32. [rating](#rating) 31. [rating](#rating)
- [Example usage of rating](#example-usage-of-rating) - [Example usage of rating](#example-usage-of-rating)
33. [create_review](#create_review) 32. [create_review](#create_review)
- [Example usage of create_review](#example-usage-of-create_review) - [Example usage of create_review](#example-usage-of-create_review)
34. [list_reviews](#list_reviews) 33. [list_reviews](#list_reviews)
- [Example usage of list_reviews](#example-usage-of-list_reviews) - [Example usage of list_reviews](#example-usage-of-list_reviews)
34. [reviews](#reviews)
- [Example usage of reviews](#example-usage-of-reviews)
35. [import_mangrove_key](#import_mangrove_key) 35. [import_mangrove_key](#import_mangrove_key)
- [Example usage of import_mangrove_key](#example-usage-of-import_mangrove_key) - [Example usage of import_mangrove_key](#example-usage-of-import_mangrove_key)
36. [opening_hours_table](#opening_hours_table) 36. [opening_hours_table](#opening_hours_table)
@ -181,16 +181,6 @@ An element which allows to add a new point on the 'last_click'-location. Only ma
<code>`{add_new_point()}`</code> <code>`{add_new_point()}`</code>
### user_profile
A component showing information about the currently logged in user (username, profile description, profile picture + link to edit them). Mostly meant to be used in the 'user-settings'
#### Example usage of user_profile
<code>`{user_profile()}`</code>
### language_picker ### language_picker
A component to set the language of the user interface A component to set the language of the user interface
@ -847,6 +837,24 @@ Adds an overview of the mangrove-reviews of this object. Mangrove.Reviews needs
#### Example usage of list_reviews #### Example usage of list_reviews
<code>`{list_reviews(name,)}`</code>
### reviews
A pragmatic combination of `create_review` and `list_reviews`
| name | default | description |
-----|-----|----- |
| subjectKey | name | The key to use to determine the subject. If specified, the subject will be <b>tags[subjectKey]</b> |
| fallback | _undefined_ | The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value |
#### Example usage of reviews
<code>`{reviews()}` for a vanilla review, `{reviews(name, play_forest)}` to review a play forest. If a name is known, the name will be used as identifier, otherwise 'play_forest' is used</code> <code>`{reviews()}` for a vanilla review, `{reviews(name, play_forest)}` to review a play forest. If a name is known, the name will be used as identifier, otherwise 'play_forest' is used</code>
### import_mangrove_key ### import_mangrove_key
@ -1099,13 +1107,14 @@ Construct a link. By using the 'special' visualisation notation, translations sh
| class | _undefined_ | CSS-classes to add to the element | | class | _undefined_ | CSS-classes to add to the element |
| download | _undefined_ | Expects a string which denotes the filename to download the contents of `href` into. If set, this link will act as a download-button. | | download | _undefined_ | Expects a string which denotes the filename to download the contents of `href` into. If set, this link will act as a download-button. |
| arialabel | _undefined_ | If set, this text will be used as aria-label | | arialabel | _undefined_ | If set, this text will be used as aria-label |
| icon | _undefined_ | If set, show this icon next to the link. You might want to combine this with `class: button` |
#### Example usage of link #### Example usage of link
<code>`{link(,,,,)}`</code> <code>`{link(,,,,,)}`</code>
### multi ### multi
@ -1368,6 +1377,116 @@ Shows the extra description from the presets of the layer, if one matches. It wi
<code>`{preset_description()}`</code> <code>`{preset_description()}`</code>
### preset_type_select
An editable tag rendering which allows to change the type
#### Example usage of preset_type_select
<code>`{preset_type_select()}`</code>
### pending_changes
A module showing the pending changes, with the option to clear the pending changes
#### Example usage of pending_changes
<code>`{pending_changes()}`</code>
### clear_caches
A button which clears the locally downloaded data and the service worker. Login status etc will be kept
| name | default | description |
-----|-----|----- |
| text | _undefined_ | The text to show on the button |
#### Example usage of clear_caches
<code>`{clear_caches()}`</code>
### group
A collapsable group (accordion)
| name | default | description |
-----|-----|----- |
| header | _undefined_ | The _identifier_ of a single tagRendering. This will be used as header |
| labels | _undefined_ | A `;`-separated list of either identifiers or label names. All tagRenderings matching this value will be shown in the accordion |
#### Example usage of group
<code>`{group(,)}`</code>
### preset_type_select
An editable tag rendering which allows to change the type
#### Example usage of preset_type_select
<code>`{preset_type_select()}`</code>
### pending_changes
A module showing the pending changes, with the option to clear the pending changes
#### Example usage of pending_changes
<code>`{pending_changes()}`</code>
### clear_caches
A button which clears the locally downloaded data and the service worker. Login status etc will be kept
| name | default | description |
-----|-----|----- |
| text | _undefined_ | The text to show on the button |
#### Example usage of clear_caches
<code>`{clear_caches()}`</code>
### group
A collapsable group (accordion)
| name | default | description |
-----|-----|----- |
| header | _undefined_ | The _identifier_ of a single tagRendering. This will be used as header |
| labels | _undefined_ | A `;`-separated list of either identifiers or label names. All tagRenderings matching this value will be shown in the accordion |
#### Example usage of group
<code>`{group(,)}`</code>
### auto_apply ### auto_apply
A button to run many actions for many features at once. To effectively use this button, you'll need some ingredients: A button to run many actions for many features at once. To effectively use this button, you'll need some ingredients:

View file

@ -278,6 +278,436 @@
{ {
"key": "ref", "key": "ref",
"description": "Layer 'All advertentie wall paintings' shows and asks freeform values for key 'ref' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if advertising!=sign)" "description": "Layer 'All advertentie wall paintings' shows and asks freeform values for key 'ref' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if advertising!=sign)"
},
{
"key": "tourism",
"description": "The MapComplete theme Ghost Signs has a layer Artworks showing features with this tag",
"value": "artwork"
},
{
"key": "artwork_type",
"description": "The MapComplete theme Ghost Signs has a layer Artworks showing features with this tag",
"value": "mural"
},
{
"key": "artwork_type",
"description": "The MapComplete theme Ghost Signs has a layer Artworks showing features with this tag",
"value": "graffiti"
},
{
"key": "artwork_type",
"description": "The MapComplete theme Ghost Signs has a layer Artworks showing features with this tag",
"value": "mosaic"
},
{
"key": "artwork_type",
"description": "The MapComplete theme Ghost Signs has a layer Artworks showing features with this tag",
"value": "relief"
},
{
"key": "artwork_type",
"description": "The MapComplete theme Ghost Signs has a layer Artworks showing features with this tag",
"value": "painting"
},
{
"key": "artwork_type",
"description": "The MapComplete theme Ghost Signs has a layer Artworks showing features with this tag",
"value": "mural_painting"
},
{
"key": "historic",
"description": "Layer 'Artworks' shows historic=advertising with a fixed text, namely 'This artwork is a historic advertisement' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "advertising"
},
{
"key": "historic",
"description": "Layer 'Artworks' shows historic= with a fixed text, namely 'This artwork is not a historic advertisement' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') Picking this answer will delete the key historic.",
"value": ""
},
{
"key": "id",
"description": "Layer 'Artworks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if _backend~.+ & _last_edit:passed_time<300 & (_version_number= | _version_number=1))"
},
{
"key": "image",
"description": "The layer 'Artworks allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "mapillary",
"description": "The layer 'Artworks allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "wikidata",
"description": "The layer 'Artworks allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "wikipedia",
"description": "The layer 'Artworks allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows and asks freeform values for key 'artwork_type' (in the mapcomplete.org theme 'Ghost Signs')"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=architecture with a fixed text, namely 'Architecture' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "architecture"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=mural with a fixed text, namely 'Mural' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "mural"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=painting with a fixed text, namely 'Painting' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "painting"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=sculpture with a fixed text, namely 'Sculpture' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "sculpture"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=statue with a fixed text, namely 'Statue' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "statue"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=bust with a fixed text, namely 'Bust' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "bust"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=stone with a fixed text, namely 'Stone' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "stone"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=installation with a fixed text, namely 'Installation' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "installation"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=graffiti with a fixed text, namely 'Graffiti' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "graffiti"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=relief with a fixed text, namely 'Relief' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "relief"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=azulejo with a fixed text, namely 'Azulejo (Spanish decorative tilework)' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "azulejo"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=tilework with a fixed text, namely 'Tilework' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "tilework"
},
{
"key": "artwork_type",
"description": "Layer 'Artworks' shows artwork_type=woodcarving with a fixed text, namely 'Woodcarving' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "woodcarving"
},
{
"key": "artist:wikidata",
"description": "Layer 'Artworks' shows and asks freeform values for key 'artist:wikidata' (in the mapcomplete.org theme 'Ghost Signs')"
},
{
"key": "artist_name",
"description": "Layer 'Artworks' shows and asks freeform values for key 'artist_name' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if artist:wikidata=)"
},
{
"key": "website",
"description": "Layer 'Artworks' shows and asks freeform values for key 'website' (in the mapcomplete.org theme 'Ghost Signs')"
},
{
"key": "wikidata",
"description": "Layer 'Artworks' shows and asks freeform values for key 'wikidata' (in the mapcomplete.org theme 'Ghost Signs')"
},
{
"key": "wikipedia",
"description": "Layer 'Artworks' shows wikipedia~.+ with a fixed text, namely '{wikipedia():max-height:25rem}' (in the mapcomplete.org theme 'Ghost Signs')"
},
{
"key": "wikidata",
"description": "Layer 'Artworks' shows wikidata= with a fixed text, namely 'No Wikipedia page has been linked yet' (in the mapcomplete.org theme 'Ghost Signs') Picking this answer will delete the key wikidata.",
"value": ""
},
{
"key": "subject:wikidata",
"description": "Layer 'Artworks' shows and asks freeform values for key 'subject:wikidata' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if subject:wikidata~.+)"
},
{
"key": "historic",
"description": "Layer 'Artworks' shows historic=memorial with a fixed text, namely 'This artwork also serves as a memorial' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "memorial"
},
{
"key": "historic",
"description": "Layer 'Artworks' shows historic= with a fixed text, namely 'This artwork does not serve as a bench' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') Picking this answer will delete the key historic.",
"value": ""
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows and asks freeform values for key 'memorial' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=statue with a fixed text, namely 'This is a statue' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "statue"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=plaque with a fixed text, namely 'This is a plaque' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "plaque"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=bench with a fixed text, namely 'This is a commemorative bench' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "bench"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=ghost_bike with a fixed text, namely 'This is a ghost bike - a bicycle painted white to remember a cyclist whom deceased because of a car crash' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "ghost_bike"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=stolperstein with a fixed text, namely 'This is a stolperstein (stumbing stone)' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "stolperstein"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=stele with a fixed text, namely 'This is a stele' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "stele"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=stone with a fixed text, namely 'This is a memorial stone' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "stone"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=bust with a fixed text, namely 'This is a bust' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "bust"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=sculpture with a fixed text, namely 'This is a sculpture' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "sculpture"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=obelisk with a fixed text, namely 'This is an obelisk' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "obelisk"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=cross with a fixed text, namely 'This is a cross' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "cross"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=blue_plaque with a fixed text, namely 'This is a blue plaque' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "blue_plaque"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=tank with a fixed text, namely 'This is a historic tank, permanently placed in public space as memorial' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "tank"
},
{
"key": "memorial",
"description": "Layer 'Artworks' shows memorial=tree with a fixed text, namely 'This is a memorial tree' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "tree"
},
{
"key": "historic",
"description": "Layer 'Artworks' shows historic=tomb with a fixed text, namely 'This is a gravestone; the person is buried here' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if historic=memorial)",
"value": "tomb"
},
{
"key": "inscription",
"description": "Layer 'Artworks' shows and asks freeform values for key 'inscription' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if memorial!=bench & historic=memorial)"
},
{
"key": "not:inscription",
"description": "Layer 'Artworks' shows not:inscription=yes with a fixed text, namely 'This memorial does not have an inscription' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if memorial!=bench & historic=memorial)",
"value": "yes"
},
{
"key": "amenity",
"description": "Layer 'Artworks' shows amenity=bench with a fixed text, namely 'This artwork also serves as a bench' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs')",
"value": "bench"
},
{
"key": "amenity",
"description": "Layer 'Artworks' shows amenity= with a fixed text, namely 'This artwork does not serve as a bench' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') Picking this answer will delete the key amenity.",
"value": ""
},
{
"key": "backrest",
"description": "Layer 'Artworks' shows backrest=yes & two_sided=yes with a fixed text, namely 'This bench is two-sided and shares the backrest' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "yes"
},
{
"key": "two_sided",
"description": "Layer 'Artworks' shows backrest=yes & two_sided=yes with a fixed text, namely 'This bench is two-sided and shares the backrest' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "yes"
},
{
"key": "backrest",
"description": "Layer 'Artworks' shows backrest=yes with a fixed text, namely 'This bench does have a backrest' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "yes"
},
{
"key": "backrest",
"description": "Layer 'Artworks' shows backrest=no with a fixed text, namely 'This bench does <b>not</b> have a backrest' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "no"
},
{
"key": "armrest",
"description": "Layer 'Artworks' shows armrest=yes with a fixed text, namely 'This bench does have one or more armrests' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "yes"
},
{
"key": "armrest",
"description": "Layer 'Artworks' shows armrest=no with a fixed text, namely 'This bench does <b>not</b> have any armrests' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "no"
},
{
"key": "seats",
"description": "Layer 'Artworks' shows and asks freeform values for key 'seats' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)"
},
{
"key": "seats:separated",
"description": "Layer 'Artworks' shows seats:separated=no with a fixed text, namely 'This bench does not have separated seats' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "no"
},
{
"key": "material",
"description": "Layer 'Artworks' shows and asks freeform values for key 'material' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)"
},
{
"key": "material",
"description": "Layer 'Artworks' shows material=wood with a fixed text, namely 'The seating is made from wood' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "wood"
},
{
"key": "material",
"description": "Layer 'Artworks' shows material=metal with a fixed text, namely 'The seating is made from metal' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "metal"
},
{
"key": "material",
"description": "Layer 'Artworks' shows material=stone with a fixed text, namely 'The seating is made from stone' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "stone"
},
{
"key": "material",
"description": "Layer 'Artworks' shows material=concrete with a fixed text, namely 'The seating is made from concrete' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "concrete"
},
{
"key": "material",
"description": "Layer 'Artworks' shows material=plastic with a fixed text, namely 'The seating is made from plastic' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "plastic"
},
{
"key": "material",
"description": "Layer 'Artworks' shows material=steel with a fixed text, namely 'The seating is made from steel' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "steel"
},
{
"key": "direction",
"description": "Layer 'Artworks' shows and asks freeform values for key 'direction' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if two_sided!=yes & amenity=bench)"
},
{
"key": "colour",
"description": "Layer 'Artworks' shows and asks freeform values for key 'colour' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)"
},
{
"key": "colour",
"description": "Layer 'Artworks' shows colour=brown with a fixed text, namely 'Colour: brown' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "brown"
},
{
"key": "colour",
"description": "Layer 'Artworks' shows colour=green with a fixed text, namely 'Colour: green' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "green"
},
{
"key": "colour",
"description": "Layer 'Artworks' shows colour=gray with a fixed text, namely 'Colour: gray' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "gray"
},
{
"key": "colour",
"description": "Layer 'Artworks' shows colour=white with a fixed text, namely 'Colour: white' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "white"
},
{
"key": "colour",
"description": "Layer 'Artworks' shows colour=red with a fixed text, namely 'Colour: red' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "red"
},
{
"key": "colour",
"description": "Layer 'Artworks' shows colour=black with a fixed text, namely 'Colour: black' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "black"
},
{
"key": "colour",
"description": "Layer 'Artworks' shows colour=blue with a fixed text, namely 'Colour: blue' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "blue"
},
{
"key": "colour",
"description": "Layer 'Artworks' shows colour=yellow with a fixed text, namely 'Colour: yellow' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "yellow"
},
{
"key": "survey:date",
"description": "Layer 'Artworks' shows and asks freeform values for key 'survey:date' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)"
},
{
"key": "survey:date",
"description": "Layer 'Artworks' shows survey:date= with a fixed text, namely 'Surveyed today!' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') Picking this answer will delete the key survey:date. (This is only shown if amenity=bench)",
"value": ""
},
{
"key": "inscription",
"description": "Layer 'Artworks' shows and asks freeform values for key 'inscription' (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)"
},
{
"key": "not:inscription",
"description": "Layer 'Artworks' shows not:inscription=yes with a fixed text, namely 'This bench does not have an inscription' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if amenity=bench)",
"value": "yes"
},
{
"key": "inscription",
"description": "Layer 'Artworks' shows inscription= with a fixed text, namely 'This bench <span class='subtle'>probably</span> does not not have an inscription' (in the mapcomplete.org theme 'Ghost Signs') Picking this answer will delete the key inscription. (This is only shown if amenity=bench)",
"value": ""
},
{
"key": "historic",
"description": "Layer 'Artworks' shows historic=memorial with a fixed text, namely 'This bench is a memorial for someone or something' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if (historic=memorial | inscription~.+ | memorial=bench | tourism=artwork) & amenity=bench)",
"value": "memorial"
},
{
"key": "historic",
"description": "Layer 'Artworks' shows historic= & not:historic=memorial with a fixed text, namely 'This bench is a <b>not</b> a memorial for someone or something' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') Picking this answer will delete the key historic. (This is only shown if (historic=memorial | inscription~.+ | memorial=bench | tourism=artwork) & amenity=bench)",
"value": ""
},
{
"key": "not:historic",
"description": "Layer 'Artworks' shows historic= & not:historic=memorial with a fixed text, namely 'This bench is a <b>not</b> a memorial for someone or something' and allows to pick this as a default answer (in the mapcomplete.org theme 'Ghost Signs') (This is only shown if (historic=memorial | inscription~.+ | memorial=bench | tourism=artwork) & amenity=bench)",
"value": "memorial"
} }
] ]
} }

View file

@ -5,137 +5,176 @@
"description": "On this map, you'll find hotels in your area", "description": "On this map, you'll find hotels in your area",
"project_url": "https://mapcomplete.org/hotels", "project_url": "https://mapcomplete.org/hotels",
"doc_url": "https://github.com/pietervdvn/MapComplete/tree/master/assets/themes/", "doc_url": "https://github.com/pietervdvn/MapComplete/tree/master/assets/themes/",
"icon_url": "https://mapcomplete.org/assets/layers/hotel/hotel.svg", "icon_url": "https://mapcomplete.org/assets/layers/tourism_accomodation/hotel.svg",
"contact_name": "Pieter Vander Vennet", "contact_name": "Pieter Vander Vennet",
"contact_email": "pietervdvn@posteo.net" "contact_email": "pietervdvn@posteo.net"
}, },
"tags": [ "tags": [
{ {
"key": "tourism", "key": "tourism",
"description": "The MapComplete theme Hotels has a layer Hotels showing features with this tag", "description": "The MapComplete theme Hotels has a layer Tourism accomodation showing features with this tag",
"value": "hostel"
},
{
"key": "tourism",
"description": "The MapComplete theme Hotels has a layer Tourism accomodation showing features with this tag",
"value": "hotel" "value": "hotel"
}, },
{ {
"key": "id", "key": "id",
"description": "Layer 'Hotels' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the mapcomplete.org theme 'Hotels') (This is only shown if _backend~.+ & _last_edit:passed_time<300 & (_version_number= | _version_number=1))" "description": "Layer 'Tourism accomodation' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the mapcomplete.org theme 'Hotels') (This is only shown if _backend~.+ & _last_edit:passed_time<300 & (_version_number= | _version_number=1))"
}, },
{ {
"key": "image", "key": "image",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" "description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
}, },
{ {
"key": "mapillary", "key": "mapillary",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" "description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
}, },
{ {
"key": "wikidata", "key": "wikidata",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" "description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
}, },
{ {
"key": "wikipedia", "key": "wikipedia",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" "description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
}, },
{ {
"key": "name", "key": "name",
"description": "Layer 'Hotels' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Hotels')" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Hotels')"
},
{
"key": "brand",
"description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'brand' (in the mapcomplete.org theme 'Hotels')"
},
{
"key": "nobrand",
"description": "Layer 'Tourism accomodation' shows nobrand=yes with a fixed text, namely 'Not part of a bigger brand' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "yes"
}, },
{ {
"key": "phone", "key": "phone",
"description": "Layer 'Hotels' shows and asks freeform values for key 'phone' (in the mapcomplete.org theme 'Hotels')" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'phone' (in the mapcomplete.org theme 'Hotels')"
}, },
{ {
"key": "contact:phone", "key": "contact:phone",
"description": "Layer 'Hotels' shows contact:phone~.+ with a fixed text, namely '<a href='tel:{contact:phone}'>{contact:phone}</a>' (in the mapcomplete.org theme 'Hotels')" "description": "Layer 'Tourism accomodation' shows contact:phone~.+ with a fixed text, namely '<a href='tel:{contact:phone}'>{contact:phone}</a>' (in the mapcomplete.org theme 'Hotels')"
}, },
{ {
"key": "email", "key": "email",
"description": "Layer 'Hotels' shows and asks freeform values for key 'email' (in the mapcomplete.org theme 'Hotels')" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'email' (in the mapcomplete.org theme 'Hotels')"
}, },
{ {
"key": "contact:email", "key": "contact:email",
"description": "Layer 'Hotels' shows contact:email~.+ with a fixed text, namely '<a href='mailto:{contact:email}' target='_blank' rel='noopener'>{contact:email}</a>' (in the mapcomplete.org theme 'Hotels')" "description": "Layer 'Tourism accomodation' shows contact:email~.+ with a fixed text, namely '<a href='mailto:{contact:email}' target='_blank' rel='noopener'>{contact:email}</a>' (in the mapcomplete.org theme 'Hotels')"
}, },
{ {
"key": "operator:email", "key": "operator:email",
"description": "Layer 'Hotels' shows operator:email~.+ with a fixed text, namely '<a href='mailto:{operator:email}' target='_blank' rel='noopener'>{operator:email}</a>' (in the mapcomplete.org theme 'Hotels')" "description": "Layer 'Tourism accomodation' shows operator:email~.+ with a fixed text, namely '<a href='mailto:{operator:email}' target='_blank' rel='noopener'>{operator:email}</a>' (in the mapcomplete.org theme 'Hotels')"
}, },
{ {
"key": "website", "key": "website",
"description": "Layer 'Hotels' shows and asks freeform values for key 'website' (in the mapcomplete.org theme 'Hotels')" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'website' (in the mapcomplete.org theme 'Hotels')"
}, },
{ {
"key": "contact:website", "key": "contact:website",
"description": "Layer 'Hotels' shows contact:website~.+ with a fixed text, namely '<a href='{contact:website}' rel='nofollow noopener noreferrer' target='_blank'>{contact:website}</a>' (in the mapcomplete.org theme 'Hotels')" "description": "Layer 'Tourism accomodation' shows contact:website~.+ with a fixed text, namely '<a href='{contact:website}' rel='nofollow noopener noreferrer' target='_blank'>{contact:website}</a>' (in the mapcomplete.org theme 'Hotels')"
}, },
{ {
"key": "wheelchair", "key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=designated with a fixed text, namely 'This place is specially adapted for wheelchair users' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')", "description": "Layer 'Tourism accomodation' shows wheelchair=designated with a fixed text, namely 'This place is specially adapted for wheelchair users' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "designated" "value": "designated"
}, },
{ {
"key": "wheelchair", "key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=yes with a fixed text, namely 'This place is easily reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')", "description": "Layer 'Tourism accomodation' shows wheelchair=yes with a fixed text, namely 'This place is easily reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "yes" "value": "yes"
}, },
{ {
"key": "wheelchair", "key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=limited with a fixed text, namely 'It is possible to reach this place in a wheelchair, but it is not easy' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')", "description": "Layer 'Tourism accomodation' shows wheelchair=limited with a fixed text, namely 'It is possible to reach this place in a wheelchair, but it is not easy' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "limited" "value": "limited"
}, },
{ {
"key": "wheelchair", "key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=no with a fixed text, namely 'This place is not reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')", "description": "Layer 'Tourism accomodation' shows wheelchair=no with a fixed text, namely 'This place is not reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "no" "value": "no"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=wlan with a fixed text, namely 'This place offers wireless internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')", "description": "Layer 'Tourism accomodation' shows internet_access=wlan with a fixed text, namely 'This place offers wireless internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "wlan" "value": "wlan"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=no with a fixed text, namely 'This place <b>does not</b> offer internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')", "description": "Layer 'Tourism accomodation' shows internet_access=no with a fixed text, namely 'This place <b>does not</b> offer internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "no" "value": "no"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=yes with a fixed text, namely 'This place offers internet access' (in the mapcomplete.org theme 'Hotels')", "description": "Layer 'Tourism accomodation' shows internet_access=yes with a fixed text, namely 'This place offers internet access' (in the mapcomplete.org theme 'Hotels')",
"value": "yes" "value": "yes"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=terminal with a fixed text, namely 'This place offers internet access via a terminal or computer' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')", "description": "Layer 'Tourism accomodation' shows internet_access=terminal with a fixed text, namely 'This place offers internet access via a terminal or computer' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "terminal" "value": "terminal"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=wired with a fixed text, namely 'This place offers wired internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')", "description": "Layer 'Tourism accomodation' shows internet_access=wired with a fixed text, namely 'This place offers wired internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "wired" "value": "wired"
}, },
{ {
"key": "internet_access:fee", "key": "internet_access:fee",
"description": "Layer 'Hotels' shows internet_access:fee=yes with a fixed text, namely 'There is a fee for the internet access at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access!=no & internet_access~.+)", "description": "Layer 'Tourism accomodation' shows internet_access:fee=yes with a fixed text, namely 'There is a fee for the internet access at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "yes" "value": "yes"
}, },
{ {
"key": "internet_access:fee", "key": "internet_access:fee",
"description": "Layer 'Hotels' shows internet_access:fee=no with a fixed text, namely 'Internet access is free at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access!=no & internet_access~.+)", "description": "Layer 'Tourism accomodation' shows internet_access:fee=no with a fixed text, namely 'Internet access is free at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "no" "value": "no"
}, },
{ {
"key": "internet_access:fee", "key": "internet_access:fee",
"description": "Layer 'Hotels' shows internet_access:fee=customers with a fixed text, namely 'Internet access is free at this place, for customers only' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access!=no & internet_access~.+)", "description": "Layer 'Tourism accomodation' shows internet_access:fee=customers with a fixed text, namely 'Internet access is free at this place, for customers only' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "customers" "value": "customers"
}, },
{ {
"key": "internet_access:ssid", "key": "internet_access:ssid",
"description": "Layer 'Hotels' shows and asks freeform values for key 'internet_access:ssid' (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access=wlan)" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'internet_access:ssid' (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access=wlan)"
}, },
{ {
"key": "internet_access:ssid", "key": "internet_access:ssid",
"description": "Layer 'Hotels' shows internet_access:ssid=Telekom with a fixed text, namely 'Telekom' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access=wlan)", "description": "Layer 'Tourism accomodation' shows internet_access:ssid=Telekom with a fixed text, namely 'Telekom' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels') (This is only shown if internet_access=wlan)",
"value": "Telekom" "value": "Telekom"
}, },
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=yes with a fixed text, namely 'Dogs are allowed' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "yes"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=no with a fixed text, namely 'Dogs are <b>not</b> allowed' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "no"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=leashed with a fixed text, namely 'Dogs are allowed, but they have to be leashed' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "leashed"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=unleashed with a fixed text, namely 'Dogs are allowed and can run around freely' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "unleashed"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=outside with a fixed text, namely 'Dogs are allowed only outside' and allows to pick this as a default answer (in the mapcomplete.org theme 'Hotels')",
"value": "outside"
},
{ {
"key": "amenity", "key": "amenity",
"description": "The MapComplete theme Hotels has a layer Love hotels showing features with this tag", "description": "The MapComplete theme Hotels has a layer Love hotels showing features with this tag",

View file

@ -3462,130 +3462,169 @@
}, },
{ {
"key": "tourism", "key": "tourism",
"description": "The MapComplete theme OnWheels has a layer Hotels showing features with this tag", "description": "The MapComplete theme OnWheels has a layer Tourism accomodation showing features with this tag",
"value": "hostel"
},
{
"key": "tourism",
"description": "The MapComplete theme OnWheels has a layer Tourism accomodation showing features with this tag",
"value": "hotel" "value": "hotel"
}, },
{ {
"key": "id", "key": "id",
"description": "Layer 'Hotels' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the mapcomplete.org theme 'OnWheels') (This is only shown if _backend~.+ & _last_edit:passed_time<300 & (_version_number= | _version_number=1))" "description": "Layer 'Tourism accomodation' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the mapcomplete.org theme 'OnWheels') (This is only shown if _backend~.+ & _last_edit:passed_time<300 & (_version_number= | _version_number=1))"
}, },
{ {
"key": "image", "key": "image",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" "description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
}, },
{ {
"key": "mapillary", "key": "mapillary",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" "description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
}, },
{ {
"key": "wikidata", "key": "wikidata",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" "description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
}, },
{ {
"key": "wikipedia", "key": "wikipedia",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" "description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
}, },
{ {
"key": "name", "key": "name",
"description": "Layer 'Hotels' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'OnWheels')" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'OnWheels')"
},
{
"key": "brand",
"description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'brand' (in the mapcomplete.org theme 'OnWheels')"
},
{
"key": "nobrand",
"description": "Layer 'Tourism accomodation' shows nobrand=yes with a fixed text, namely 'Not part of a bigger brand' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "yes"
}, },
{ {
"key": "phone", "key": "phone",
"description": "Layer 'Hotels' shows and asks freeform values for key 'phone' (in the mapcomplete.org theme 'OnWheels')" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'phone' (in the mapcomplete.org theme 'OnWheels')"
}, },
{ {
"key": "contact:phone", "key": "contact:phone",
"description": "Layer 'Hotels' shows contact:phone~.+ with a fixed text, namely '<a href='tel:{contact:phone}'>{contact:phone}</a>' (in the mapcomplete.org theme 'OnWheels')" "description": "Layer 'Tourism accomodation' shows contact:phone~.+ with a fixed text, namely '<a href='tel:{contact:phone}'>{contact:phone}</a>' (in the mapcomplete.org theme 'OnWheels')"
}, },
{ {
"key": "email", "key": "email",
"description": "Layer 'Hotels' shows and asks freeform values for key 'email' (in the mapcomplete.org theme 'OnWheels')" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'email' (in the mapcomplete.org theme 'OnWheels')"
}, },
{ {
"key": "contact:email", "key": "contact:email",
"description": "Layer 'Hotels' shows contact:email~.+ with a fixed text, namely '<a href='mailto:{contact:email}' target='_blank' rel='noopener'>{contact:email}</a>' (in the mapcomplete.org theme 'OnWheels')" "description": "Layer 'Tourism accomodation' shows contact:email~.+ with a fixed text, namely '<a href='mailto:{contact:email}' target='_blank' rel='noopener'>{contact:email}</a>' (in the mapcomplete.org theme 'OnWheels')"
}, },
{ {
"key": "operator:email", "key": "operator:email",
"description": "Layer 'Hotels' shows operator:email~.+ with a fixed text, namely '<a href='mailto:{operator:email}' target='_blank' rel='noopener'>{operator:email}</a>' (in the mapcomplete.org theme 'OnWheels')" "description": "Layer 'Tourism accomodation' shows operator:email~.+ with a fixed text, namely '<a href='mailto:{operator:email}' target='_blank' rel='noopener'>{operator:email}</a>' (in the mapcomplete.org theme 'OnWheels')"
}, },
{ {
"key": "website", "key": "website",
"description": "Layer 'Hotels' shows and asks freeform values for key 'website' (in the mapcomplete.org theme 'OnWheels')" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'website' (in the mapcomplete.org theme 'OnWheels')"
}, },
{ {
"key": "contact:website", "key": "contact:website",
"description": "Layer 'Hotels' shows contact:website~.+ with a fixed text, namely '<a href='{contact:website}' rel='nofollow noopener noreferrer' target='_blank'>{contact:website}</a>' (in the mapcomplete.org theme 'OnWheels')" "description": "Layer 'Tourism accomodation' shows contact:website~.+ with a fixed text, namely '<a href='{contact:website}' rel='nofollow noopener noreferrer' target='_blank'>{contact:website}</a>' (in the mapcomplete.org theme 'OnWheels')"
}, },
{ {
"key": "wheelchair", "key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=designated with a fixed text, namely 'This place is specially adapted for wheelchair users' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')", "description": "Layer 'Tourism accomodation' shows wheelchair=designated with a fixed text, namely 'This place is specially adapted for wheelchair users' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "designated" "value": "designated"
}, },
{ {
"key": "wheelchair", "key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=yes with a fixed text, namely 'This place is easily reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')", "description": "Layer 'Tourism accomodation' shows wheelchair=yes with a fixed text, namely 'This place is easily reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "yes" "value": "yes"
}, },
{ {
"key": "wheelchair", "key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=limited with a fixed text, namely 'It is possible to reach this place in a wheelchair, but it is not easy' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')", "description": "Layer 'Tourism accomodation' shows wheelchair=limited with a fixed text, namely 'It is possible to reach this place in a wheelchair, but it is not easy' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "limited" "value": "limited"
}, },
{ {
"key": "wheelchair", "key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=no with a fixed text, namely 'This place is not reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')", "description": "Layer 'Tourism accomodation' shows wheelchair=no with a fixed text, namely 'This place is not reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "no" "value": "no"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=wlan with a fixed text, namely 'This place offers wireless internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')", "description": "Layer 'Tourism accomodation' shows internet_access=wlan with a fixed text, namely 'This place offers wireless internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "wlan" "value": "wlan"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=no with a fixed text, namely 'This place <b>does not</b> offer internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')", "description": "Layer 'Tourism accomodation' shows internet_access=no with a fixed text, namely 'This place <b>does not</b> offer internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "no" "value": "no"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=yes with a fixed text, namely 'This place offers internet access' (in the mapcomplete.org theme 'OnWheels')", "description": "Layer 'Tourism accomodation' shows internet_access=yes with a fixed text, namely 'This place offers internet access' (in the mapcomplete.org theme 'OnWheels')",
"value": "yes" "value": "yes"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=terminal with a fixed text, namely 'This place offers internet access via a terminal or computer' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')", "description": "Layer 'Tourism accomodation' shows internet_access=terminal with a fixed text, namely 'This place offers internet access via a terminal or computer' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "terminal" "value": "terminal"
}, },
{ {
"key": "internet_access", "key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=wired with a fixed text, namely 'This place offers wired internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')", "description": "Layer 'Tourism accomodation' shows internet_access=wired with a fixed text, namely 'This place offers wired internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "wired" "value": "wired"
}, },
{ {
"key": "internet_access:fee", "key": "internet_access:fee",
"description": "Layer 'Hotels' shows internet_access:fee=yes with a fixed text, namely 'There is a fee for the internet access at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access!=no & internet_access~.+)", "description": "Layer 'Tourism accomodation' shows internet_access:fee=yes with a fixed text, namely 'There is a fee for the internet access at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "yes" "value": "yes"
}, },
{ {
"key": "internet_access:fee", "key": "internet_access:fee",
"description": "Layer 'Hotels' shows internet_access:fee=no with a fixed text, namely 'Internet access is free at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access!=no & internet_access~.+)", "description": "Layer 'Tourism accomodation' shows internet_access:fee=no with a fixed text, namely 'Internet access is free at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "no" "value": "no"
}, },
{ {
"key": "internet_access:fee", "key": "internet_access:fee",
"description": "Layer 'Hotels' shows internet_access:fee=customers with a fixed text, namely 'Internet access is free at this place, for customers only' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access!=no & internet_access~.+)", "description": "Layer 'Tourism accomodation' shows internet_access:fee=customers with a fixed text, namely 'Internet access is free at this place, for customers only' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "customers" "value": "customers"
}, },
{ {
"key": "internet_access:ssid", "key": "internet_access:ssid",
"description": "Layer 'Hotels' shows and asks freeform values for key 'internet_access:ssid' (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access=wlan)" "description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'internet_access:ssid' (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access=wlan)"
}, },
{ {
"key": "internet_access:ssid", "key": "internet_access:ssid",
"description": "Layer 'Hotels' shows internet_access:ssid=Telekom with a fixed text, namely 'Telekom' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access=wlan)", "description": "Layer 'Tourism accomodation' shows internet_access:ssid=Telekom with a fixed text, namely 'Telekom' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels') (This is only shown if internet_access=wlan)",
"value": "Telekom" "value": "Telekom"
}, },
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=yes with a fixed text, namely 'Dogs are allowed' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "yes"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=no with a fixed text, namely 'Dogs are <b>not</b> allowed' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "no"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=leashed with a fixed text, namely 'Dogs are allowed, but they have to be leashed' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "leashed"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=unleashed with a fixed text, namely 'Dogs are allowed and can run around freely' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "unleashed"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=outside with a fixed text, namely 'Dogs are allowed only outside' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
"value": "outside"
},
{ {
"key": "office", "key": "office",
"description": "The MapComplete theme OnWheels has a layer governments showing features with this tag", "description": "The MapComplete theme OnWheels has a layer governments showing features with this tag",

View file

@ -10935,132 +10935,6 @@
"key": "opening_hours:visitors", "key": "opening_hours:visitors",
"description": "Layer 'Hospitals' shows and asks freeform values for key 'opening_hours:visitors' (in the mapcomplete.org theme 'Personal theme')" "description": "Layer 'Hospitals' shows and asks freeform values for key 'opening_hours:visitors' (in the mapcomplete.org theme 'Personal theme')"
}, },
{
"key": "tourism",
"description": "The MapComplete theme Personal theme has a layer Hotels showing features with this tag",
"value": "hotel"
},
{
"key": "id",
"description": "Layer 'Hotels' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the mapcomplete.org theme 'Personal theme') (This is only shown if _backend~.+ & _last_edit:passed_time<300 & (_version_number= | _version_number=1))"
},
{
"key": "image",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "mapillary",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "wikidata",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "wikipedia",
"description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "name",
"description": "Layer 'Hotels' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "phone",
"description": "Layer 'Hotels' shows and asks freeform values for key 'phone' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "contact:phone",
"description": "Layer 'Hotels' shows contact:phone~.+ with a fixed text, namely '<a href='tel:{contact:phone}'>{contact:phone}</a>' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "email",
"description": "Layer 'Hotels' shows and asks freeform values for key 'email' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "contact:email",
"description": "Layer 'Hotels' shows contact:email~.+ with a fixed text, namely '<a href='mailto:{contact:email}' target='_blank' rel='noopener'>{contact:email}</a>' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "operator:email",
"description": "Layer 'Hotels' shows operator:email~.+ with a fixed text, namely '<a href='mailto:{operator:email}' target='_blank' rel='noopener'>{operator:email}</a>' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "website",
"description": "Layer 'Hotels' shows and asks freeform values for key 'website' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "contact:website",
"description": "Layer 'Hotels' shows contact:website~.+ with a fixed text, namely '<a href='{contact:website}' rel='nofollow noopener noreferrer' target='_blank'>{contact:website}</a>' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=designated with a fixed text, namely 'This place is specially adapted for wheelchair users' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "designated"
},
{
"key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=yes with a fixed text, namely 'This place is easily reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "yes"
},
{
"key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=limited with a fixed text, namely 'It is possible to reach this place in a wheelchair, but it is not easy' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "limited"
},
{
"key": "wheelchair",
"description": "Layer 'Hotels' shows wheelchair=no with a fixed text, namely 'This place is not reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "no"
},
{
"key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=wlan with a fixed text, namely 'This place offers wireless internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "wlan"
},
{
"key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=no with a fixed text, namely 'This place <b>does not</b> offer internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "no"
},
{
"key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=yes with a fixed text, namely 'This place offers internet access' (in the mapcomplete.org theme 'Personal theme')",
"value": "yes"
},
{
"key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=terminal with a fixed text, namely 'This place offers internet access via a terminal or computer' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "terminal"
},
{
"key": "internet_access",
"description": "Layer 'Hotels' shows internet_access=wired with a fixed text, namely 'This place offers wired internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "wired"
},
{
"key": "internet_access:fee",
"description": "Layer 'Hotels' shows internet_access:fee=yes with a fixed text, namely 'There is a fee for the internet access at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "yes"
},
{
"key": "internet_access:fee",
"description": "Layer 'Hotels' shows internet_access:fee=no with a fixed text, namely 'Internet access is free at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "no"
},
{
"key": "internet_access:fee",
"description": "Layer 'Hotels' shows internet_access:fee=customers with a fixed text, namely 'Internet access is free at this place, for customers only' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "customers"
},
{
"key": "internet_access:ssid",
"description": "Layer 'Hotels' shows and asks freeform values for key 'internet_access:ssid' (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access=wlan)"
},
{
"key": "internet_access:ssid",
"description": "Layer 'Hotels' shows internet_access:ssid=Telekom with a fixed text, namely 'Telekom' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access=wlan)",
"value": "Telekom"
},
{ {
"key": "emergency", "key": "emergency",
"description": "The MapComplete theme Personal theme has a layer Map of hydrants showing features with this tag", "description": "The MapComplete theme Personal theme has a layer Map of hydrants showing features with this tag",
@ -18999,6 +18873,171 @@
"description": "Layer 'Tool libraries' shows fee=donation with a fixed text, namely 'A donation can be given when borrowing tools' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')", "description": "Layer 'Tool libraries' shows fee=donation with a fixed text, namely 'A donation can be given when borrowing tools' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "donation" "value": "donation"
}, },
{
"key": "tourism",
"description": "The MapComplete theme Personal theme has a layer Tourism accomodation showing features with this tag",
"value": "hostel"
},
{
"key": "tourism",
"description": "The MapComplete theme Personal theme has a layer Tourism accomodation showing features with this tag",
"value": "hotel"
},
{
"key": "id",
"description": "Layer 'Tourism accomodation' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the mapcomplete.org theme 'Personal theme') (This is only shown if _backend~.+ & _last_edit:passed_time<300 & (_version_number= | _version_number=1))"
},
{
"key": "image",
"description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "mapillary",
"description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "wikidata",
"description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "wikipedia",
"description": "The layer 'Tourism accomodation allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary"
},
{
"key": "name",
"description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "brand",
"description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'brand' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "nobrand",
"description": "Layer 'Tourism accomodation' shows nobrand=yes with a fixed text, namely 'Not part of a bigger brand' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "yes"
},
{
"key": "phone",
"description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'phone' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "contact:phone",
"description": "Layer 'Tourism accomodation' shows contact:phone~.+ with a fixed text, namely '<a href='tel:{contact:phone}'>{contact:phone}</a>' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "email",
"description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'email' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "contact:email",
"description": "Layer 'Tourism accomodation' shows contact:email~.+ with a fixed text, namely '<a href='mailto:{contact:email}' target='_blank' rel='noopener'>{contact:email}</a>' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "operator:email",
"description": "Layer 'Tourism accomodation' shows operator:email~.+ with a fixed text, namely '<a href='mailto:{operator:email}' target='_blank' rel='noopener'>{operator:email}</a>' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "website",
"description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'website' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "contact:website",
"description": "Layer 'Tourism accomodation' shows contact:website~.+ with a fixed text, namely '<a href='{contact:website}' rel='nofollow noopener noreferrer' target='_blank'>{contact:website}</a>' (in the mapcomplete.org theme 'Personal theme')"
},
{
"key": "wheelchair",
"description": "Layer 'Tourism accomodation' shows wheelchair=designated with a fixed text, namely 'This place is specially adapted for wheelchair users' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "designated"
},
{
"key": "wheelchair",
"description": "Layer 'Tourism accomodation' shows wheelchair=yes with a fixed text, namely 'This place is easily reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "yes"
},
{
"key": "wheelchair",
"description": "Layer 'Tourism accomodation' shows wheelchair=limited with a fixed text, namely 'It is possible to reach this place in a wheelchair, but it is not easy' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "limited"
},
{
"key": "wheelchair",
"description": "Layer 'Tourism accomodation' shows wheelchair=no with a fixed text, namely 'This place is not reachable with a wheelchair' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "no"
},
{
"key": "internet_access",
"description": "Layer 'Tourism accomodation' shows internet_access=wlan with a fixed text, namely 'This place offers wireless internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "wlan"
},
{
"key": "internet_access",
"description": "Layer 'Tourism accomodation' shows internet_access=no with a fixed text, namely 'This place <b>does not</b> offer internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "no"
},
{
"key": "internet_access",
"description": "Layer 'Tourism accomodation' shows internet_access=yes with a fixed text, namely 'This place offers internet access' (in the mapcomplete.org theme 'Personal theme')",
"value": "yes"
},
{
"key": "internet_access",
"description": "Layer 'Tourism accomodation' shows internet_access=terminal with a fixed text, namely 'This place offers internet access via a terminal or computer' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "terminal"
},
{
"key": "internet_access",
"description": "Layer 'Tourism accomodation' shows internet_access=wired with a fixed text, namely 'This place offers wired internet access' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "wired"
},
{
"key": "internet_access:fee",
"description": "Layer 'Tourism accomodation' shows internet_access:fee=yes with a fixed text, namely 'There is a fee for the internet access at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "yes"
},
{
"key": "internet_access:fee",
"description": "Layer 'Tourism accomodation' shows internet_access:fee=no with a fixed text, namely 'Internet access is free at this place' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "no"
},
{
"key": "internet_access:fee",
"description": "Layer 'Tourism accomodation' shows internet_access:fee=customers with a fixed text, namely 'Internet access is free at this place, for customers only' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access!=no & internet_access~.+)",
"value": "customers"
},
{
"key": "internet_access:ssid",
"description": "Layer 'Tourism accomodation' shows and asks freeform values for key 'internet_access:ssid' (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access=wlan)"
},
{
"key": "internet_access:ssid",
"description": "Layer 'Tourism accomodation' shows internet_access:ssid=Telekom with a fixed text, namely 'Telekom' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme') (This is only shown if internet_access=wlan)",
"value": "Telekom"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=yes with a fixed text, namely 'Dogs are allowed' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "yes"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=no with a fixed text, namely 'Dogs are <b>not</b> allowed' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "no"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=leashed with a fixed text, namely 'Dogs are allowed, but they have to be leashed' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "leashed"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=unleashed with a fixed text, namely 'Dogs are allowed and can run around freely' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "unleashed"
},
{
"key": "dog",
"description": "Layer 'Tourism accomodation' shows dog=outside with a fixed text, namely 'Dogs are allowed only outside' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
"value": "outside"
},
{ {
"key": "type", "key": "type",
"description": "The MapComplete theme Personal theme has a layer Bus lines showing features with this tag", "description": "The MapComplete theme Personal theme has a layer Bus lines showing features with this tag",

View file

@ -338,7 +338,7 @@ _This tagrendering has no question and is thus read-only_
### menu-website ### menu-website
The question is `On what webpage is the menu published?` The question is `On what webpage is the menu published?`
*{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,)}* is shown if `website:menu` is set *{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,,)}* is shown if `website:menu` is set

View file

@ -11,6 +11,7 @@ This theme contains the following layers:
- [ghostsigns (defined in this theme)](#ghostsigns) - [ghostsigns (defined in this theme)](#ghostsigns)
- [advertising_wall_paintings (defined in this theme)](#advertising_wall_paintings) - [advertising_wall_paintings (defined in this theme)](#advertising_wall_paintings)
- [artwork_on_wall (defined in this theme)](#artwork_on_wall)
- [walls_and_buildings](../Layers/walls_and_buildings.md) - [walls_and_buildings](../Layers/walls_and_buildings.md)
@ -51,6 +52,35 @@ Available languages:
+ [move-button](#move-button) + [move-button](#move-button)
+ [delete-button](#delete-button) + [delete-button](#delete-button)
+ [lod](#lod) + [lod](#lod)
4. [artwork_on_wall](#artwork_on_wall)
- [Basic tags for this layer](#basic-tags-for-this-layer)
- [Supported attributes](#supported-attributes)
+ [historic_or_not](#historic_or_not)
+ [images](#images)
+ [artwork-artwork_type](#artwork-artwork_type)
+ [artwork-artist-wikidata](#artwork-artist-wikidata)
+ [artwork-artist_name](#artwork-artist_name)
+ [artwork-website](#artwork-website)
+ [wikipedia](#wikipedia)
+ [artwork_subject](#artwork_subject)
+ [doubles_as_memorial](#doubles_as_memorial)
+ [memorial-type](#memorial-type)
+ [inscription](#inscription)
+ [doubles_as_bench](#doubles_as_bench)
+ [bench-backrest](#bench-backrest)
+ [bench-armrest](#bench-armrest)
+ [bench-seats](#bench-seats)
+ [bench-material](#bench-material)
+ [bench-direction](#bench-direction)
+ [bench-colour](#bench-colour)
+ [bench-survey:date](#bench-surveydate)
+ [bench-inscription](#bench-inscription)
+ [bench-memorial](#bench-memorial)
+ [leftover-questions](#leftover-questions)
+ [move-button](#move-button)
+ [delete-button](#delete-button)
+ [lod](#lod)
- [Filters](#filters)
# Layers defined in this theme configuration file # Layers defined in this theme configuration file
These layers can not be reused in different themes. These layers can not be reused in different themes.
@ -352,6 +382,421 @@ _This tagrendering has no question and is thus read-only_
This tagrendering has labels This tagrendering has labels
`added_by_default` `added_by_default`
# artwork_on_wall
This layer is based on [artwork](../Layers/artwork.md)
An open map of statues, busts, graffitis and other artwork all over the world
- This layer is shown at zoomlevel **16** and higher
No themes use this layer
## Basic tags for this layer
Elements must match **all** of the following expressions:
0. <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dartwork' target='_blank'>artwork</a>
1. <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmural' target='_blank'>mural</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dgraffiti' target='_blank'>graffiti</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmosaic' target='_blank'>mosaic</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Drelief' target='_blank'>relief</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dpainting' target='_blank'>painting</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmural_painting' target='_blank'>mural_painting</a>
[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B%28%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22mural%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22graffiti%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22mosaic%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22relief%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22painting%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D%5B%22artwork_type%22%3D%22mural_painting%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%29%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B)
## Supported attributes
**Warning:**,this quick overview is incomplete,
| attribute | type | values which are supported by this layer |
-----|-----|----- |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/historic#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/historic/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [historic](https://wiki.openstreetmap.org/wiki/Key:historic) | Multiple choice | [advertising](https://wiki.openstreetmap.org/wiki/Tag:historic%3Dadvertising) [](https://wiki.openstreetmap.org/wiki/Tag:historic%3D) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/artwork_type#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/artwork_type/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [artwork_type](https://wiki.openstreetmap.org/wiki/Key:artwork_type) | [string](../SpecialInputElements.md#string) | [architecture](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Darchitecture) [mural](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmural) [painting](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dpainting) [sculpture](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dsculpture) [statue](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dstatue) [bust](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dbust) [stone](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dstone) [installation](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dinstallation) [graffiti](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dgraffiti) [relief](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Drelief) [azulejo](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dazulejo) [tilework](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dtilework) [woodcarving](https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dwoodcarving) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/artist:wikidata#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/artist%3Awikidata/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [artist:wikidata](https://wiki.openstreetmap.org/wiki/Key:artist:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/artist_name#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/artist_name/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [artist_name](https://wiki.openstreetmap.org/wiki/Key:artist_name) | [string](../SpecialInputElements.md#string) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/website#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/website/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/wikidata#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/wikidata/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [wikidata](https://wiki.openstreetmap.org/wiki/Key:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/subject:wikidata#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/subject%3Awikidata/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [subject:wikidata](https://wiki.openstreetmap.org/wiki/Key:subject:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/historic#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/historic/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [historic](https://wiki.openstreetmap.org/wiki/Key:historic) | Multiple choice | [memorial](https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial) [](https://wiki.openstreetmap.org/wiki/Tag:historic%3D) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/memorial#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/memorial/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [memorial](https://wiki.openstreetmap.org/wiki/Key:memorial) | [string](../SpecialInputElements.md#string) | [statue](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstatue) [plaque](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dplaque) [bench](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbench) [ghost_bike](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dghost_bike) [stolperstein](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstolperstein) [stele](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstele) [stone](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstone) [bust](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbust) [sculpture](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dsculpture) [obelisk](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dobelisk) [cross](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dcross) [blue_plaque](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dblue_plaque) [tank](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dtank) [tree](https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dtree) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/inscription#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/inscription/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [text](../SpecialInputElements.md#text) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/amenity#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/amenity/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [bench](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench) [](https://wiki.openstreetmap.org/wiki/Tag:amenity%3D) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/backrest#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/backrest/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [backrest](https://wiki.openstreetmap.org/wiki/Key:backrest) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes) [yes](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dno) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/armrest#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/armrest/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [armrest](https://wiki.openstreetmap.org/wiki/Key:armrest) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:armrest%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:armrest%3Dno) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/seats#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/seats/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [seats](https://wiki.openstreetmap.org/wiki/Key:seats) | [nat](../SpecialInputElements.md#nat) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/material#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/material/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [material](https://wiki.openstreetmap.org/wiki/Key:material) | [string](../SpecialInputElements.md#string) | [wood](https://wiki.openstreetmap.org/wiki/Tag:material%3Dwood) [metal](https://wiki.openstreetmap.org/wiki/Tag:material%3Dmetal) [stone](https://wiki.openstreetmap.org/wiki/Tag:material%3Dstone) [concrete](https://wiki.openstreetmap.org/wiki/Tag:material%3Dconcrete) [plastic](https://wiki.openstreetmap.org/wiki/Tag:material%3Dplastic) [steel](https://wiki.openstreetmap.org/wiki/Tag:material%3Dsteel) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/direction#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/direction/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [direction](https://wiki.openstreetmap.org/wiki/Key:direction) | [direction](../SpecialInputElements.md#direction) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/colour#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/colour/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [colour](https://wiki.openstreetmap.org/wiki/Key:colour) | [color](../SpecialInputElements.md#color) | [brown](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dbrown) [green](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dgreen) [gray](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dgray) [white](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dwhite) [red](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dred) [black](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dblack) [blue](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dblue) [yellow](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dyellow) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/survey:date#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/survey%3Adate/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [survey:date](https://wiki.openstreetmap.org/wiki/Key:survey:date) | [date](../SpecialInputElements.md#date) | [](https://wiki.openstreetmap.org/wiki/Tag:survey:date%3D) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/inscription#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/inscription/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [text](../SpecialInputElements.md#text) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/historic#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/historic/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [historic](https://wiki.openstreetmap.org/wiki/Key:historic) | Multiple choice | [memorial](https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial) [](https://wiki.openstreetmap.org/wiki/Tag:historic%3D) |
### historic_or_not
The question is `Is this artwork a historic advertisement?`
- *This artwork is a historic advertisement* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dadvertising' target='_blank'>advertising</a>
- *This artwork is not a historic advertisement* is shown if with historic=
### images
This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` and shows the button to upload new images
_This tagrendering has no question and is thus read-only_
*{image_carousel()}{image_upload()}*
### artwork-artwork_type
The question is `What is the type of this artwork?`
*This is a {artwork_type}* is shown if `artwork_type` is set
- *Architecture* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Darchitecture' target='_blank'>architecture</a>
- *Mural* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dmural' target='_blank'>mural</a>
- *Painting* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dpainting' target='_blank'>painting</a>
- *Sculpture* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dsculpture' target='_blank'>sculpture</a>
- *Statue* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dstatue' target='_blank'>statue</a>
- *Bust* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dbust' target='_blank'>bust</a>
- *Stone* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dstone' target='_blank'>stone</a>
- *Installation* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dinstallation' target='_blank'>installation</a>
- *Graffiti* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dgraffiti' target='_blank'>graffiti</a>
- *Relief* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Drelief' target='_blank'>relief</a>
- *Azulejo (Spanish decorative tilework)* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dazulejo' target='_blank'>azulejo</a>
- *Tilework* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dtilework' target='_blank'>tilework</a>
- *Woodcarving* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:artwork_type' target='_blank'>artwork_type</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:artwork_type%3Dwoodcarving' target='_blank'>woodcarving</a>
This tagrendering has labels
`artwork-question`
### artwork-artist-wikidata
The question is `Who made this artwork?`
*This artwork was made by {wikidata_label(artist:wikidata):font-weight:bold}<br/>{wikipedia(artist:wikidata)}* is shown if `artist:wikidata` is set
This tagrendering has labels
`artwork-question`
### artwork-artist_name
The question is `Which artist created this?`
*Created by {artist_name}* is shown if `artist_name` is set
This tagrendering has labels
`artwork-question`
### artwork-website
The question is `Is there a website with more information about this artwork?`
*{link(More information on this website,&LBRACEwebsite&RBRACE,,,,)}* is shown if `website` is set
This tagrendering has labels
`artwork-question`
### wikipedia
Shows a wikipedia box with the corresponding wikipedia article; the wikidata-item link can be changed by a contributor
The question is `What is the corresponding Wikidata entity?`
*{wikipedia():max-height:25rem}* is shown if `wikidata` is set
- *{wikipedia():max-height:25rem}* is shown if with wikipedia~.+. _This option cannot be chosen as answer_
- *No Wikipedia page has been linked yet* is shown if with wikidata=. _This option cannot be chosen as answer_
### artwork_subject
The question is `What does this artwork depict?`
*This artwork depicts {wikidata_label(subject:wikidata)}{wikipedia(subject:wikidata)}* is shown if `subject:wikidata` is set
This tagrendering is only visible in the popup if the following condition is met: subject:wikidata~.+
This tagrendering has labels
`artwork-question`
### doubles_as_memorial
The question is `Does this artwork serve as a memorial?`
- *This artwork also serves as a memorial* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a>
- *This artwork does not serve as a bench* is shown if with historic=
### memorial-type
The question is `What type of memorial is this?`
*This is a {memorial}* is shown if `memorial` is set
- *This is a statue* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstatue' target='_blank'>statue</a>
- *This is a plaque* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dplaque' target='_blank'>plaque</a>
- *This is a commemorative bench* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbench' target='_blank'>bench</a>
- *This is a ghost bike - a bicycle painted white to remember a cyclist whom deceased because of a car crash* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dghost_bike' target='_blank'>ghost_bike</a>
- *This is a stolperstein (stumbing stone)* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstolperstein' target='_blank'>stolperstein</a>
- *This is a stele* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstele' target='_blank'>stele</a>
- *This is a memorial stone* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dstone' target='_blank'>stone</a>
- *This is a bust* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbust' target='_blank'>bust</a>
- *This is a sculpture* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dsculpture' target='_blank'>sculpture</a>
- *This is an obelisk* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dobelisk' target='_blank'>obelisk</a>
- *This is a cross* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dcross' target='_blank'>cross</a>
- *This is a blue plaque* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dblue_plaque' target='_blank'>blue_plaque</a>
- *This is a historic tank, permanently placed in public space as memorial* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dtank' target='_blank'>tank</a>
- *This is a memorial tree* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dtree' target='_blank'>tree</a>
- *This is a gravestone; the person is buried here* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dtomb' target='_blank'>tomb</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a>
This tagrendering has labels
`memorial-questions`
### inscription
The question is `What is the inscription on this memorial?`
*The inscription on this memorial reads: <p><i>{inscription}<i></p>* is shown if `inscription` is set
- *This memorial does not have an inscription* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:not:inscription' target='_blank'>not:inscription</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:not:inscription%3Dyes' target='_blank'>yes</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a> & memorial!=bench
This tagrendering has labels
`memorial-questions`
### doubles_as_bench
The question is `Does this artwork serve as a bench?`
- *This artwork also serves as a bench* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
- *This artwork does not serve as a bench* is shown if with amenity=
- *This artwork does not serve as a bench* is shown if with amenity!=bench. _This option cannot be chosen as answer_
### bench-backrest
The question is `Does this bench have a backrest?`
- <img src='https://raw.githubusercontent.com/pietervdvn/MapComplete/develop/./assets/layers/bench/two_sided.svg' style='width: 3rem; height: 3rem'> *This bench is two-sided and shares the backrest* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:backrest' target='_blank'>backrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes' target='_blank'>yes</a> & <a href='https://wiki.openstreetmap.org/wiki/Key:two_sided' target='_blank'>two_sided</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:two_sided%3Dyes' target='_blank'>yes</a>
- *This bench does have a backrest* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:backrest' target='_blank'>backrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes' target='_blank'>yes</a>
- *This bench does <b>not</b> have a backrest* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:backrest' target='_blank'>backrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dno' target='_blank'>no</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-armrest
The question is `Does this bench have one or more armrests?`
- *This bench does have one or more armrests* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:armrest' target='_blank'>armrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:armrest%3Dyes' target='_blank'>yes</a>
- *This bench does <b>not</b> have any armrests* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:armrest' target='_blank'>armrest</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:armrest%3Dno' target='_blank'>no</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-seats
The question is `How many seats does this bench have?`
*This bench has {seats} seats* is shown if `seats` is set
- *This bench does not have separated seats* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:seats:separated' target='_blank'>seats:separated</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:seats:separated%3Dno' target='_blank'>no</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-material
The question is `What is the bench (seating) made from?`
*Material: {material}* is shown if `material` is set
- *The seating is made from wood* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dwood' target='_blank'>wood</a>
- *The seating is made from metal* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dmetal' target='_blank'>metal</a>
- *The seating is made from stone* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dstone' target='_blank'>stone</a>
- *The seating is made from concrete* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dconcrete' target='_blank'>concrete</a>
- *The seating is made from plastic* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dplastic' target='_blank'>plastic</a>
- *The seating is made from steel* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:material' target='_blank'>material</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:material%3Dsteel' target='_blank'>steel</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-direction
The question is `In which direction are you looking when sitting on the bench?`
*When sitting on the bench, one looks towards {direction}°.* is shown if `direction` is set
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a> & two_sided!=yes
This tagrendering has labels
`bench-questions`
### bench-colour
The question is `Which colour does this bench have?`
*Colour: {colour}* is shown if `colour` is set
- *Colour: brown* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dbrown' target='_blank'>brown</a>
- *Colour: green* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dgreen' target='_blank'>green</a>
- *Colour: gray* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dgray' target='_blank'>gray</a>
- *Colour: white* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dwhite' target='_blank'>white</a>
- *Colour: red* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dred' target='_blank'>red</a>
- *Colour: black* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dblack' target='_blank'>black</a>
- *Colour: blue* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dblue' target='_blank'>blue</a>
- *Colour: yellow* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:colour' target='_blank'>colour</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:colour%3Dyellow' target='_blank'>yellow</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-survey:date
The question is `When was this bench last surveyed?`
*This bench was last surveyed on {survey:date}* is shown if `survey:date` is set
- *Surveyed today!* is shown if with survey:date=
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-inscription
The question is `Does this bench have an inscription?`
*This bench has the following inscription:<br/><p><i>{inscription}</i></p>* is shown if `inscription` is set
- *This bench does not have an inscription* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:not:inscription' target='_blank'>not:inscription</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:not:inscription%3Dyes' target='_blank'>yes</a>
- *This bench <span class='subtle'>probably</span> does not not have an inscription* is shown if with inscription=. _This option cannot be chosen as answer_
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a>
This tagrendering has labels
`bench-questions`
### bench-memorial
The question is `Does this bench act as memorial for someone or something?`
- *This bench is a memorial for someone or something* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a>
- *This bench is a <b>not</b> a memorial for someone or something* is shown if with historic= & <a href='https://wiki.openstreetmap.org/wiki/Key:not:historic' target='_blank'>not:historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:not:historic%3Dmemorial' target='_blank'>memorial</a>
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench' target='_blank'>bench</a> & (<a href='https://wiki.openstreetmap.org/wiki/Key:historic' target='_blank'>historic</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:historic%3Dmemorial' target='_blank'>memorial</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:memorial' target='_blank'>memorial</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:memorial%3Dbench' target='_blank'>bench</a> | <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dartwork' target='_blank'>artwork</a> | inscription~.+)
This tagrendering has labels
`bench-questions`
### leftover-questions
_This tagrendering has no question and is thus read-only_
*{questions( ,)}*
### move-button
_This tagrendering has no question and is thus read-only_
*{move_button()}*
### delete-button
_This tagrendering has no question and is thus read-only_
*{delete_button()}*
### lod
_This tagrendering has no question and is thus read-only_
*{linked_data_from_website()}*
This tagrendering has labels
`added_by_default`
## Filters
| id | question | osmTags |
-----|-----|----- |
| has_image.0 | *With and without images* (default) | |
| has_image.1 | Has at least one image | image~.+ | image:0~.+ | image:1~.+ | image:2~.+ | image:3~.+ | mapillary~.+ |
| has_image.2 | Probably does not have an image | image= & image:0= & image:1= & image:2= & image:3= & mapillary= |
| id | question | osmTags |
-----|-----|----- |
| artwork-artwork_type.0 | *What is the type of this artwork?* (default) | |
| artwork-artwork_type.1 | Architecture | artwork_type=architecture |
| artwork-artwork_type.2 | Mural | artwork_type=mural |
| artwork-artwork_type.3 | Painting | artwork_type=painting |
| artwork-artwork_type.4 | Sculpture | artwork_type=sculpture |
| artwork-artwork_type.5 | Statue | artwork_type=statue |
| artwork-artwork_type.6 | Bust | artwork_type=bust |
| artwork-artwork_type.7 | Stone | artwork_type=stone |
| artwork-artwork_type.8 | Installation | artwork_type=installation |
| artwork-artwork_type.9 | Graffiti | artwork_type=graffiti |
| artwork-artwork_type.10 | Relief | artwork_type=relief |
| artwork-artwork_type.11 | Azulejo (Spanish decorative tilework) | artwork_type=azulejo |
| artwork-artwork_type.12 | Tilework | artwork_type=tilework |
| artwork-artwork_type.13 | Woodcarving | artwork_type=woodcarving |
This document is autogenerated from [assets/themes/ghostsigns/ghostsigns.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/ghostsigns/ghostsigns.json) This document is autogenerated from [assets/themes/ghostsigns/ghostsigns.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/ghostsigns/ghostsigns.json)

View file

@ -420,7 +420,7 @@ _This tagrendering has no question and is thus read-only_
### menu-website ### menu-website
The question is `On what webpage is the menu published?` The question is `On what webpage is the menu published?`
*{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,)}* is shown if `website:menu` is set *{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,,)}* is shown if `website:menu` is set

View file

@ -9,7 +9,7 @@ The theme introduction reads:
This theme contains the following layers: This theme contains the following layers:
- [hotel](../Layers/hotel.md) - [tourism_accomodation](../Layers/tourism_accomodation.md)
- [love_hotel](../Layers/love_hotel.md) - [love_hotel](../Layers/love_hotel.md)

View file

@ -418,7 +418,7 @@ _This tagrendering has no question and is thus read-only_
### menu-website ### menu-website
The question is `On what webpage is the menu published?` The question is `On what webpage is the menu published?`
*{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,)}* is shown if `website:menu` is set *{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,,)}* is shown if `website:menu` is set

View file

@ -26,7 +26,7 @@ This theme contains the following layers:
- [reception_desk](../Layers/reception_desk.md) - [reception_desk](../Layers/reception_desk.md)
- [walls_and_buildings](../Layers/walls_and_buildings.md) - [walls_and_buildings](../Layers/walls_and_buildings.md)
- [elevator](../Layers/elevator.md) - [elevator](../Layers/elevator.md)
- [hotel](../Layers/hotel.md) - [tourism_accomodation](../Layers/tourism_accomodation.md)
- [governments](../Layers/governments.md) - [governments](../Layers/governments.md)
- [current_view](../Layers/current_view.md) - [current_view](../Layers/current_view.md)
- [maproulette_challenge](../Layers/maproulette_challenge.md) - [maproulette_challenge](../Layers/maproulette_challenge.md)

View file

@ -18,7 +18,7 @@ This theme contains the following layers:
- [erotic_cinema (defined in this theme)](#erotic_cinema) - [erotic_cinema (defined in this theme)](#erotic_cinema)
- [cinema](../Layers/cinema.md) - [cinema](../Layers/cinema.md)
- [love_hotel](../Layers/love_hotel.md) - [love_hotel](../Layers/love_hotel.md)
- [hotel](../Layers/hotel.md) - [tourism_accomodation](../Layers/tourism_accomodation.md)
Available languages: Available languages:

View file

@ -67,7 +67,6 @@ This theme contains the following layers:
- [guidepost](../Layers/guidepost.md) - [guidepost](../Layers/guidepost.md)
- [hackerspace](../Layers/hackerspace.md) - [hackerspace](../Layers/hackerspace.md)
- [hospital](../Layers/hospital.md) - [hospital](../Layers/hospital.md)
- [hotel](../Layers/hotel.md)
- [hydrant](../Layers/hydrant.md) - [hydrant](../Layers/hydrant.md)
- [ice_cream](../Layers/ice_cream.md) - [ice_cream](../Layers/ice_cream.md)
- [indoors](../Layers/indoors.md) - [indoors](../Layers/indoors.md)
@ -121,6 +120,7 @@ This theme contains the following layers:
- [toilet](../Layers/toilet.md) - [toilet](../Layers/toilet.md)
- [toilet_at_amenity](../Layers/toilet_at_amenity.md) - [toilet_at_amenity](../Layers/toilet_at_amenity.md)
- [tool_library](../Layers/tool_library.md) - [tool_library](../Layers/tool_library.md)
- [tourism_accomodation](../Layers/tourism_accomodation.md)
- [transit_routes](../Layers/transit_routes.md) - [transit_routes](../Layers/transit_routes.md)
- [transit_stops](../Layers/transit_stops.md) - [transit_stops](../Layers/transit_stops.md)
- [tree_node](../Layers/tree_node.md) - [tree_node](../Layers/tree_node.md)

View file

@ -394,7 +394,7 @@ _This tagrendering has no question and is thus read-only_
### menu-website ### menu-website
The question is `On what webpage is the menu published?` The question is `On what webpage is the menu published?`
*{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,)}* is shown if `website:menu` is set *{link(Consult the menu,&LBRACEwebsite:menu&RBRACE,,,,)}* is shown if `website:menu` is set

View file

@ -1,192 +0,0 @@
[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources)
## Sidewalks ( [sidewalks](https://mapcomplete.org/sidewalks) )
_This document details some technical information about this MapComplete theme, mostly about the attributes used in the theme. Various links point toward more information about the attributes, e.g. to the OpenStreetMap-wiki, to TagInfo or tools creating statistics_
The theme introduction reads:
> Experimental theme
This theme contains the following layers:
- [sidewalks (defined in this theme)](#sidewalks)
Available languages:
- en
- ru
- nl
- de
- ca
- es
- fr
- nb_NO
- it
- da
- pa_PK
- cs
- zh_Hant
- eu
- pl
# Table of contents
- [Sidewalks ( sidewalks )](#sidewalks-(-sidewalks-))
1. [Layers defined in this theme configuration file](#layers-defined-in-this-theme-configuration-file)
2. [sidewalks](#sidewalks)
- [Basic tags for this layer](#basic-tags-for-this-layer)
- [Supported attributes](#supported-attributes)
+ [streetname](#streetname)
+ [sidewalk_minimap_left](#sidewalk_minimap_left)
+ [has_sidewalk_left](#has_sidewalk_left)
+ [sidewalk_width_left](#sidewalk_width_left)
+ [sidewalk_minimap_right](#sidewalk_minimap_right)
+ [has_sidewalk_right](#has_sidewalk_right)
+ [sidewalk_width_right](#sidewalk_width_right)
+ [leftover-questions](#leftover-questions)
+ [split_button](#split_button)
+ [lod](#lod)
# Layers defined in this theme configuration file
These layers can not be reused in different themes.
# sidewalks
Layer showing sidewalks of highways
- This layer is shown at zoomlevel **12** and higher
No themes use this layer
## Basic tags for this layer
Elements must match **any** of the following expressions:
- <a href='https://wiki.openstreetmap.org/wiki/Key:highway' target='_blank'>highway</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:highway%3Dresidential' target='_blank'>residential</a>
- <a href='https://wiki.openstreetmap.org/wiki/Key:highway' target='_blank'>highway</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:highway%3Dunclassified' target='_blank'>unclassified</a>
- <a href='https://wiki.openstreetmap.org/wiki/Key:highway' target='_blank'>highway</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:highway%3Dtertiary' target='_blank'>tertiary</a>
- <a href='https://wiki.openstreetmap.org/wiki/Key:highway' target='_blank'>highway</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:highway%3Dsecondary' target='_blank'>secondary</a>
[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B%28%20%20%20%20nwr%5B%22highway%22%3D%22residential%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22unclassified%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22tertiary%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22secondary%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%29%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B)
## Supported attributes
**Warning:**,this quick overview is incomplete,
| attribute | type | values which are supported by this layer |
-----|-----|----- |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/sidewalk:left#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/sidewalk%3Aleft/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [sidewalk:left](https://wiki.openstreetmap.org/wiki/Key:sidewalk:left) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:left%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:left%3Dno) [separate](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:left%3Dseparate) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/sidewalk:left:width#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/sidewalk%3Aleft%3Awidth/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [sidewalk:left:width](https://wiki.openstreetmap.org/wiki/Key:sidewalk:left:width) | [distance](../SpecialInputElements.md#distance) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/sidewalk:right#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/sidewalk%3Aright/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [sidewalk:right](https://wiki.openstreetmap.org/wiki/Key:sidewalk:right) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:right%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:right%3Dno) [separate](https://wiki.openstreetmap.org/wiki/Tag:sidewalk:right%3Dseparate) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/sidewalk:right:width#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/sidewalk%3Aright%3Awidth/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [sidewalk:right:width](https://wiki.openstreetmap.org/wiki/Key:sidewalk:right:width) | [distance](../SpecialInputElements.md#distance) | |
### streetname
_This tagrendering has no question and is thus read-only_
*This street is named {name}*
### sidewalk_minimap_left
_This tagrendering has no question and is thus read-only_
*{sided_minimap(left):height:8rem;border-radius:0.5rem;overflow:hidden}*
### has_sidewalk_left
The question is `Is there a sidewalk on this side of the road?`
- *There is a sidewalk on this side of the road* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:sidewalk:left' target='_blank'>sidewalk:left</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:sidewalk:left%3Dyes' target='_blank'>yes</a>
- *There is no sidewalk to walk on* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:sidewalk:left' target='_blank'>sidewalk:left</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:sidewalk:left%3Dno' target='_blank'>no</a>
- *There is a separately mapped sidewalk to walk on* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:sidewalk:left' target='_blank'>sidewalk:left</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:sidewalk:left%3Dseparate' target='_blank'>separate</a>
### sidewalk_width_left
The question is `What is the width of the sidewalk on this side of the road?`
*This sidewalk is {sidewalk:left:width}m wide* is shown if `sidewalk:left:width` is set
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:sidewalk:left' target='_blank'>sidewalk:left</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:sidewalk:left%3Dyes' target='_blank'>yes</a>
### sidewalk_minimap_right
_This tagrendering has no question and is thus read-only_
*{sided_minimap(right):height:8rem;border-radius:0.5rem;overflow:hidden}*
### has_sidewalk_right
The question is `Is there a sidewalk on this side of the road?`
- *There is a sidewalk on this side of the road* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:sidewalk:right' target='_blank'>sidewalk:right</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:sidewalk:right%3Dyes' target='_blank'>yes</a>
- *There is no sidewalk to walk on* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:sidewalk:right' target='_blank'>sidewalk:right</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:sidewalk:right%3Dno' target='_blank'>no</a>
- *There is a separately mapped sidewalk to walk on* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:sidewalk:right' target='_blank'>sidewalk:right</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:sidewalk:right%3Dseparate' target='_blank'>separate</a>
### sidewalk_width_right
The question is `What is the width of the sidewalk on this side of the road?`
*This sidewalk is {sidewalk:right:width}m wide* is shown if `sidewalk:right:width` is set
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:sidewalk:right' target='_blank'>sidewalk:right</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:sidewalk:right%3Dyes' target='_blank'>yes</a>
### leftover-questions
_This tagrendering has no question and is thus read-only_
*{questions( ,)}*
### split_button
_This tagrendering has no question and is thus read-only_
*{split_button()}*
### lod
_This tagrendering has no question and is thus read-only_
*{linked_data_from_website()}*
This tagrendering has labels
`added_by_default`
This document is autogenerated from [assets/themes/sidewalks/sidewalks.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/sidewalks/sidewalks.json)

View file

@ -138,7 +138,7 @@ Elements must match the expression **mr_taskId~.+**
### velopark-ref ### velopark-ref
The question is `What is the URL of the data path within Velopark?` The question is `What is the URL of the data path within Velopark?`
*This bicycle parking is on OpenStreetMap and is linked to Velopark:{link(&LBRACEref:velopark&RBRACE,&LBRACEref:velopark&RBRACE,,,)}* is shown if `ref:velopark` is set *This bicycle parking is on OpenStreetMap and is linked to Velopark:{link(&LBRACEref:velopark&RBRACE,&LBRACEref:velopark&RBRACE,,,,)}* is shown if `ref:velopark` is set
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbicycle_parking' target='_blank'>bicycle_parking</a> This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbicycle_parking' target='_blank'>bicycle_parking</a>
@ -162,7 +162,7 @@ _This tagrendering has no question and is thus read-only_
### is_linked ### is_linked
_This tagrendering has no question and is thus read-only_ _This tagrendering has no question and is thus read-only_
*{link(Matched with bicycle parking &LBRACE_osm_parkings_with_this_velopark_ref&RBRACE,#&LBRACE_osm_parkings_with_this_velopark_ref&RBRACE,,,)}* is shown if `_osm_parkings_with_this_velopark_ref` is set *{link(Matched with bicycle parking &LBRACE_osm_parkings_with_this_velopark_ref&RBRACE,#&LBRACE_osm_parkings_with_this_velopark_ref&RBRACE,,,,)}* is shown if `_osm_parkings_with_this_velopark_ref` is set
@ -170,7 +170,7 @@ _This tagrendering has no question and is thus read-only_
### velopark-link ### velopark-link
_This tagrendering has no question and is thus read-only_ _This tagrendering has no question and is thus read-only_
*This is data from <b>Velopark</b>. {link(See on velopark &LPARENSwebpage&RPARENS,https://www.velopark.be/static/data/&LBRACEmr_velopark_id&RBRACE,,,)}* *This is data from <b>Velopark</b>. {link(See on velopark &LPARENSwebpage&RPARENS,https://www.velopark.be/static/data/&LBRACEmr_velopark_id&RBRACE,,,,)}*
@ -262,7 +262,7 @@ _This tagrendering has no question and is thus read-only_
### velopark-data-link ### velopark-data-link
_This tagrendering has no question and is thus read-only_ _This tagrendering has no question and is thus read-only_
*{link(Inspect raw data on velopark.be,&LBRACEref:velopark&RBRACE,,,)}* *{link(Inspect raw data on velopark.be,&LBRACEref:velopark&RBRACE,,,,)}*
@ -375,7 +375,7 @@ Elements must match **all** of the following expressions:
### velopark-ref ### velopark-ref
The question is `What is the URL of the data path within Velopark?` The question is `What is the URL of the data path within Velopark?`
*This bicycle parking is on OpenStreetMap and is linked to Velopark:{link(&LBRACEref:velopark&RBRACE,&LBRACEref:velopark&RBRACE,,,)}* is shown if `ref:velopark` is set *This bicycle parking is on OpenStreetMap and is linked to Velopark:{link(&LBRACEref:velopark&RBRACE,&LBRACEref:velopark&RBRACE,,,,)}* is shown if `ref:velopark` is set
This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbicycle_parking' target='_blank'>bicycle_parking</a> This tagrendering is only visible in the popup if the following condition is met: <a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbicycle_parking' target='_blank'>bicycle_parking</a>

View file

@ -24,26 +24,27 @@ This document gives an overview of which URL-parameters can be used to influence
15. [fs-layers-enabled](#fs-layers-enabled) 15. [fs-layers-enabled](#fs-layers-enabled)
16. [fs-all-questions](#fs-all-questions) 16. [fs-all-questions](#fs-all-questions)
17. [fs-export](#fs-export) 17. [fs-export](#fs-export)
18. [test](#test) 18. [fs-cache](#fs-cache)
19. [debug](#debug) 19. [test](#test)
20. [moreprivacy](#moreprivacy) 20. [debug](#debug)
21. [overpassUrl](#overpassurl) 21. [moreprivacy](#moreprivacy)
22. [overpassTimeout](#overpasstimeout) 22. [overpassUrl](#overpassurl)
23. [overpassMaxZoom](#overpassmaxzoom) 23. [overpassTimeout](#overpasstimeout)
24. [osmApiTileSize](#osmapitilesize) 24. [overpassMaxZoom](#overpassmaxzoom)
25. [background](#background) 25. [osmApiTileSize](#osmapitilesize)
26. [z](#z) 26. [background](#background)
27. [lat](#lat) 27. [z](#z)
28. [lon](#lon) 28. [lat](#lat)
29. [oauth_token](#oauth_token) 29. [lon](#lon)
30. [layer-public_bookcase](#layer-public_bookcase) 30. [oauth_token](#oauth_token)
31. [filter-public_bookcase-kid-books](#filter-public_bookcase-kid-books) 31. [layer-public_bookcase](#layer-public_bookcase)
32. [filter-public_bookcase-adult-books](#filter-public_bookcase-adult-books) 32. [filter-public_bookcase-kid-books](#filter-public_bookcase-kid-books)
33. [filter-public_bookcase-inside](#filter-public_bookcase-inside) 33. [filter-public_bookcase-adult-books](#filter-public_bookcase-adult-books)
34. [filter-public_bookcase-has_image](#filter-public_bookcase-has_image) 34. [filter-public_bookcase-inside](#filter-public_bookcase-inside)
35. [layer-note_import_public_bookcase](#layer-note_import_public_bookcase) 35. [filter-public_bookcase-has_image](#filter-public_bookcase-has_image)
36. [mode](#mode) 36. [layer-note_import_public_bookcase](#layer-note_import_public_bookcase)
37. [layer-<layer-id>](#layer-<layer-id>) 37. [mode](#mode)
38. [layer-<layer-id>](#layer-<layer-id>)
## What is a URL parameter? ## What is a URL parameter?
@ -132,7 +133,7 @@ The default value is _false_
Disables/Enables logging in and thus disables editing all together. This effectively puts MapComplete into read-only mode. Disables/Enables logging in and thus disables editing all together. This effectively puts MapComplete into read-only mode.
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L99) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L101)
@ -142,7 +143,7 @@ The default value is _true_
Disables/Enables the search bar Disables/Enables the search bar
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L114) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L116)
@ -152,7 +153,7 @@ The default value is _true_
Disables/Enables the background layer control where a user can enable e.g. aerial imagery Disables/Enables the background layer control where a user can enable e.g. aerial imagery
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L119) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L121)
@ -162,7 +163,7 @@ The default value is _true_
Disables/Enables the filter view where a user can enable/disable MapComplete-layers or filter for certain properties Disables/Enables the filter view where a user can enable/disable MapComplete-layers or filter for certain properties
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L125) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L127)
@ -172,7 +173,7 @@ The default value is _true_
Disables/enables the help menu or welcome message Disables/enables the help menu or welcome message
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L131) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L133)
@ -182,7 +183,7 @@ The default value is _true_
Disables/enables the button to get in touch with the community Disables/enables the button to get in touch with the community
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L136) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L138)
@ -192,7 +193,7 @@ The default value is _true_
Disables/Enables the extraLink button. By default, if in iframe mode and the welcome message is hidden, a popout button to the full mapcomplete instance is shown instead (unless disabled with this switch or another extraLink button is enabled) Disables/Enables the extraLink button. By default, if in iframe mode and the welcome message is hidden, a popout button to the full mapcomplete instance is shown instead (unless disabled with this switch or another extraLink button is enabled)
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L141) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L143)
@ -202,7 +203,7 @@ The default value is _true_
Disables/Enables the various links which go back to the index page with the theme overview Disables/Enables the various links which go back to the index page with the theme overview
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L146) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L148)
@ -212,7 +213,7 @@ The default value is _true_
Disables/Enables the 'Share-screen'-tab in the welcome message Disables/Enables the 'Share-screen'-tab in the welcome message
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L151) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L153)
@ -222,7 +223,7 @@ The default value is _true_
Disables/Enables the geolocation button Disables/Enables the geolocation button
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L156) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L158)
@ -232,7 +233,7 @@ The default value is _true_
If set to false, all layers will be disabled - except the explicitly enabled layers If set to false, all layers will be disabled - except the explicitly enabled layers
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L162) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L164)
@ -242,7 +243,7 @@ The default value is _true_
Always show all questions Always show all questions
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L167) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L169)
@ -252,7 +253,17 @@ The default value is _false_
Enable the export as GeoJSON and CSV button Enable the export as GeoJSON and CSV button
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L173) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L175)
The default value is _true_
## fs-cache
Enable/disable caching from localStorage
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L181)
@ -262,7 +273,7 @@ The default value is _true_
If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org If true, 'dryrun' mode is activated. The app will behave as normal, except that changes to OSM will be printed onto the console instead of actually uploaded to osm.org
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L188) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L197)
@ -272,7 +283,7 @@ The default value is _false_
If true, shows some extra debugging help such as all the available tags on every object If true, shows some extra debugging help such as all the available tags on every object
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L194) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L203)
@ -282,7 +293,7 @@ The default value is _false_
If true, the location distance indication will not be written to the changeset and other privacy enhancing measures might be taken. If true, the location distance indication will not be written to the changeset and other privacy enhancing measures might be taken.
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L200) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L209)
@ -292,7 +303,7 @@ The default value is _false_
Point mapcomplete to a different overpass-instance. Example: https://overpass-api.de/api/interpreter Point mapcomplete to a different overpass-instance. Example: https://overpass-api.de/api/interpreter
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L206) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L215)
@ -302,7 +313,7 @@ The default value is _https://overpass-api.de/api/interpreter,https://overpass.k
Set a different timeout (in seconds) for queries in overpass Set a different timeout (in seconds) for queries in overpass
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L217) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L226)
@ -312,7 +323,7 @@ The default value is _30_
point to switch between OSM-api and overpass point to switch between OSM-api and overpass
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L225) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L234)
@ -322,7 +333,7 @@ The default value is _16_
Tilesize when the OSM-API is used to fetch data within a BBOX Tilesize when the OSM-API is used to fetch data within a BBOX
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L233) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L242)
@ -332,7 +343,7 @@ The default value is _17_
The id of the background layer to start with The id of the background layer to start with
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L240) This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L249)
@ -372,7 +383,7 @@ The default value is _0_
Used to complete the login Used to complete the login
This documentation is defined in the source code at [ThemeViewState.ts](/src/Models/ThemeViewState.ts#L177) This documentation is defined in the source code at [ThemeViewState.ts](/src/Models/ThemeViewState.ts#L171)

View file

@ -172,14 +172,13 @@ export default class ScriptUtils {
headers?: any, headers?: any,
timeoutSecs?: number timeoutSecs?: number
): Promise<{ content: string } | { redirect: string } | "timeout"> { ): Promise<{ content: string } | { redirect: string } | "timeout"> {
if(url.startsWith("./assets")){ if (url.startsWith("./assets")) {
return Promise.resolve({content: readFileSync("./public/"+url, "utf8")}) return Promise.resolve({ content: readFileSync("./public/" + url, "utf8") })
} }
if(url.startsWith("./")){ if (url.startsWith("./")) {
return Promise.resolve({content: readFileSync(url, "utf8")}) return Promise.resolve({ content: readFileSync(url, "utf8") })
} }
const requestPromise = new Promise((resolve, reject) => { const requestPromise = new Promise((resolve, reject) => {
try { try {
headers = headers ?? {} headers = headers ?? {}

View file

@ -100,14 +100,17 @@ class DownloadEli extends Script {
const contents = const contents =
'{"type":"FeatureCollection",\n "features": [\n' + '{"type":"FeatureCollection",\n "features": [\n' +
keptLayers.filter(l => l.properties.id !== "Bing").map((l) => JSON.stringify(l)).join(",\n") + keptLayers
.filter((l) => l.properties.id !== "Bing")
.map((l) => JSON.stringify(l))
.join(",\n") +
"\n]}" "\n]}"
const bing = keptLayers.find(l => l.properties.id === "Bing") const bing = keptLayers.find((l) => l.properties.id === "Bing")
if(bing){ if (bing) {
fs.writeFileSync(targetBing, JSON.stringify(bing), { encoding: "utf8" }) fs.writeFileSync(targetBing, JSON.stringify(bing), { encoding: "utf8" })
console.log("Written", targetBing) console.log("Written", targetBing)
}else{ } else {
console.log("No bing entry found") console.log("No bing entry found")
} }
fs.writeFileSync(target, contents, { encoding: "utf8" }) fs.writeFileSync(target, contents, { encoding: "utf8" })

View file

@ -273,7 +273,6 @@ class LayerOverviewUtils extends Script {
JSON.stringify(theme, null, " "), JSON.stringify(theme, null, " "),
{ encoding: "utf8" } { encoding: "utf8" }
) )
} }
writeLayer(layer: LayerConfigJson) { writeLayer(layer: LayerConfigJson) {
@ -852,7 +851,11 @@ class LayerOverviewUtils extends Script {
} }
} }
const usedImages = Utils.Dedup(new ExtractImages(true, knownTagRenderings).convertStrict(themeFile).map(x => x.path)) const usedImages = Utils.Dedup(
new ExtractImages(true, knownTagRenderings)
.convertStrict(themeFile)
.map((x) => x.path)
)
usedImages.sort() usedImages.sort()
themeFile["_usedImages"] = usedImages themeFile["_usedImages"] = usedImages

View file

@ -74,7 +74,12 @@ class HandleErrors extends Script {
} }
for (const parsed of all) { for (const parsed of all) {
console.log(parsed.message.username, parsed.message.layout, parsed.message.message, parsed.date) console.log(
parsed.message.username,
parsed.message.layout,
parsed.message.message,
parsed.date
)
const e = parsed.message const e = parsed.message
const neededIds = Changes.GetNeededIds(e.pendingChanges) const neededIds = Changes.GetNeededIds(e.pendingChanges)
@ -112,7 +117,7 @@ class HandleErrors extends Script {
"Changes for " + parsed.index + ": empty changeset, not creating a file for it" "Changes for " + parsed.index + ": empty changeset, not creating a file for it"
)*/ )*/
} else if (createdChangesets.has(changeset)) { } else if (createdChangesets.has(changeset)) {
/* console.log( /* console.log(
"Changeset " + "Changeset " +
parsed.index + parsed.index +
" is identical to previously seen changeset, not writing to file" " is identical to previously seen changeset, not writing to file"
@ -126,7 +131,7 @@ ${changeset}`
} }
const refusedContent = JSON.stringify(refused) const refusedContent = JSON.stringify(refused)
if (refusedFiles.has(refusedContent)) { if (refusedFiles.has(refusedContent)) {
/* console.log( /* console.log(
"Refused changes for " + "Refused changes for " +
parsed.index + parsed.index +
" is identical to previously seen changeset, not writing to file" " is identical to previously seen changeset, not writing to file"

View file

@ -36,7 +36,7 @@ export class AllKnownLayoutsLazy {
return this.raw.get(key) return this.raw.get(key)
} }
public size(){ public size() {
return this.raw.size return this.raw.size
} }

View file

@ -1,6 +1,10 @@
import { Store, UIEventSource } from "../UIEventSource" import { Store, UIEventSource } from "../UIEventSource"
import { Utils } from "../../Utils" import { Utils } from "../../Utils"
import { AvailableRasterLayers, RasterLayerPolygon, RasterLayerUtils } from "../../Models/RasterLayers" import {
AvailableRasterLayers,
RasterLayerPolygon,
RasterLayerUtils,
} from "../../Models/RasterLayers"
/** /**
* When a user pans around on the map, they might pan out of the range of the current background raster layer. * When a user pans around on the map, they might pan out of the range of the current background raster layer.
@ -9,24 +13,32 @@ import { AvailableRasterLayers, RasterLayerPolygon, RasterLayerUtils } from "../
export default class BackgroundLayerResetter { export default class BackgroundLayerResetter {
constructor( constructor(
currentBackgroundLayer: UIEventSource<RasterLayerPolygon | undefined>, currentBackgroundLayer: UIEventSource<RasterLayerPolygon | undefined>,
availableLayers: {store: Store<RasterLayerPolygon[]>} availableLayers: { store: Store<RasterLayerPolygon[]> }
) { ) {
if (Utils.runningFromConsole) { if (Utils.runningFromConsole) {
return return
} }
currentBackgroundLayer.addCallbackAndRunD(l => { currentBackgroundLayer.addCallbackAndRunD((l) => {
if(l.geometry !== undefined && AvailableRasterLayers.globalLayers.find(global => global.properties.id !== l.properties.id)){ if (
BackgroundLayerResetter.installHandler(currentBackgroundLayer, availableLayers.store) l.geometry !== undefined &&
AvailableRasterLayers.globalLayers.find(
(global) => global.properties.id !== l.properties.id
)
) {
BackgroundLayerResetter.installHandler(
currentBackgroundLayer,
availableLayers.store
)
return true // unregister return true // unregister
} }
}) })
} }
private static installHandler( currentBackgroundLayer: UIEventSource<RasterLayerPolygon | undefined>, private static installHandler(
availableLayers: Store<RasterLayerPolygon[]> currentBackgroundLayer: UIEventSource<RasterLayerPolygon | undefined>,
){ availableLayers: Store<RasterLayerPolygon[]>
) {
// Change the baseLayer back to OSM if we go out of the current range of the layer // Change the baseLayer back to OSM if we go out of the current range of the layer
availableLayers.addCallbackAndRunD((availableLayers) => { availableLayers.addCallbackAndRunD((availableLayers) => {
// We only check on move/on change of the availableLayers // We only check on move/on change of the availableLayers

View file

@ -20,7 +20,7 @@ export class PreferredRasterLayerSelector {
queryParameter: UIEventSource<string>, queryParameter: UIEventSource<string>,
preferredBackgroundLayer: UIEventSource< preferredBackgroundLayer: UIEventSource<
string | "photo" | "map" | "osmbasedmap" | undefined string | "photo" | "map" | "osmbasedmap" | undefined
>, >
) { ) {
this._rasterLayerSetting = rasterLayerSetting this._rasterLayerSetting = rasterLayerSetting
this._availableLayers = availableLayers this._availableLayers = availableLayers
@ -47,8 +47,8 @@ export class PreferredRasterLayerSelector {
this._preferredBackgroundLayer.addCallbackD((_) => self.updateLayer()) this._preferredBackgroundLayer.addCallbackD((_) => self.updateLayer())
rasterLayerSetting.addCallbackAndRunD(layer => { rasterLayerSetting.addCallbackAndRunD((layer) => {
if (AvailableRasterLayers.globalLayers.find(l => l.id === layer.properties.id)) { if (AvailableRasterLayers.globalLayers.find((l) => l.id === layer.properties.id)) {
return return
} }
this._availableLayers.store.addCallbackD((_) => self.updateLayer()) this._availableLayers.store.addCallbackD((_) => self.updateLayer())
@ -67,7 +67,9 @@ export class PreferredRasterLayerSelector {
if (targetLayerId === undefined || targetLayerId === "default") { if (targetLayerId === undefined || targetLayerId === "default") {
return return
} }
const global = AvailableRasterLayers.globalLayers.find(l => l.properties.id === targetLayerId) const global = AvailableRasterLayers.globalLayers.find(
(l) => l.properties.id === targetLayerId
)
if (global) { if (global) {
this._rasterLayerSetting.setData(global) this._rasterLayerSetting.setData(global)
return return

View file

@ -108,12 +108,18 @@ export default class DetermineLayout {
).data ).data
const id = layoutId?.toLowerCase() const id = layoutId?.toLowerCase()
const layouts = AllKnownLayouts.allKnownLayouts const layouts = AllKnownLayouts.allKnownLayouts
if(layouts.size() == 0){ if (layouts.size() == 0) {
throw "Build failed or running, no layouts are known at all" throw "Build failed or running, no layouts are known at all"
} }
if (layouts.getConfig(id) === undefined) { if (layouts.getConfig(id) === undefined) {
const alternatives = Utils.sortedByLevenshteinDistance(id, Array.from(layouts.keys()), i => i).slice(0, 3) const alternatives = Utils.sortedByLevenshteinDistance(
const msg = (`No builtin map theme with name ${layoutId} exists. Perhaps you meant one of ${alternatives.join(", ")}`) id,
Array.from(layouts.keys()),
(i) => i
).slice(0, 3)
const msg = `No builtin map theme with name ${layoutId} exists. Perhaps you meant one of ${alternatives.join(
", "
)}`
throw msg throw msg
} }
return layouts.get(id) return layouts.get(id)
@ -204,11 +210,11 @@ export default class DetermineLayout {
id: json.id, id: json.id,
description: json.description, description: json.description,
descriptionTail: { descriptionTail: {
en: "<div class='alert'>Layer only mode.</div> The loaded custom theme actually isn't a custom theme, but only contains a layer." en: "<div class='alert'>Layer only mode.</div> The loaded custom theme actually isn't a custom theme, but only contains a layer.",
}, },
icon, icon,
title: json.name, title: json.name,
layers: [json] layers: [json],
} }
} }
@ -221,7 +227,7 @@ export default class DetermineLayout {
tagRenderings: DetermineLayout.getSharedTagRenderings(), tagRenderings: DetermineLayout.getSharedTagRenderings(),
tagRenderingOrder: DetermineLayout.getSharedTagRenderingOrder(), tagRenderingOrder: DetermineLayout.getSharedTagRenderingOrder(),
sharedLayers: knownLayersDict, sharedLayers: knownLayersDict,
publicLayers: new Set<string>() publicLayers: new Set<string>(),
} }
json = new FixLegacyTheme().convertStrict(json) json = new FixLegacyTheme().convertStrict(json)
const raw = json const raw = json
@ -245,7 +251,7 @@ export default class DetermineLayout {
} }
return new LayoutConfig(json, false, { return new LayoutConfig(json, false, {
definitionRaw: JSON.stringify(raw, null, " "), definitionRaw: JSON.stringify(raw, null, " "),
definedAtUrl: sourceUrl definedAtUrl: sourceUrl,
}) })
} }

View file

@ -55,12 +55,11 @@ export default class LayoutSource extends FeatureSourceMerger {
mapProperties, mapProperties,
{ {
isActive: isDisplayed(layer.id), isActive: isDisplayed(layer.id),
maxAge: layer.maxAgeOfCache maxAge: layer.maxAgeOfCache,
} }
) )
fromCache.set(layer.id, src) fromCache.set(layer.id, src)
} }
} }
const mvtSources: UpdatableFeatureSource[] = osmLayers const mvtSources: UpdatableFeatureSource[] = osmLayers
.filter((f) => mvtAvailableLayers.has(f.id)) .filter((f) => mvtAvailableLayers.has(f.id))
@ -170,7 +169,7 @@ export default class LayoutSource extends FeatureSourceMerger {
backend, backend,
isActive, isActive,
patchRelations: true, patchRelations: true,
fullNodeDatabase fullNodeDatabase,
}) })
} }
@ -202,11 +201,11 @@ export default class LayoutSource extends FeatureSourceMerger {
widenFactor: featureSwitches.layoutToUse.widenFactor, widenFactor: featureSwitches.layoutToUse.widenFactor,
overpassUrl: featureSwitches.overpassUrl, overpassUrl: featureSwitches.overpassUrl,
overpassTimeout: featureSwitches.overpassTimeout, overpassTimeout: featureSwitches.overpassTimeout,
overpassMaxZoom: featureSwitches.overpassMaxZoom overpassMaxZoom: featureSwitches.overpassMaxZoom,
}, },
{ {
padToTiles: zoom.map((zoom) => Math.min(15, zoom + 1)), padToTiles: zoom.map((zoom) => Math.min(15, zoom + 1)),
isActive isActive,
} }
) )
} }

View file

@ -129,7 +129,7 @@ export default class MetaTagging {
state.featureProperties, state.featureProperties,
{ {
includeDates: !lightUpdate, includeDates: !lightUpdate,
evaluateStrict: !lightUpdate evaluateStrict: !lightUpdate,
} }
) )
} }
@ -305,7 +305,7 @@ export default class MetaTagging {
return [] return []
} }
return [state.perLayer.get(layerId).GetFeaturesWithin(bbox)] return [state.perLayer.get(layerId).GetFeaturesWithin(bbox)]
} },
} }
} }
@ -350,8 +350,8 @@ export default class MetaTagging {
if (MetaTagging.errorPrintCount < MetaTagging.stopErrorOutputAt) { if (MetaTagging.errorPrintCount < MetaTagging.stopErrorOutputAt) {
console.warn( console.warn(
"Could not calculate a " + "Could not calculate a " +
(isStrict ? "strict " : "") + (isStrict ? "strict " : "") +
"calculated tag for key", "calculated tag for key",
key, key,
"for feature", "for feature",
feat.properties.id, feat.properties.id,
@ -359,9 +359,9 @@ export default class MetaTagging {
code, code,
"(in layer", "(in layer",
layerId + layerId +
") due to \n" + ") due to \n" +
e + e +
"\n. Are you the theme creator? Doublecheck your code. Note that the metatags might not be stable on new features", "\n. Are you the theme creator? Doublecheck your code. Note that the metatags might not be stable on new features",
e, e,
e.stack, e.stack,
{ feat } { feat }

View file

@ -440,7 +440,13 @@ export class Changes {
} }
}) })
if(!(result.newObjects.length === 0 && result.modifiedObjects.length === 0 && result.deletedObjects.length === 0)) { if (
!(
result.newObjects.length === 0 &&
result.modifiedObjects.length === 0 &&
result.deletedObjects.length === 0
)
) {
console.debug( console.debug(
"Calculated the pending changes: ", "Calculated the pending changes: ",
result.newObjects.length, result.newObjects.length,
@ -589,7 +595,13 @@ export class Changes {
if (matchFound) { if (matchFound) {
toUpload.push(c) toUpload.push(c)
} else { } else {
console.log("Refusing change about "+c.type+"/"+ c.id+" as not in the objects. No internet?") console.log(
"Refusing change about " +
c.type +
"/" +
c.id +
" as not in the objects. No internet?"
)
refused.push(c) refused.push(c)
} }
}) })
@ -711,7 +723,7 @@ export class Changes {
let { toUpload, refused } = this.fragmentChanges(pending, objects) let { toUpload, refused } = this.fragmentChanges(pending, objects)
if(toUpload.length === 0){ if (toUpload.length === 0) {
return refused return refused
} }
await this._changesetHandler.UploadChangeset( await this._changesetHandler.UploadChangeset(

View file

@ -154,7 +154,7 @@ export class ChangesetHandler {
if (this._reportError) { if (this._reportError) {
this._reportError(e) this._reportError(e)
} }
if((<XMLHttpRequest> e).status === 400){ if ((<XMLHttpRequest>e).status === 400) {
// This request is invalid. We simply drop the changes and hope that someone will analyze what went wrong with it in the upload; we pretend everything went fine // This request is invalid. We simply drop the changes and hope that someone will analyze what went wrong with it in the upload; we pretend everything went fine
return return
} }

View file

@ -107,7 +107,8 @@ export class OsmConnection {
ud.name = "Fake user" ud.name = "Fake user"
ud.totalMessages = 42 ud.totalMessages = 42
ud.languages = ["en"] ud.languages = ["en"]
ud.description = "The 'fake-user' is a URL-parameter which allows to test features without needing an OSM account or even internet connection." ud.description =
"The 'fake-user' is a URL-parameter which allows to test features without needing an OSM account or even internet connection."
this.loadingStatus.setData("logged-in") this.loadingStatus.setData("logged-in")
} }
this.UpdateCapabilities() this.UpdateCapabilities()

View file

@ -184,7 +184,6 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches {
"Enable/disable caching from localStorage" "Enable/disable caching from localStorage"
) )
let testingDefaultValue = false let testingDefaultValue = false
if ( if (
!Utils.runningFromConsole && !Utils.runningFromConsole &&

View file

@ -57,7 +57,8 @@ export class GeoLocationState {
* If the user denies the geolocation this time, we unset this flag * If the user denies the geolocation this time, we unset this flag
* @private * @private
*/ */
private readonly _previousLocationGrant: UIEventSource<boolean> = LocalStorageSource.GetParsed<boolean>("geolocation-permissions", false) private readonly _previousLocationGrant: UIEventSource<boolean> =
LocalStorageSource.GetParsed<boolean>("geolocation-permissions", false)
/** /**
* Used to detect a permission retraction * Used to detect a permission retraction
@ -67,8 +68,8 @@ export class GeoLocationState {
/** /**
* A human explanation of the current gps state, to be shown on the home screen or as tooltip * A human explanation of the current gps state, to be shown on the home screen or as tooltip
*/ */
public readonly gpsStateExplanation : Store<Translation> public readonly gpsStateExplanation: Store<Translation>
constructor() { constructor() {
const self = this const self = this
this.permission.addCallbackAndRunD(async (state) => { this.permission.addCallbackAndRunD(async (state) => {
@ -103,33 +104,33 @@ export class GeoLocationState {
this.requestPermission() this.requestPermission()
} }
this.gpsStateExplanation = this.gpsAvailable.map(
(available) => {
if (this.currentGPSLocation.data !== undefined) {
if (!this.allowMoving.data) {
return Translations.t.general.visualFeedback.islocked
}
this.gpsStateExplanation = this.gpsAvailable.map(available => { return Translations.t.general.labels.jumpToLocation
if (this.currentGPSLocation.data !== undefined) {
if (!this.allowMoving.data) {
return Translations.t.general.visualFeedback.islocked
} }
return Translations.t.general.labels.jumpToLocation if (!available) {
} return Translations.t.general.labels.locationNotAvailable
}
if (!available) { if (this.permission.data === "denied") {
return Translations.t.general.labels.locationNotAvailable return Translations.t.general.geopermissionDenied
} }
if (this.permission.data === "denied") { if (this.permission.data === "prompt") {
return Translations.t.general.geopermissionDenied return Translations.t.general.labels.jumpToLocation
} }
if (this.permission.data === "prompt") { if (this.permission.data === "requested") {
return Translations.t.general.labels.jumpToLocation return Translations.t.general.waitingForGeopermission
} }
if (this.permission.data === "requested") { return Translations.t.general.waitingForLocation
return Translations.t.general.waitingForGeopermission },
} [this.allowMoving, this.permission, this.currentGPSLocation]
return Translations.t.general.waitingForLocation )
}, [this.allowMoving, this.permission, this.currentGPSLocation]) }
}
/** /**
* Requests the user to allow access to their position. * Requests the user to allow access to their position.
@ -208,12 +209,12 @@ export class GeoLocationState {
self._previousLocationGrant.setData(true) self._previousLocationGrant.setData(true)
}, },
function (e) { function (e) {
if(e.code === 2 || e.code === 3){ if (e.code === 2 || e.code === 3) {
self._gpsAvailable.set(false) self._gpsAvailable.set(false)
return return
} }
self._gpsAvailable.set(true) // We go back to the default assumption that the location is physically available self._gpsAvailable.set(true) // We go back to the default assumption that the location is physically available
if(e.code === 1) { if (e.code === 1) {
self.permission.set("denied") self.permission.set("denied")
self._grantedThisSession.setData(false) self._grantedThisSession.setData(false)
return return

View file

@ -391,12 +391,14 @@ export default class UserRelatedState {
for (const k in userDetails) { for (const k in userDetails) {
amendedPrefs.data["_" + k] = "" + userDetails[k] amendedPrefs.data["_" + k] = "" + userDetails[k]
} }
if(userDetails.description){ if (userDetails.description) {
amendedPrefs.data["_description_html"] = Utils.purify(new Showdown.Converter() amendedPrefs.data["_description_html"] = Utils.purify(
.makeHtml(userDetails.description) new Showdown.Converter()
?.replace(/&gt;/g, ">") .makeHtml(userDetails.description)
?.replace(/&lt;/g, "<") ?.replace(/&gt;/g, ">")
?.replace(/\n/g, "")) ?.replace(/&lt;/g, "<")
?.replace(/\n/g, "")
)
} }
usersettingMetaTagging.metaTaggging_for_usersettings({ properties: amendedPrefs.data }) usersettingMetaTagging.metaTaggging_for_usersettings({ properties: amendedPrefs.data })

View file

@ -1,14 +1,42 @@
import { Utils } from "../../Utils" import { Utils } from "../../Utils"
/** This code is autogenerated - do not edit. Edit ./assets/layers/usersettings/usersettings.json instead */ /** This code is autogenerated - do not edit. Edit ./assets/layers/usersettings/usersettings.json instead */
export class ThemeMetaTagging { export class ThemeMetaTagging {
public static readonly themeName = "usersettings" public static readonly themeName = "usersettings"
public metaTaggging_for_usersettings(feat: {properties: Record<string, string>}) { public metaTaggging_for_usersettings(feat: { properties: Record<string, string> }) {
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_md', () => feat.properties._description.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)?.at(1) ) Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_md", () =>
Utils.AddLazyProperty(feat.properties, '_d', () => feat.properties._description?.replace(/&lt;/g,'<')?.replace(/&gt;/g,'>') ?? '' ) feat.properties._description
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_a', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.href.match(/mastodon|en.osm.town/) !== null)[0]?.href }) (feat) ) .match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)
Utils.AddLazyProperty(feat.properties, '_mastodon_link', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.getAttribute("rel")?.indexOf('me') >= 0)[0]?.href})(feat) ) ?.at(1)
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate', () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a ) )
feat.properties['__current_backgroun'] = 'initial_value' Utils.AddLazyProperty(
} feat.properties,
} "_d",
() => feat.properties._description?.replace(/&lt;/g, "<")?.replace(/&gt;/g, ">") ?? ""
)
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_a", () =>
((feat) => {
const e = document.createElement("div")
e.innerHTML = feat.properties._d
return Array.from(e.getElementsByTagName("a")).filter(
(a) => a.href.match(/mastodon|en.osm.town/) !== null
)[0]?.href
})(feat)
)
Utils.AddLazyProperty(feat.properties, "_mastodon_link", () =>
((feat) => {
const e = document.createElement("div")
e.innerHTML = feat.properties._d
return Array.from(e.getElementsByTagName("a")).filter(
(a) => a.getAttribute("rel")?.indexOf("me") >= 0
)[0]?.href
})(feat)
)
Utils.AddLazyProperty(
feat.properties,
"_mastodon_candidate",
() => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a
)
feat.properties["__current_backgroun"] = "initial_value"
}
}

View file

@ -218,7 +218,7 @@ export class TagUtils {
* *
* TagUtils.KVtoProperties([new Tag("a","b"), new Tag("c","d")] // => {a: "b", c: "d"} * TagUtils.KVtoProperties([new Tag("a","b"), new Tag("c","d")] // => {a: "b", c: "d"}
*/ */
static KVtoProperties(tags: {key: string, value: string}[]): Record<string, string> { static KVtoProperties(tags: { key: string; value: string }[]): Record<string, string> {
const properties: Record<string, string> = {} const properties: Record<string, string> = {}
for (const tag of tags) { for (const tag of tags) {
properties[tag.key] = tag.value properties[tag.key] = tag.value
@ -226,7 +226,7 @@ export class TagUtils {
return properties return properties
} }
static KVObjtoProperties(tags: {k: string, v: string}[]): Record<string, string> { static KVObjtoProperties(tags: { k: string; v: string }[]): Record<string, string> {
const properties: Record<string, string> = {} const properties: Record<string, string> = {}
for (const tag of tags) { for (const tag of tags) {
properties[tag.k] = tag.v properties[tag.k] = tag.v

View file

@ -10,7 +10,7 @@ export class IdbLocalStorage {
public static Get<T>( public static Get<T>(
key: string, key: string,
options?: { defaultValue?: T; whenLoaded?: (t: T | null) => void }, options?: { defaultValue?: T; whenLoaded?: (t: T | null) => void }
): UIEventSource<T> { ): UIEventSource<T> {
if (IdbLocalStorage._sourceCache[key] !== undefined) { if (IdbLocalStorage._sourceCache[key] !== undefined) {
return IdbLocalStorage._sourceCache[key] return IdbLocalStorage._sourceCache[key]

View file

@ -143,14 +143,14 @@ export default class NameSuggestionIndex {
tags: Record<string, string>, tags: Record<string, string>,
country: string[], country: string[],
location?: [number, number], location?: [number, number],
options?:{ options?: {
/** /**
* If set, sort by frequency instead of alphabetically * If set, sort by frequency instead of alphabetically
*/ */
sortByFrequency: boolean sortByFrequency: boolean
} }
): Promise<Mapping[]> { ): Promise<Mapping[]> {
const mappings: (Mapping & {frequency: number})[] = [] const mappings: (Mapping & { frequency: number })[] = []
const frequencies = await NameSuggestionIndex.fetchFrequenciesFor(type, country) const frequencies = await NameSuggestionIndex.fetchFrequenciesFor(type, country)
for (const key in tags) { for (const key in tags) {
if (key.startsWith("_")) { if (key.startsWith("_")) {
@ -196,11 +196,11 @@ export default class NameSuggestionIndex {
// As such, it should be "true" but this is not supported // As such, it should be "true" but this is not supported
priorityIf: frequency > 0 ? new RegexTag("id", /.*/) : undefined, priorityIf: frequency > 0 ? new RegexTag("id", /.*/) : undefined,
searchTerms: { "*": [nsiItem.displayName, nsiItem.id] }, searchTerms: { "*": [nsiItem.displayName, nsiItem.id] },
frequency: frequency ?? -1 frequency: frequency ?? -1,
}) })
} }
} }
if(options?.sortByFrequency){ if (options?.sortByFrequency) {
mappings.sort((a, b) => b.frequency - a.frequency) mappings.sort((a, b) => b.frequency - a.frequency)
} }

View file

@ -17,7 +17,7 @@ export default class ThemeViewStateHashActor {
"The possible hashes are:", "The possible hashes are:",
"", "",
MenuState._menuviewTabs.map((tab) => "`menu:" + tab + "`").join(","), MenuState._menuviewTabs.map((tab) => "`menu:" + tab + "`").join(","),
MenuState._themeviewTabs.map((tab) => "`theme-menu:" + tab + "`").join(",") MenuState._themeviewTabs.map((tab) => "`theme-menu:" + tab + "`").join(","),
] ]
/** /**

View file

@ -8,26 +8,26 @@ import { GeoOperations } from "../Logic/GeoOperations"
import { RasterLayerProperties } from "./RasterLayerProperties" import { RasterLayerProperties } from "./RasterLayerProperties"
import { Utils } from "../Utils" import { Utils } from "../Utils"
export type EditorLayerIndex = (Feature<Polygon, EditorLayerIndexProperties> & export type EditorLayerIndex = (Feature<Polygon, EditorLayerIndexProperties> & RasterLayerPolygon)[]
RasterLayerPolygon)[]
export class AvailableRasterLayers { export class AvailableRasterLayers {
private static _editorLayerIndex: EditorLayerIndex = undefined private static _editorLayerIndex: EditorLayerIndex = undefined
private static _editorLayerIndexStore: UIEventSource<EditorLayerIndex> = new UIEventSource<EditorLayerIndex>(undefined) private static _editorLayerIndexStore: UIEventSource<EditorLayerIndex> =
new UIEventSource<EditorLayerIndex>(undefined)
public static async editorLayerIndex(): Promise<EditorLayerIndex> { public static async editorLayerIndex(): Promise<EditorLayerIndex> {
if(AvailableRasterLayers._editorLayerIndex !== undefined){ if (AvailableRasterLayers._editorLayerIndex !== undefined) {
return AvailableRasterLayers._editorLayerIndex return AvailableRasterLayers._editorLayerIndex
} }
console.debug("Downloading ELI") console.debug("Downloading ELI")
const eli = await Utils.downloadJson<{ features: EditorLayerIndex }>("./assets/data/editor-layer-index.json") const eli = await Utils.downloadJson<{ features: EditorLayerIndex }>(
this._editorLayerIndex = eli.features.filter(l => l.properties.id !== "Bing") "./assets/data/editor-layer-index.json"
)
this._editorLayerIndex = eli.features.filter((l) => l.properties.id !== "Bing")
this._editorLayerIndexStore.set(this._editorLayerIndex) this._editorLayerIndexStore.set(this._editorLayerIndex)
return this._editorLayerIndex return this._editorLayerIndex
} }
public static globalLayers: RasterLayerPolygon[] = globallayers.layers public static globalLayers: RasterLayerPolygon[] = globallayers.layers
.filter( .filter(
(properties) => (properties) =>
@ -41,7 +41,7 @@ export class AvailableRasterLayers {
geometry: BBox.global.asGeometry(), geometry: BBox.global.asGeometry(),
} }
) )
public static bing = <RasterLayerPolygon> bingJson public static bing = <RasterLayerPolygon>bingJson
public static readonly osmCartoProperties: RasterLayerProperties = { public static readonly osmCartoProperties: RasterLayerProperties = {
id: "osm", id: "osm",
name: "OpenStreetMap", name: "OpenStreetMap",
@ -70,10 +70,14 @@ export class AvailableRasterLayers {
return l.properties.id === "protomaps.sunny" return l.properties.id === "protomaps.sunny"
}) })
public static layersAvailableAt( location: Store<{ lon: number; lat: number }>, public static layersAvailableAt(
enableBing?: Store<boolean>): {store: Store<RasterLayerPolygon[]> } { location: Store<{ lon: number; lat: number }>,
const store = {store: undefined} enableBing?: Store<boolean>
Utils.AddLazyProperty(store, "store", () => AvailableRasterLayers._layersAvailableAt(location, enableBing)) ): { store: Store<RasterLayerPolygon[]> } {
const store = { store: undefined }
Utils.AddLazyProperty(store, "store", () =>
AvailableRasterLayers._layersAvailableAt(location, enableBing)
)
return store return store
} }
@ -81,19 +85,19 @@ export class AvailableRasterLayers {
location: Store<{ lon: number; lat: number }>, location: Store<{ lon: number; lat: number }>,
enableBing?: Store<boolean> enableBing?: Store<boolean>
): Store<RasterLayerPolygon[]> { ): Store<RasterLayerPolygon[]> {
this.editorLayerIndex() // start the download this.editorLayerIndex() // start the download
const availableLayersBboxes = Stores.ListStabilized( const availableLayersBboxes = Stores.ListStabilized(
location.mapD((loc) => { location.mapD(
const eli = AvailableRasterLayers._editorLayerIndexStore.data (loc) => {
if(!eli){ const eli = AvailableRasterLayers._editorLayerIndexStore.data
return [] if (!eli) {
} return []
const lonlat: [number, number] = [loc.lon, loc.lat] }
return eli.filter((eliPolygon) => const lonlat: [number, number] = [loc.lon, loc.lat]
BBox.get(eliPolygon).contains(lonlat) return eli.filter((eliPolygon) => BBox.get(eliPolygon).contains(lonlat))
) },
}, [AvailableRasterLayers._editorLayerIndexStore]) [AvailableRasterLayers._editorLayerIndexStore]
)
) )
return Stores.ListStabilized( return Stores.ListStabilized(
availableLayersBboxes.map( availableLayersBboxes.map(
@ -126,7 +130,6 @@ export class AvailableRasterLayers {
) )
) )
} }
} }
export class RasterLayerUtils { export class RasterLayerUtils {

View file

@ -84,7 +84,7 @@ export class Pipe<TIn, TInter, TOut> extends Conversion<TIn, TOut> {
convert(json: TIn, context: ConversionContext): TOut { convert(json: TIn, context: ConversionContext): TOut {
const r0 = this._step0.convert(json, context.inOperation(this._step0.name)) const r0 = this._step0.convert(json, context.inOperation(this._step0.name))
if(context.hasErrors() && this._failfast){ if (context.hasErrors() && this._failfast) {
return undefined return undefined
} }
return this._step1.convert(r0, context.inOperation(this._step1.name)) return this._step1.convert(r0, context.inOperation(this._step1.name))

View file

@ -12,7 +12,7 @@ export class DetectMappingsWithImages extends DesugaringStep<TagRenderingConfigJ
super( super(
"Checks that 'then'clauses in mappings don't have images, but use 'icon' instead", "Checks that 'then'clauses in mappings don't have images, but use 'icon' instead",
[], [],
"DetectMappingsWithImages", "DetectMappingsWithImages"
) )
this._doesImageExist = doesImageExist this._doesImageExist = doesImageExist
} }
@ -52,14 +52,14 @@ export class DetectMappingsWithImages extends DesugaringStep<TagRenderingConfigJ
if (!ignore) { if (!ignore) {
ctx.err( ctx.err(
`A mapping has an image in the 'then'-clause. Remove the image there and use \`"icon": <your-image>\` instead. The images found are ${images.join( `A mapping has an image in the 'then'-clause. Remove the image there and use \`"icon": <your-image>\` instead. The images found are ${images.join(
", ", ", "
)}. (This check can be turned of by adding "#": "${ignoreToken}" in the mapping, but this is discouraged`, )}. (This check can be turned of by adding "#": "${ignoreToken}" in the mapping, but this is discouraged`
) )
} else { } else {
ctx.info( ctx.info(
`Ignored image ${images.join( `Ignored image ${images.join(
", ", ", "
)} in 'then'-clause of a mapping as this check has been disabled`, )} in 'then'-clause of a mapping as this check has been disabled`
) )
for (const image of images) { for (const image of images) {

View file

@ -1,7 +1,10 @@
import { DesugaringStep } from "./Conversion" import { DesugaringStep } from "./Conversion"
import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson" import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
import { LayerConfigJson } from "../Json/LayerConfigJson" import { LayerConfigJson } from "../Json/LayerConfigJson"
import { MappingConfigJson, QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson" import {
MappingConfigJson,
QuestionableTagRenderingConfigJson,
} from "../Json/QuestionableTagRenderingConfigJson"
import { ConversionContext } from "./ConversionContext" import { ConversionContext } from "./ConversionContext"
import { Translation } from "../../../UI/i18n/Translation" import { Translation } from "../../../UI/i18n/Translation"
import NameSuggestionIndex from "../../../Logic/Web/NameSuggestionIndex" import NameSuggestionIndex from "../../../Logic/Web/NameSuggestionIndex"
@ -20,17 +23,17 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
convert( convert(
json: TagRenderingConfigJson | QuestionableTagRenderingConfigJson, json: TagRenderingConfigJson | QuestionableTagRenderingConfigJson,
context: ConversionContext, context: ConversionContext
): TagRenderingConfigJson { ): TagRenderingConfigJson {
if (json["special"] !== undefined) { if (json["special"] !== undefined) {
context.err( context.err(
"Detected `special` on the top level. Did you mean `{\"render\":{ \"special\": ... }}`", 'Detected `special` on the top level. Did you mean `{"render":{ "special": ... }}`'
) )
} }
if (Object.keys(json).length === 1 && typeof json["render"] === "string") { if (Object.keys(json).length === 1 && typeof json["render"] === "string") {
context.warn( context.warn(
`use the content directly instead of {render: ${JSON.stringify(json["render"])}}`, `use the content directly instead of {render: ${JSON.stringify(json["render"])}}`
) )
} }
@ -42,7 +45,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
const mapping: MappingConfigJson = json.mappings[i] const mapping: MappingConfigJson = json.mappings[i]
CheckTranslation.noUndefined.convert( CheckTranslation.noUndefined.convert(
mapping.then, mapping.then,
context.enters("mappings", i, "then"), context.enters("mappings", i, "then")
) )
if (!mapping.if) { if (!mapping.if) {
console.log( console.log(
@ -51,7 +54,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
"if", "if",
mapping.if, mapping.if,
context.path.join("."), context.path.join("."),
mapping.then, mapping.then
) )
context.enters("mappings", i, "if").err("No `if` is defined") context.enters("mappings", i, "if").err("No `if` is defined")
} }
@ -61,7 +64,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
context context
.enters("mappings", i, "addExtraTags", j) .enters("mappings", i, "addExtraTags", j)
.err( .err(
"Detected a 'null' or 'undefined' value. Either specify a tag or delete this item", "Detected a 'null' or 'undefined' value. Either specify a tag or delete this item"
) )
} }
} }
@ -72,18 +75,18 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
context context
.enters("mappings", i, "then") .enters("mappings", i, "then")
.warn( .warn(
"A mapping should not start with 'yes' or 'no'. If the attribute is known, it will only show 'yes' or 'no' <i>without</i> the question, resulting in a weird phrasing in the information box", "A mapping should not start with 'yes' or 'no'. If the attribute is known, it will only show 'yes' or 'no' <i>without</i> the question, resulting in a weird phrasing in the information box"
) )
} }
} }
} }
if (json["group"]) { if (json["group"]) {
context.err("Groups are deprecated, use `\"label\": [\"" + json["group"] + "\"]` instead") context.err('Groups are deprecated, use `"label": ["' + json["group"] + '"]` instead')
} }
if (json["question"] && json.freeform?.key === undefined && json.mappings === undefined) { if (json["question"] && json.freeform?.key === undefined && json.mappings === undefined) {
context.err( context.err(
"A question is defined, but no mappings nor freeform (key) are. Add at least one of them", "A question is defined, but no mappings nor freeform (key) are. Add at least one of them"
) )
} }
if (json["question"] && !json.freeform && (json.mappings?.length ?? 0) == 1) { if (json["question"] && !json.freeform && (json.mappings?.length ?? 0) == 1) {
@ -93,7 +96,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
context context
.enter("questionHint") .enter("questionHint")
.err( .err(
"A questionHint is defined, but no question is given. As such, the questionHint will never be shown", "A questionHint is defined, but no question is given. As such, the questionHint will never be shown"
) )
} }
@ -101,7 +104,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
context context
.enters("icon", "size") .enters("icon", "size")
.err( .err(
"size is not a valid attribute. Did you mean 'class'? Class can be one of `small`, `medium` or `large`", "size is not a valid attribute. Did you mean 'class'? Class can be one of `small`, `medium` or `large`"
) )
} }
@ -111,10 +114,10 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
.enter("render") .enter("render")
.err( .err(
"This tagRendering allows to set a value to key " + "This tagRendering allows to set a value to key " +
json.freeform.key + json.freeform.key +
", but does not define a `render`. Please, add a value here which contains `{" + ", but does not define a `render`. Please, add a value here which contains `{" +
json.freeform.key + json.freeform.key +
"}`", "}`"
) )
} else { } else {
const render = new Translation(<any>json.render) const render = new Translation(<any>json.render)
@ -145,7 +148,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
const keyFirstArg = ["canonical", "fediverse_link", "translated"] const keyFirstArg = ["canonical", "fediverse_link", "translated"]
if ( if (
keyFirstArg.some( keyFirstArg.some(
(funcName) => txt.indexOf(`{${funcName}(${json.freeform.key}`) >= 0, (funcName) => txt.indexOf(`{${funcName}(${json.freeform.key}`) >= 0
) )
) { ) {
continue continue
@ -169,7 +172,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
context context
.enter("render") .enter("render")
.err( .err(
`The rendering for language ${ln} does not contain \`{${json.freeform.key}}\`. Did you perhaps forget to set "freeform.type: 'wikidata'"?`, `The rendering for language ${ln} does not contain \`{${json.freeform.key}}\`. Did you perhaps forget to set "freeform.type: 'wikidata'"?`
) )
continue continue
} }
@ -181,7 +184,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
context context
.enter("render") .enter("render")
.err( .err(
`The rendering for language ${ln} does not contain \`{${json.freeform.key}}\`. However, it does contain ${json.freeform.key} without braces. Did you forget the braces?\n\tThe current text is ${txt}`, `The rendering for language ${ln} does not contain \`{${json.freeform.key}}\`. However, it does contain ${json.freeform.key} without braces. Did you forget the braces?\n\tThe current text is ${txt}`
) )
continue continue
} }
@ -189,7 +192,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
context context
.enter("render") .enter("render")
.err( .err(
`The rendering for language ${ln} does not contain \`{${json.freeform.key}}\`. This is a bug, as this rendering should show exactly this freeform key!\n\tThe current text is ${txt}`, `The rendering for language ${ln} does not contain \`{${json.freeform.key}}\`. This is a bug, as this rendering should show exactly this freeform key!\n\tThe current text is ${txt}`
) )
} }
} }
@ -204,22 +207,22 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
.enters("freeform", "type") .enters("freeform", "type")
.err( .err(
"No entry found in the 'Name Suggestion Index'. None of the 'osmSource'-tags match an entry in the NSI.\n\tOsmSource-tags are " + "No entry found in the 'Name Suggestion Index'. None of the 'osmSource'-tags match an entry in the NSI.\n\tOsmSource-tags are " +
tags.map((t) => new Tag(t.key, t.value).asHumanString()).join(" ; "), tags.map((t) => new Tag(t.key, t.value).asHumanString()).join(" ; ")
) )
} }
} else if (json.freeform.type === "nsi") { } else if (json.freeform.type === "nsi") {
context context
.enters("freeform", "type") .enters("freeform", "type")
.warn( .warn(
"No need to explicitly set type to 'NSI', autodetected based on freeform type", "No need to explicitly set type to 'NSI', autodetected based on freeform type"
) )
} }
} }
if (json.render && json["question"] && json.freeform === undefined) { if (json.render && json["question"] && json.freeform === undefined) {
context.err( context.err(
`Detected a tagrendering which takes input without freeform key in ${context}; the question is ${new Translation( `Detected a tagrendering which takes input without freeform key in ${context}; the question is ${new Translation(
json["question"], json["question"]
).textFor("en")}`, ).textFor("en")}`
) )
} }
@ -230,9 +233,9 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
.enters("freeform", "type") .enters("freeform", "type")
.err( .err(
"Unknown type: " + "Unknown type: " +
freeformType + freeformType +
"; try one of " + "; try one of " +
Validators.availableTypes.join(", "), Validators.availableTypes.join(", ")
) )
} }
} }

View file

@ -24,7 +24,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
path: string, path: string,
isBuiltin: boolean, isBuiltin: boolean,
doesImageExist: DoesImageExist, doesImageExist: DoesImageExist,
studioValidations: boolean, studioValidations: boolean
) { ) {
super("Runs various checks against common mistakes for a layer", [], "PrevalidateLayer") super("Runs various checks against common mistakes for a layer", [], "PrevalidateLayer")
this._path = path this._path = path
@ -50,7 +50,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
context context
.enter("source") .enter("source")
.err( .err(
"No source section is defined; please define one as data is not loaded otherwise", "No source section is defined; please define one as data is not loaded otherwise"
) )
} else { } else {
if (json.source === "special" || json.source === "special:library") { if (json.source === "special" || json.source === "special:library") {
@ -58,7 +58,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
context context
.enters("source", "osmTags") .enters("source", "osmTags")
.err( .err(
"No osmTags defined in the source section - these should always be present, even for geojson layer", "No osmTags defined in the source section - these should always be present, even for geojson layer"
) )
} else { } else {
const osmTags = TagUtils.Tag(json.source["osmTags"], context + "source.osmTags") const osmTags = TagUtils.Tag(json.source["osmTags"], context + "source.osmTags")
@ -67,7 +67,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
.enters("source", "osmTags") .enters("source", "osmTags")
.err( .err(
"The source states tags which give a very wide selection: it only uses negative expressions, which will result in too much and unexpected data. Add at least one required tag. The tags are:\n\t" + "The source states tags which give a very wide selection: it only uses negative expressions, which will result in too much and unexpected data. Add at least one required tag. The tags are:\n\t" +
osmTags.asHumanString(false, false, {}), osmTags.asHumanString(false, false, {})
) )
} }
} }
@ -93,10 +93,10 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
.enter("syncSelection") .enter("syncSelection")
.err( .err(
"Invalid sync-selection: must be one of " + "Invalid sync-selection: must be one of " +
LayerConfig.syncSelectionAllowed.map((v) => `'${v}'`).join(", ") + LayerConfig.syncSelectionAllowed.map((v) => `'${v}'`).join(", ") +
" but got '" + " but got '" +
json.syncSelection + json.syncSelection +
"'", "'"
) )
} }
if (json["pointRenderings"]?.length > 0) { if (json["pointRenderings"]?.length > 0) {
@ -115,7 +115,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
} }
json.pointRendering?.forEach((pr, i) => json.pointRendering?.forEach((pr, i) =>
this._validatePointRendering.convert(pr, context.enters("pointeRendering", i)), this._validatePointRendering.convert(pr, context.enters("pointeRendering", i))
) )
if (json["mapRendering"]) { if (json["mapRendering"]) {
@ -132,8 +132,8 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
if (!Constants.priviliged_layers.find((x) => x == json.id)) { if (!Constants.priviliged_layers.find((x) => x == json.id)) {
context.err( context.err(
"Layer " + "Layer " +
json.id + json.id +
" uses 'special' as source.osmTags. However, this layer is not a priviliged layer", " uses 'special' as source.osmTags. However, this layer is not a priviliged layer"
) )
} }
} }
@ -148,19 +148,19 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
context context
.enter("title") .enter("title")
.err( .err(
"This layer does not have a title defined but it does have tagRenderings. Not having a title will disable the popups, resulting in an unclickable element. Please add a title. If not having a popup is intended and the tagrenderings need to be kept (e.g. in a library layer), set `title: null` to disable this error.", "This layer does not have a title defined but it does have tagRenderings. Not having a title will disable the popups, resulting in an unclickable element. Please add a title. If not having a popup is intended and the tagrenderings need to be kept (e.g. in a library layer), set `title: null` to disable this error."
) )
} }
if (json.title === null) { if (json.title === null) {
context.info( context.info(
"Title is `null`. This results in an element that cannot be clicked - even though tagRenderings is set.", "Title is `null`. This results in an element that cannot be clicked - even though tagRenderings is set."
) )
} }
{ {
// Check for multiple, identical builtin questions - usability for studio users // Check for multiple, identical builtin questions - usability for studio users
const duplicates = Utils.Duplicates( const duplicates = Utils.Duplicates(
<string[]>json.tagRenderings.filter((tr) => typeof tr === "string"), <string[]>json.tagRenderings.filter((tr) => typeof tr === "string")
) )
for (let i = 0; i < json.tagRenderings.length; i++) { for (let i = 0; i < json.tagRenderings.length; i++) {
const tagRendering = json.tagRenderings[i] const tagRendering = json.tagRenderings[i]
@ -190,7 +190,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
{ {
// duplicate ids in tagrenderings check // duplicate ids in tagrenderings check
const duplicates = Utils.NoNull( const duplicates = Utils.NoNull(
Utils.Duplicates(Utils.NoNull((json.tagRenderings ?? []).map((tr) => tr["id"]))), Utils.Duplicates(Utils.NoNull((json.tagRenderings ?? []).map((tr) => tr["id"])))
) )
if (duplicates.length > 0) { if (duplicates.length > 0) {
// It is tempting to add an index to this warning; however, due to labels the indices here might be different from the index in the tagRendering list // It is tempting to add an index to this warning; however, due to labels the indices here might be different from the index in the tagRendering list
@ -198,11 +198,11 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
.enter("tagRenderings") .enter("tagRenderings")
.err( .err(
"Some tagrenderings have a duplicate id: " + "Some tagrenderings have a duplicate id: " +
duplicates.join(", ") + duplicates.join(", ") +
"\n" + "\n" +
JSON.stringify( JSON.stringify(
json.tagRenderings.filter((tr) => duplicates.indexOf(tr["id"]) >= 0), json.tagRenderings.filter((tr) => duplicates.indexOf(tr["id"]) >= 0)
), )
) )
} }
} }
@ -235,8 +235,8 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
if (json["overpassTags"] !== undefined) { if (json["overpassTags"] !== undefined) {
context.err( context.err(
"Layer " + "Layer " +
json.id + json.id +
"still uses the old 'overpassTags'-format. Please use \"source\": {\"osmTags\": <tags>}' instead of \"overpassTags\": <tags> (note: this isn't your fault, the custom theme generator still spits out the old format)", 'still uses the old \'overpassTags\'-format. Please use "source": {"osmTags": <tags>}\' instead of "overpassTags": <tags> (note: this isn\'t your fault, the custom theme generator still spits out the old format)'
) )
} }
const forbiddenTopLevel = [ const forbiddenTopLevel = [
@ -256,7 +256,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
} }
if (json["hideUnderlayingFeaturesMinPercentage"] !== undefined) { if (json["hideUnderlayingFeaturesMinPercentage"] !== undefined) {
context.err( context.err(
"Layer " + json.id + " contains an old 'hideUnderlayingFeaturesMinPercentage'", "Layer " + json.id + " contains an old 'hideUnderlayingFeaturesMinPercentage'"
) )
} }
@ -273,9 +273,9 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
if (this._path != undefined && this._path.indexOf(expected) < 0) { if (this._path != undefined && this._path.indexOf(expected) < 0) {
context.err( context.err(
"Layer is in an incorrect place. The path is " + "Layer is in an incorrect place. The path is " +
this._path + this._path +
", but expected " + ", but expected " +
expected, expected
) )
} }
} }
@ -293,13 +293,13 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
.enter(["tagRenderings", ...emptyIndexes]) .enter(["tagRenderings", ...emptyIndexes])
.err( .err(
`Some tagrendering-ids are empty or have an emtpy string; this is not allowed (at ${emptyIndexes.join( `Some tagrendering-ids are empty or have an emtpy string; this is not allowed (at ${emptyIndexes.join(
",", ","
)}])`, )}])`
) )
} }
const duplicateIds = Utils.Duplicates( const duplicateIds = Utils.Duplicates(
(json.tagRenderings ?? [])?.map((f) => f["id"]).filter((id) => id !== "questions"), (json.tagRenderings ?? [])?.map((f) => f["id"]).filter((id) => id !== "questions")
) )
if (duplicateIds.length > 0 && !Utils.runningFromConsole) { if (duplicateIds.length > 0 && !Utils.runningFromConsole) {
context context
@ -323,7 +323,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
if (json.tagRenderings !== undefined) { if (json.tagRenderings !== undefined) {
new On( new On(
"tagRenderings", "tagRenderings",
new Each(new ValidateTagRenderings(json, this._doesImageExist)), new Each(new ValidateTagRenderings(json, this._doesImageExist))
).convert(json, context) ).convert(json, context)
} }
@ -350,7 +350,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
context context
.enters("pointRendering", i, "marker", indexM, "icon", "condition") .enters("pointRendering", i, "marker", indexM, "icon", "condition")
.err( .err(
"Don't set a condition in a marker as this will result in an invisible but clickable element. Use extra filters in the source instead.", "Don't set a condition in a marker as this will result in an invisible but clickable element. Use extra filters in the source instead."
) )
} }
} }
@ -388,9 +388,9 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
.enters("presets", i, "tags") .enters("presets", i, "tags")
.err( .err(
"This preset does not match the required tags of this layer. This implies that a newly added point will not show up.\n A newly created point will have properties: " + "This preset does not match the required tags of this layer. This implies that a newly added point will not show up.\n A newly created point will have properties: " +
tags.asHumanString(false, false, {}) + tags.asHumanString(false, false, {}) +
"\n The required tags are: " + "\n The required tags are: " +
baseTags.asHumanString(false, false, {}), baseTags.asHumanString(false, false, {})
) )
} }
} }

View file

@ -26,7 +26,7 @@ export class ValidateTagRenderings extends Fuse<TagRenderingConfigJson> {
new On("question", new ValidatePossibleLinks()), new On("question", new ValidatePossibleLinks()),
new On("questionHint", new ValidatePossibleLinks()), new On("questionHint", new ValidatePossibleLinks()),
new On("mappings", new Each(new On("then", new ValidatePossibleLinks()))), new On("mappings", new Each(new On("then", new ValidatePossibleLinks()))),
new MiscTagRenderingChecks(layerConfig), new MiscTagRenderingChecks(layerConfig)
) )
} }
} }

View file

@ -22,7 +22,7 @@ export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
doesImageExist: DoesImageExist, doesImageExist: DoesImageExist,
path: string, path: string,
isBuiltin: boolean, isBuiltin: boolean,
sharedTagRenderings?: Set<string>, sharedTagRenderings?: Set<string>
) { ) {
super("Doesn't change anything, but emits warnings and errors", [], "ValidateTheme") super("Doesn't change anything, but emits warnings and errors", [], "ValidateTheme")
this._validateImage = doesImageExist this._validateImage = doesImageExist
@ -41,15 +41,15 @@ export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
if (json["units"] !== undefined) { if (json["units"] !== undefined) {
context.err( context.err(
"The theme " + "The theme " +
json.id + json.id +
" has units defined - these should be defined on the layer instead. (Hint: use overrideAll: { '+units': ... }) ", " has units defined - these should be defined on the layer instead. (Hint: use overrideAll: { '+units': ... }) "
) )
} }
if (json["roamingRenderings"] !== undefined) { if (json["roamingRenderings"] !== undefined) {
context.err( context.err(
"Theme " + "Theme " +
json.id + json.id +
" contains an old 'roamingRenderings'. Use an 'overrideAll' instead", " contains an old 'roamingRenderings'. Use an 'overrideAll' instead"
) )
} }
} }
@ -67,10 +67,10 @@ export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
for (const remoteImage of remoteImages) { for (const remoteImage of remoteImages) {
context.err( context.err(
"Found a remote image: " + "Found a remote image: " +
remoteImage.path + remoteImage.path +
" in theme " + " in theme " +
json.id + json.id +
", please download it.", ", please download it."
) )
} }
for (const image of images) { for (const image of images) {
@ -86,17 +86,17 @@ export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
const filename = this._path.substring( const filename = this._path.substring(
this._path.lastIndexOf("/") + 1, this._path.lastIndexOf("/") + 1,
this._path.length - 5, this._path.length - 5
) )
if (theme.id !== filename) { if (theme.id !== filename) {
context.err( context.err(
"Theme ids should be the same as the name.json, but we got id: " + "Theme ids should be the same as the name.json, but we got id: " +
theme.id + theme.id +
" and filename " + " and filename " +
filename + filename +
" (" + " (" +
this._path + this._path +
")", ")"
) )
} }
this._validateImage.convert(theme.icon, context.enter("icon")) this._validateImage.convert(theme.icon, context.enter("icon"))
@ -104,13 +104,13 @@ export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
const dups = Utils.Duplicates(json.layers.map((layer) => layer["id"])) const dups = Utils.Duplicates(json.layers.map((layer) => layer["id"]))
if (dups.length > 0) { if (dups.length > 0) {
context.err( context.err(
`The theme ${json.id} defines multiple layers with id ${dups.join(", ")}`, `The theme ${json.id} defines multiple layers with id ${dups.join(", ")}`
) )
} }
if (json["mustHaveLanguage"] !== undefined) { if (json["mustHaveLanguage"] !== undefined) {
new ValidateLanguageCompleteness(...json["mustHaveLanguage"]).convert( new ValidateLanguageCompleteness(...json["mustHaveLanguage"]).convert(
theme, theme,
context, context
) )
} }
if (!json.hideFromOverview && theme.id !== "personal" && this._isBuiltin) { if (!json.hideFromOverview && theme.id !== "personal" && this._isBuiltin) {
@ -118,7 +118,7 @@ export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
const targetLanguage = theme.title.SupportedLanguages()[0] const targetLanguage = theme.title.SupportedLanguages()[0]
if (targetLanguage !== "en") { if (targetLanguage !== "en") {
context.err( context.err(
`TargetLanguage is not 'en' for public theme ${theme.id}, it is ${targetLanguage}. Move 'en' up in the title of the theme and set it as the first key`, `TargetLanguage is not 'en' for public theme ${theme.id}, it is ${targetLanguage}. Move 'en' up in the title of the theme and set it as the first key`
) )
} }

View file

@ -9,7 +9,7 @@ export class ValidateThemeAndLayers extends Fuse<LayoutConfigJson> {
doesImageExist: DoesImageExist, doesImageExist: DoesImageExist,
path: string, path: string,
isBuiltin: boolean, isBuiltin: boolean,
sharedTagRenderings?: Set<string>, sharedTagRenderings?: Set<string>
) { ) {
super( super(
"Validates a theme and the contained layers", "Validates a theme and the contained layers",
@ -19,10 +19,10 @@ export class ValidateThemeAndLayers extends Fuse<LayoutConfigJson> {
new Each( new Each(
new Bypass( new Bypass(
(layer) => Constants.added_by_default.indexOf(<any>layer.id) < 0, (layer) => Constants.added_by_default.indexOf(<any>layer.id) < 0,
new ValidateLayerConfig(undefined, isBuiltin, doesImageExist, false, true), new ValidateLayerConfig(undefined, isBuiltin, doesImageExist, false, true)
), )
), )
), )
) )
} }
} }

View file

@ -28,7 +28,7 @@ export class ValidateLanguageCompleteness extends DesugaringStep<LayoutConfig> {
super( super(
"Checks that the given object is fully translated in the specified languages", "Checks that the given object is fully translated in the specified languages",
[], [],
"ValidateLanguageCompleteness", "ValidateLanguageCompleteness"
) )
this._languages = languages ?? ["en"] this._languages = languages ?? ["en"]
} }
@ -42,18 +42,18 @@ export class ValidateLanguageCompleteness extends DesugaringStep<LayoutConfig> {
.filter( .filter(
(t) => (t) =>
t.tr.translations[neededLanguage] === undefined && t.tr.translations[neededLanguage] === undefined &&
t.tr.translations["*"] === undefined, t.tr.translations["*"] === undefined
) )
.forEach((missing) => { .forEach((missing) => {
context context
.enter(missing.context.split(".")) .enter(missing.context.split("."))
.err( .err(
`The theme ${obj.id} should be translation-complete for ` + `The theme ${obj.id} should be translation-complete for ` +
neededLanguage + neededLanguage +
", but it lacks a translation for " + ", but it lacks a translation for " +
missing.context + missing.context +
".\n\tThe known translation is " + ".\n\tThe known translation is " +
missing.tr.textFor("en"), missing.tr.textFor("en")
) )
}) })
} }
@ -70,7 +70,7 @@ export class DoesImageExist extends DesugaringStep<string> {
constructor( constructor(
knownImagePaths: Set<string>, knownImagePaths: Set<string>,
checkExistsSync: (path: string) => boolean = undefined, checkExistsSync: (path: string) => boolean = undefined,
ignore?: Set<string>, ignore?: Set<string>
) { ) {
super("Checks if an image exists", [], "DoesImageExist") super("Checks if an image exists", [], "DoesImageExist")
this._ignore = ignore this._ignore = ignore
@ -106,15 +106,15 @@ export class DoesImageExist extends DesugaringStep<string> {
if (!this._knownImagePaths.has(image)) { if (!this._knownImagePaths.has(image)) {
if (this.doesPathExist === undefined) { if (this.doesPathExist === undefined) {
context.err( context.err(
`Image with path ${image} not found or not attributed; it is used in ${context}`, `Image with path ${image} not found or not attributed; it is used in ${context}`
) )
} else if (!this.doesPathExist(image)) { } else if (!this.doesPathExist(image)) {
context.err( context.err(
`Image with path ${image} does not exist.\n Check for typo's and missing directories in the path.`, `Image with path ${image} does not exist.\n Check for typo's and missing directories in the path.`
) )
} else { } else {
context.err( context.err(
`Image with path ${image} is not attributed (but it exists); execute 'npm run query:licenses' to add the license information and/or run 'npm run generate:licenses' to compile all the license info`, `Image with path ${image} is not attributed (but it exists); execute 'npm run query:licenses' to add the license information and/or run 'npm run generate:licenses' to compile all the license info`
) )
} }
} }
@ -127,7 +127,7 @@ class OverrideShadowingCheck extends DesugaringStep<LayoutConfigJson> {
super( super(
"Checks that an 'overrideAll' does not override a single override", "Checks that an 'overrideAll' does not override a single override",
[], [],
"OverrideShadowingCheck", "OverrideShadowingCheck"
) )
} }
@ -174,7 +174,11 @@ class MiscThemeChecks extends DesugaringStep<LayoutConfigJson> {
context.err("The theme " + json.id + " has no 'layers' defined") context.err("The theme " + json.id + " has no 'layers' defined")
} }
if (!Array.isArray(json.layers)) { if (!Array.isArray(json.layers)) {
context.enter("layers").err("The 'layers'-field should be an array, but it is not. Did you pase a layer identifier and forget to add the '[' and ']'?") context
.enter("layers")
.err(
"The 'layers'-field should be an array, but it is not. Did you pase a layer identifier and forget to add the '[' and ']'?"
)
} }
if (json.socialImage === "") { if (json.socialImage === "") {
context.warn("Social image for theme " + json.id + " is the emtpy string") context.warn("Social image for theme " + json.id + " is the emtpy string")
@ -183,9 +187,9 @@ class MiscThemeChecks extends DesugaringStep<LayoutConfigJson> {
context.warn("Obsolete field `clustering` is still around") context.warn("Obsolete field `clustering` is still around")
} }
if(json.layers === undefined){ if (json.layers === undefined) {
context.err("This theme has no layers defined") context.err("This theme has no layers defined")
}else{ } else {
for (let i = 0; i < json.layers.length; i++) { for (let i = 0; i < json.layers.length; i++) {
const l = json.layers[i] const l = json.layers[i]
if (l["override"]?.["source"] === undefined) { if (l["override"]?.["source"] === undefined) {
@ -207,7 +211,7 @@ class MiscThemeChecks extends DesugaringStep<LayoutConfigJson> {
context context
.enter("overideAll") .enter("overideAll")
.err( .err(
"'overrideAll' is spelled with _two_ `r`s. You only wrote a single one of them.", "'overrideAll' is spelled with _two_ `r`s. You only wrote a single one of them."
) )
} }
return json return json
@ -219,7 +223,7 @@ export class PrevalidateTheme extends Fuse<LayoutConfigJson> {
super( super(
"Various consistency checks on the raw JSON", "Various consistency checks on the raw JSON",
new MiscThemeChecks(), new MiscThemeChecks(),
new OverrideShadowingCheck(), new OverrideShadowingCheck()
) )
} }
} }
@ -229,7 +233,7 @@ export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingCo
super( super(
"The `if`-part in a mapping might set some keys. Those keys are not allowed to be set in the `addExtraTags`, as this might result in conflicting values", "The `if`-part in a mapping might set some keys. Those keys are not allowed to be set in the `addExtraTags`, as this might result in conflicting values",
[], [],
"DetectConflictingAddExtraTags", "DetectConflictingAddExtraTags"
) )
} }
@ -256,7 +260,7 @@ export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingCo
.enters("mappings", i) .enters("mappings", i)
.err( .err(
"AddExtraTags overrides a key that is set in the `if`-clause of this mapping. Selecting this answer might thus first set one value (needed to match as answer) and then override it with a different value, resulting in an unsaveable question. The offending `addExtraTags` is " + "AddExtraTags overrides a key that is set in the `if`-clause of this mapping. Selecting this answer might thus first set one value (needed to match as answer) and then override it with a different value, resulting in an unsaveable question. The offending `addExtraTags` is " +
duplicateKeys.join(", "), duplicateKeys.join(", ")
) )
} }
} }
@ -274,13 +278,13 @@ export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTa
super( super(
"A tagRendering might set a freeform key (e.g. `name` and have an option that _should_ erase this name, e.g. `noname=yes`). Under normal circumstances, every mapping/freeform should affect all touched keys", "A tagRendering might set a freeform key (e.g. `name` and have an option that _should_ erase this name, e.g. `noname=yes`). Under normal circumstances, every mapping/freeform should affect all touched keys",
[], [],
"DetectNonErasedKeysInMappings", "DetectNonErasedKeysInMappings"
) )
} }
convert( convert(
json: QuestionableTagRenderingConfigJson, json: QuestionableTagRenderingConfigJson,
context: ConversionContext, context: ConversionContext
): QuestionableTagRenderingConfigJson { ): QuestionableTagRenderingConfigJson {
if (json.multiAnswer) { if (json.multiAnswer) {
// No need to check this here, this has its own validation // No need to check this here, this has its own validation
@ -334,8 +338,8 @@ export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTa
.enters("freeform") .enters("freeform")
.warn( .warn(
"The freeform block does not modify the key `" + "The freeform block does not modify the key `" +
neededKey + neededKey +
"` which is set in a mapping. Use `addExtraTags` to overwrite it", "` which is set in a mapping. Use `addExtraTags` to overwrite it"
) )
} }
} }
@ -353,8 +357,8 @@ export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTa
.enters("mappings", i) .enters("mappings", i)
.warn( .warn(
"This mapping does not modify the key `" + "This mapping does not modify the key `" +
neededKey + neededKey +
"` which is set in a mapping or by the freeform block. Use `addExtraTags` to overwrite it", "` which is set in a mapping or by the freeform block. Use `addExtraTags` to overwrite it"
) )
} }
} }
@ -371,7 +375,7 @@ export class DetectMappingsShadowedByCondition extends DesugaringStep<TagRenderi
super( super(
"Checks that, if the tagrendering has a condition, that a mapping is not contradictory to it, i.e. that there are no dead mappings", "Checks that, if the tagrendering has a condition, that a mapping is not contradictory to it, i.e. that there are no dead mappings",
[], [],
"DetectMappingsShadowedByCondition", "DetectMappingsShadowedByCondition"
) )
this._forceError = forceError this._forceError = forceError
} }
@ -443,7 +447,7 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
* DetectShadowedMappings.extractCalculatedTagNames({calculatedTags: ["_abc=js()"]}) // => ["_abc"] * DetectShadowedMappings.extractCalculatedTagNames({calculatedTags: ["_abc=js()"]}) // => ["_abc"]
*/ */
private static extractCalculatedTagNames( private static extractCalculatedTagNames(
layerConfig?: LayerConfigJson | { calculatedTags: string[] }, layerConfig?: LayerConfigJson | { calculatedTags: string[] }
) { ) {
return ( return (
layerConfig?.calculatedTags?.map((ct) => { layerConfig?.calculatedTags?.map((ct) => {
@ -529,16 +533,16 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
json.mappings[i]["hideInAnswer"] !== true json.mappings[i]["hideInAnswer"] !== true
) { ) {
context.warn( context.warn(
`Mapping ${i} is shadowed by mapping ${j}. However, mapping ${j} has 'hideInAnswer' set, which will result in a different rendering in question-mode.`, `Mapping ${i} is shadowed by mapping ${j}. However, mapping ${j} has 'hideInAnswer' set, which will result in a different rendering in question-mode.`
) )
} else if (doesMatch) { } else if (doesMatch) {
// The current mapping is shadowed! // The current mapping is shadowed!
context.err(`Mapping ${i} is shadowed by mapping ${j} and will thus never be shown: context.err(`Mapping ${i} is shadowed by mapping ${j} and will thus never be shown:
The mapping ${parsedConditions[i].asHumanString( The mapping ${parsedConditions[i].asHumanString(
false, false,
false, false,
{}, {}
)} is fully matched by a previous mapping (namely ${j}), which matches: )} is fully matched by a previous mapping (namely ${j}), which matches:
${parsedConditions[j].asHumanString(false, false, {})}. ${parsedConditions[j].asHumanString(false, false, {})}.
To fix this problem, you can try to: To fix this problem, you can try to:
@ -563,7 +567,7 @@ export class ValidatePossibleLinks extends DesugaringStep<string | Record<string
super( super(
"Given a possible set of translations, validates that <a href=... target='_blank'> does have `rel='noopener'` set", "Given a possible set of translations, validates that <a href=... target='_blank'> does have `rel='noopener'` set",
[], [],
"ValidatePossibleLinks", "ValidatePossibleLinks"
) )
} }
@ -593,21 +597,21 @@ export class ValidatePossibleLinks extends DesugaringStep<string | Record<string
convert( convert(
json: string | Record<string, string>, json: string | Record<string, string>,
context: ConversionContext, context: ConversionContext
): string | Record<string, string> { ): string | Record<string, string> {
if (typeof json === "string") { if (typeof json === "string") {
if (this.isTabnabbingProne(json)) { if (this.isTabnabbingProne(json)) {
context.err( context.err(
"The string " + "The string " +
json + json +
" has a link targeting `_blank`, but it doesn't have `rel='noopener'` set. This gives rise to reverse tabnapping", " has a link targeting `_blank`, but it doesn't have `rel='noopener'` set. This gives rise to reverse tabnapping"
) )
} }
} else { } else {
for (const k in json) { for (const k in json) {
if (this.isTabnabbingProne(json[k])) { if (this.isTabnabbingProne(json[k])) {
context.err( context.err(
`The translation for ${k} '${json[k]}' has a link targeting \`_blank\`, but it doesn't have \`rel='noopener'\` set. This gives rise to reverse tabnapping`, `The translation for ${k} '${json[k]}' has a link targeting \`_blank\`, but it doesn't have \`rel='noopener'\` set. This gives rise to reverse tabnapping`
) )
} }
} }
@ -625,7 +629,7 @@ export class CheckTranslation extends DesugaringStep<Translatable> {
super( super(
"Checks that a translation is valid and internally consistent", "Checks that a translation is valid and internally consistent",
["*"], ["*"],
"CheckTranslation", "CheckTranslation"
) )
this._allowUndefined = allowUndefined this._allowUndefined = allowUndefined
} }
@ -672,7 +676,7 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
isBuiltin: boolean, isBuiltin: boolean,
doesImageExist: DoesImageExist, doesImageExist: DoesImageExist,
studioValidations: boolean = false, studioValidations: boolean = false,
skipDefaultLayers: boolean = false, skipDefaultLayers: boolean = false
) { ) {
super("Thin wrapper around 'ValidateLayer", [], "ValidateLayerConfig") super("Thin wrapper around 'ValidateLayer", [], "ValidateLayerConfig")
this.validator = new ValidateLayer( this.validator = new ValidateLayer(
@ -680,7 +684,7 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
isBuiltin, isBuiltin,
doesImageExist, doesImageExist,
studioValidations, studioValidations,
skipDefaultLayers, skipDefaultLayers
) )
} }
@ -708,7 +712,7 @@ export class ValidatePointRendering extends DesugaringStep<PointRenderingConfigJ
context context
.enter("markers") .enter("markers")
.err( .err(
`Detected a field 'markerS' in pointRendering. It is written as a singular case`, `Detected a field 'markerS' in pointRendering. It is written as a singular case`
) )
} }
if (json.marker && !Array.isArray(json.marker)) { if (json.marker && !Array.isArray(json.marker)) {
@ -718,7 +722,7 @@ export class ValidatePointRendering extends DesugaringStep<PointRenderingConfigJ
context context
.enter("location") .enter("location")
.err( .err(
"A pointRendering should have at least one 'location' to defined where it should be rendered. ", "A pointRendering should have at least one 'location' to defined where it should be rendered. "
) )
} }
return json return json
@ -737,26 +741,26 @@ export class ValidateLayer extends Conversion<
isBuiltin: boolean, isBuiltin: boolean,
doesImageExist: DoesImageExist, doesImageExist: DoesImageExist,
studioValidations: boolean = false, studioValidations: boolean = false,
skipDefaultLayers: boolean = false, skipDefaultLayers: boolean = false
) { ) {
super("Doesn't change anything, but emits warnings and errors", [], "ValidateLayer") super("Doesn't change anything, but emits warnings and errors", [], "ValidateLayer")
this._prevalidation = new PrevalidateLayer( this._prevalidation = new PrevalidateLayer(
path, path,
isBuiltin, isBuiltin,
doesImageExist, doesImageExist,
studioValidations, studioValidations
) )
this._skipDefaultLayers = skipDefaultLayers this._skipDefaultLayers = skipDefaultLayers
} }
convert( convert(
json: LayerConfigJson, json: LayerConfigJson,
context: ConversionContext, context: ConversionContext
): { parsed: LayerConfig; raw: LayerConfigJson } { ): { parsed: LayerConfig; raw: LayerConfigJson } {
context = context.inOperation(this.name) context = context.inOperation(this.name)
if (typeof json === "string") { if (typeof json === "string") {
context.err( context.err(
`Not a valid layer: the layerConfig is a string. 'npm run generate:layeroverview' might be needed`, `Not a valid layer: the layerConfig is a string. 'npm run generate:layeroverview' might be needed`
) )
return undefined return undefined
} }
@ -787,7 +791,7 @@ export class ValidateLayer extends Conversion<
context context
.enters("calculatedTags", i) .enters("calculatedTags", i)
.err( .err(
`Invalid function definition: the custom javascript is invalid:${e}. The offending javascript code is:\n ${code}`, `Invalid function definition: the custom javascript is invalid:${e}. The offending javascript code is:\n ${code}`
) )
} }
} }
@ -835,7 +839,7 @@ export class ValidateLayer extends Conversion<
context context
.enters("allowMove", "enableAccuracy") .enters("allowMove", "enableAccuracy")
.err( .err(
"`enableAccuracy` is written with two C in the first occurrence and only one in the last", "`enableAccuracy` is written with two C in the first occurrence and only one in the last"
) )
} }
@ -866,8 +870,8 @@ export class ValidateFilter extends DesugaringStep<FilterConfigJson> {
.enters("fields", i) .enters("fields", i)
.err( .err(
`Invalid filter: ${type} is not a valid textfield type.\n\tTry one of ${Array.from( `Invalid filter: ${type} is not a valid textfield type.\n\tTry one of ${Array.from(
Validators.availableTypes, Validators.availableTypes
).join(",")}`, ).join(",")}`
) )
} }
} }
@ -884,13 +888,13 @@ export class DetectDuplicateFilters extends DesugaringStep<{
super( super(
"Tries to detect layers where a shared filter can be used (or where similar filters occur)", "Tries to detect layers where a shared filter can be used (or where similar filters occur)",
[], [],
"DetectDuplicateFilters", "DetectDuplicateFilters"
) )
} }
convert( convert(
json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] }, json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] },
context: ConversionContext, context: ConversionContext
): { layers: LayerConfigJson[]; themes: LayoutConfigJson[] } { ): { layers: LayerConfigJson[]; themes: LayoutConfigJson[] } {
const { layers, themes } = json const { layers, themes } = json
const perOsmTag = new Map< const perOsmTag = new Map<
@ -954,7 +958,7 @@ export class DetectDuplicateFilters extends DesugaringStep<{
filter: FilterConfigJson filter: FilterConfigJson
}[] }[]
>, >,
layout?: LayoutConfigJson | undefined, layout?: LayoutConfigJson | undefined
): void { ): void {
if (layer.filter === undefined || layer.filter === null) { if (layer.filter === undefined || layer.filter === null) {
return return
@ -994,7 +998,7 @@ export class DetectDuplicatePresets extends DesugaringStep<LayoutConfig> {
super( super(
"Detects mappings which have identical (english) names or identical mappings.", "Detects mappings which have identical (english) names or identical mappings.",
["presets"], ["presets"],
"DetectDuplicatePresets", "DetectDuplicatePresets"
) )
} }
@ -1005,13 +1009,13 @@ export class DetectDuplicatePresets extends DesugaringStep<LayoutConfig> {
if (new Set(enNames).size != enNames.length) { if (new Set(enNames).size != enNames.length) {
const dups = Utils.Duplicates(enNames) const dups = Utils.Duplicates(enNames)
const layersWithDup = json.layers.filter((l) => const layersWithDup = json.layers.filter((l) =>
l.presets.some((p) => dups.indexOf(p.title.textFor("en")) >= 0), l.presets.some((p) => dups.indexOf(p.title.textFor("en")) >= 0)
) )
const layerIds = layersWithDup.map((l) => l.id) const layerIds = layersWithDup.map((l) => l.id)
context.err( context.err(
`This theme has multiple presets which are named:${dups}, namely layers ${layerIds.join( `This theme has multiple presets which are named:${dups}, namely layers ${layerIds.join(
", ", ", "
)} this is confusing for contributors and is probably the result of reusing the same layer multiple times. Use \`{"override": {"=presets": []}}\` to remove some presets`, )} this is confusing for contributors and is probably the result of reusing the same layer multiple times. Use \`{"override": {"=presets": []}}\` to remove some presets`
) )
} }
@ -1026,17 +1030,17 @@ export class DetectDuplicatePresets extends DesugaringStep<LayoutConfig> {
Utils.SameObject(presetATags, presetBTags) && Utils.SameObject(presetATags, presetBTags) &&
Utils.sameList( Utils.sameList(
presetA.preciseInput.snapToLayers, presetA.preciseInput.snapToLayers,
presetB.preciseInput.snapToLayers, presetB.preciseInput.snapToLayers
) )
) { ) {
context.err( context.err(
`This theme has multiple presets with the same tags: ${presetATags.asHumanString( `This theme has multiple presets with the same tags: ${presetATags.asHumanString(
false, false,
false, false,
{}, {}
)}, namely the preset '${presets[i].title.textFor("en")}' and '${presets[ )}, namely the preset '${presets[i].title.textFor("en")}' and '${presets[
j j
].title.textFor("en")}'`, ].title.textFor("en")}'`
) )
} }
} }
@ -1061,13 +1065,13 @@ export class ValidateThemeEnsemble extends Conversion<
super( super(
"Validates that all themes together are logical, i.e. no duplicate ids exists within (overriden) themes", "Validates that all themes together are logical, i.e. no duplicate ids exists within (overriden) themes",
[], [],
"ValidateThemeEnsemble", "ValidateThemeEnsemble"
) )
} }
convert( convert(
json: LayoutConfig[], json: LayoutConfig[],
context: ConversionContext, context: ConversionContext
): Map< ): Map<
string, string,
{ {
@ -1118,11 +1122,11 @@ export class ValidateThemeEnsemble extends Conversion<
context.err( context.err(
[ [
"The layer with id '" + "The layer with id '" +
id + id +
"' is found in multiple themes with different tag definitions:", "' is found in multiple themes with different tag definitions:",
"\t In theme " + oldTheme + ":\t" + oldTags.asHumanString(false, false, {}), "\t In theme " + oldTheme + ":\t" + oldTags.asHumanString(false, false, {}),
"\tIn theme " + theme.id + ":\t" + tags.asHumanString(false, false, {}), "\tIn theme " + theme.id + ":\t" + tags.asHumanString(false, false, {}),
].join("\n"), ].join("\n")
) )
} }
} }

View file

@ -338,7 +338,7 @@ export default class LayoutConfig implements LayoutInformation {
...json, ...json,
layers: json.layers.filter((l) => l["id"] !== "favourite"), layers: json.layers.filter((l) => l["id"] !== "favourite"),
} }
const usedImages =json._usedImages const usedImages = json._usedImages
usedImages.sort() usedImages.sort()
this.usedImages = Utils.Dedup(usedImages) this.usedImages = Utils.Dedup(usedImages)

View file

@ -963,7 +963,7 @@ export class TagRenderingConfigUtils {
tags, tags,
country.split(";"), country.split(";"),
center, center,
{sortByFrequency: true} { sortByFrequency: true }
) )
) )
}) })

View file

@ -2,7 +2,11 @@ import LayoutConfig from "./ThemeConfig/LayoutConfig"
import { SpecialVisualizationState } from "../UI/SpecialVisualization" import { SpecialVisualizationState } from "../UI/SpecialVisualization"
import { Changes } from "../Logic/Osm/Changes" import { Changes } from "../Logic/Osm/Changes"
import { Store, UIEventSource } from "../Logic/UIEventSource" import { Store, UIEventSource } from "../Logic/UIEventSource"
import { FeatureSource, IndexedFeatureSource, WritableFeatureSource } from "../Logic/FeatureSource/FeatureSource" import {
FeatureSource,
IndexedFeatureSource,
WritableFeatureSource,
} from "../Logic/FeatureSource/FeatureSource"
import { OsmConnection } from "../Logic/Osm/OsmConnection" import { OsmConnection } from "../Logic/Osm/OsmConnection"
import { ExportableMap, MapProperties } from "./MapProperties" import { ExportableMap, MapProperties } from "./MapProperties"
import LayerState from "../Logic/State/LayerState" import LayerState from "../Logic/State/LayerState"
@ -46,7 +50,9 @@ import BackgroundLayerResetter from "../Logic/Actors/BackgroundLayerResetter"
import SaveFeatureSourceToLocalStorage from "../Logic/FeatureSource/Actors/SaveFeatureSourceToLocalStorage" import SaveFeatureSourceToLocalStorage from "../Logic/FeatureSource/Actors/SaveFeatureSourceToLocalStorage"
import BBoxFeatureSource from "../Logic/FeatureSource/Sources/TouchesBboxFeatureSource" import BBoxFeatureSource from "../Logic/FeatureSource/Sources/TouchesBboxFeatureSource"
import ThemeViewStateHashActor from "../Logic/Web/ThemeViewStateHashActor" import ThemeViewStateHashActor from "../Logic/Web/ThemeViewStateHashActor"
import NoElementsInViewDetector, { FeatureViewState } from "../Logic/Actors/NoElementsInViewDetector" import NoElementsInViewDetector, {
FeatureViewState,
} from "../Logic/Actors/NoElementsInViewDetector"
import FilteredLayer from "./FilteredLayer" import FilteredLayer from "./FilteredLayer"
import { PreferredRasterLayerSelector } from "../Logic/Actors/PreferredRasterLayerSelector" import { PreferredRasterLayerSelector } from "../Logic/Actors/PreferredRasterLayerSelector"
import { ImageUploadManager } from "../Logic/ImageProviders/ImageUploadManager" import { ImageUploadManager } from "../Logic/ImageProviders/ImageUploadManager"
@ -155,7 +161,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.featureSwitches = new FeatureSwitchState(layout) this.featureSwitches = new FeatureSwitchState(layout)
this.guistate = new MenuState( this.guistate = new MenuState(
this.featureSwitches.featureSwitchWelcomeMessage.data, this.featureSwitches.featureSwitchWelcomeMessage.data,
layout.id, layout.id
) )
this.map = new UIEventSource<MlMap>(undefined) this.map = new UIEventSource<MlMap>(undefined)
const geolocationState = new GeoLocationState() const geolocationState = new GeoLocationState()
@ -171,14 +177,14 @@ export default class ThemeViewState implements SpecialVisualizationState {
oauth_token: QueryParameters.GetQueryParameter( oauth_token: QueryParameters.GetQueryParameter(
"oauth_token", "oauth_token",
undefined, undefined,
"Used to complete the login", "Used to complete the login"
), ),
}) })
this.userRelatedState = new UserRelatedState( this.userRelatedState = new UserRelatedState(
this.osmConnection, this.osmConnection,
layout, layout,
this.featureSwitches, this.featureSwitches,
this.mapProperties, this.mapProperties
) )
this.userRelatedState.fixateNorth.addCallbackAndRunD((fixated) => { this.userRelatedState.fixateNorth.addCallbackAndRunD((fixated) => {
this.mapProperties.allowRotating.setData(fixated !== "yes") this.mapProperties.allowRotating.setData(fixated !== "yes")
@ -189,20 +195,20 @@ export default class ThemeViewState implements SpecialVisualizationState {
geolocationState, geolocationState,
this.selectedElement, this.selectedElement,
this.mapProperties, this.mapProperties,
this.userRelatedState.gpsLocationHistoryRetentionTime, this.userRelatedState.gpsLocationHistoryRetentionTime
) )
this.geolocationControl = new GeolocationControlState(this.geolocation, this.mapProperties) this.geolocationControl = new GeolocationControlState(this.geolocation, this.mapProperties)
this.availableLayers = AvailableRasterLayers.layersAvailableAt( this.availableLayers = AvailableRasterLayers.layersAvailableAt(
this.mapProperties.location, this.mapProperties.location,
this.osmConnection.isLoggedIn, this.osmConnection.isLoggedIn
) )
this.layerState = new LayerState( this.layerState = new LayerState(
this.osmConnection, this.osmConnection,
layout.layers, layout.layers,
layout.id, layout.id,
this.featureSwitches.featureSwitchLayerDefault, this.featureSwitches.featureSwitchLayerDefault
) )
{ {
@ -211,7 +217,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
const isDisplayed = QueryParameters.GetBooleanQueryParameter( const isDisplayed = QueryParameters.GetBooleanQueryParameter(
"overlay-" + rasterInfo.id, "overlay-" + rasterInfo.id,
rasterInfo.defaultState ?? true, rasterInfo.defaultState ?? true,
"Whether or not overlay layer " + rasterInfo.id + " is shown", "Whether or not overlay layer " + rasterInfo.id + " is shown"
) )
const state = { isDisplayed } const state = { isDisplayed }
overlayLayerStates.set(rasterInfo.id, state) overlayLayerStates.set(rasterInfo.id, state)
@ -236,7 +242,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.osmConnection.Backend(), this.osmConnection.Backend(),
(id) => this.layerState.filteredLayers.get(id).isDisplayed, (id) => this.layerState.filteredLayers.get(id).isDisplayed,
mvtAvailableLayers, mvtAvailableLayers,
this.fullNodeDatabase, this.fullNodeDatabase
) )
let currentViewIndex = 0 let currentViewIndex = 0
@ -254,7 +260,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
id: "current_view_" + currentViewIndex, id: "current_view_" + currentViewIndex,
}), }),
] ]
}), })
) )
this.featuresInView = new BBoxFeatureSource(layoutSource, this.mapProperties.bounds) this.featuresInView = new BBoxFeatureSource(layoutSource, this.mapProperties.bounds)
@ -272,19 +278,19 @@ export default class ThemeViewState implements SpecialVisualizationState {
featureSwitches: this.featureSwitches, featureSwitches: this.featureSwitches,
}, },
layout?.isLeftRightSensitive() ?? false, layout?.isLeftRightSensitive() ?? false,
(e) => this.reportError(e), (e) => this.reportError(e)
) )
this.historicalUserLocations = this.geolocation.historicalUserLocations this.historicalUserLocations = this.geolocation.historicalUserLocations
this.newFeatures = new NewGeometryFromChangesFeatureSource( this.newFeatures = new NewGeometryFromChangesFeatureSource(
this.changes, this.changes,
layoutSource, layoutSource,
this.featureProperties, this.featureProperties
) )
layoutSource.addSource(this.newFeatures) layoutSource.addSource(this.newFeatures)
const perLayer = new PerLayerFeatureSourceSplitter( const perLayer = new PerLayerFeatureSourceSplitter(
Array.from(this.layerState.filteredLayers.values()).filter( Array.from(this.layerState.filteredLayers.values()).filter(
(l) => l.layerDef?.source !== null, (l) => l.layerDef?.source !== null
), ),
new ChangeGeometryApplicator(this.indexedFeatures, this.changes), new ChangeGeometryApplicator(this.indexedFeatures, this.changes),
{ {
@ -295,10 +301,10 @@ export default class ThemeViewState implements SpecialVisualizationState {
"Got ", "Got ",
features.length, features.length,
"leftover features, such as", "leftover features, such as",
features[0].properties, features[0].properties
) )
}, },
}, }
) )
this.perLayer = perLayer.perLayer this.perLayer = perLayer.perLayer
} }
@ -338,12 +344,12 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.lastClickObject = new LastClickFeatureSource( this.lastClickObject = new LastClickFeatureSource(
this.layout, this.layout,
this.mapProperties.lastClickLocation, this.mapProperties.lastClickLocation,
this.userRelatedState.addNewFeatureMode, this.userRelatedState.addNewFeatureMode
) )
this.osmObjectDownloader = new OsmObjectDownloader( this.osmObjectDownloader = new OsmObjectDownloader(
this.osmConnection.Backend(), this.osmConnection.Backend(),
this.changes, this.changes
) )
this.perLayerFiltered = this.showNormalDataOn(this.map) this.perLayerFiltered = this.showNormalDataOn(this.map)
@ -354,7 +360,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
currentZoom: this.mapProperties.zoom, currentZoom: this.mapProperties.zoom,
layerState: this.layerState, layerState: this.layerState,
bounds: this.visualFeedbackViewportBounds, bounds: this.visualFeedbackViewportBounds,
}, }
) )
this.hasDataInView = new NoElementsInViewDetector(this).hasFeatureInView this.hasDataInView = new NoElementsInViewDetector(this).hasFeatureInView
this.imageUploadManager = new ImageUploadManager( this.imageUploadManager = new ImageUploadManager(
@ -362,7 +368,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
Imgur.singleton, Imgur.singleton,
this.featureProperties, this.featureProperties,
this.osmConnection, this.osmConnection,
this.changes, this.changes
) )
this.favourites = new FavouritesFeatureSource(this) this.favourites = new FavouritesFeatureSource(this)
const longAgo = new Date() const longAgo = new Date()
@ -408,7 +414,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
LayoutSource.fromCacheZoomLevel, LayoutSource.fromCacheZoomLevel,
fs, fs,
this.featureProperties, this.featureProperties,
fs.layer.layerDef.maxAgeOfCache, fs.layer.layerDef.maxAgeOfCache
) )
toLocalStorage.set(layerId, storage) toLocalStorage.set(layerId, storage)
}) })
@ -421,7 +427,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
const doShowLayer = this.mapProperties.zoom.map( const doShowLayer = this.mapProperties.zoom.map(
(z) => (z) =>
(fs.layer.isDisplayed?.data ?? true) && z >= (fs.layer.layerDef?.minzoom ?? 0), (fs.layer.isDisplayed?.data ?? true) && z >= (fs.layer.layerDef?.minzoom ?? 0),
[fs.layer.isDisplayed], [fs.layer.isDisplayed]
) )
if (!doShowLayer.data && this.featureSwitches.featureSwitchFilter.data === false) { if (!doShowLayer.data && this.featureSwitches.featureSwitchFilter.data === false) {
@ -438,7 +444,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
fs.layer, fs.layer,
fs, fs,
(id) => this.featureProperties.getStore(id), (id) => this.featureProperties.getStore(id),
this.layerState.globalFilters, this.layerState.globalFilters
) )
filteringFeatureSource.set(layerName, filtered) filteringFeatureSource.set(layerName, filtered)
@ -582,7 +588,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
return return
} }
this.selectClosestAtCenter(0) this.selectClosestAtCenter(0)
}, }
) )
for (let i = 1; i < 9; i++) { for (let i = 1; i < 9; i++) {
@ -600,7 +606,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
onUp: true, onUp: true,
}, },
doc, doc,
() => this.selectClosestAtCenter(i - 1), () => this.selectClosestAtCenter(i - 1)
) )
} }
@ -617,7 +623,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
if (this.featureSwitches.featureSwitchBackgroundSelection.data) { if (this.featureSwitches.featureSwitchBackgroundSelection.data) {
this.guistate.backgroundLayerSelectionIsOpened.setData(true) this.guistate.backgroundLayerSelectionIsOpened.setData(true)
} }
}, }
) )
Hotkeys.RegisterHotkey( Hotkeys.RegisterHotkey(
{ {
@ -629,60 +635,57 @@ export default class ThemeViewState implements SpecialVisualizationState {
if (this.featureSwitches.featureSwitchFilter.data) { if (this.featureSwitches.featureSwitchFilter.data) {
this.guistate.openFilterView() this.guistate.openFilterView()
} }
}, }
) )
Hotkeys.RegisterHotkey( Hotkeys.RegisterHotkey(
{ shift: "O" }, { shift: "O" },
Translations.t.hotkeyDocumentation.selectMapnik, Translations.t.hotkeyDocumentation.selectMapnik,
() => { () => {
this.mapProperties.rasterLayer.setData(AvailableRasterLayers.osmCarto) this.mapProperties.rasterLayer.setData(AvailableRasterLayers.osmCarto)
}, }
) )
const setLayerCategory = (category: EliCategory) => { const setLayerCategory = (category: EliCategory) => {
const timeOfCall = new Date() const timeOfCall = new Date()
const available = this.availableLayers.store.addCallbackAndRunD( const available = this.availableLayers.store.addCallbackAndRunD((available) => {
available => { const now = new Date()
const now = new Date() const timeDiff = (now.getTime() - timeOfCall.getTime()) / 1000
const timeDiff= (now.getTime() - timeOfCall.getTime()) / 1000 if (timeDiff > 3) {
if(timeDiff > 3){ return true // unregister
return true // unregister }
} const current = this.mapProperties.rasterLayer
const current = this.mapProperties.rasterLayer const best = RasterLayerUtils.SelectBestLayerAccordingTo(
const best = RasterLayerUtils.SelectBestLayerAccordingTo( available,
available, category,
category, current.data
current.data, )
) console.log("Best layer for category", category, "is", best.properties.id)
console.log("Best layer for category", category, "is", best.properties.id) current.setData(best)
current.setData(best) })
},
)
} }
Hotkeys.RegisterHotkey( Hotkeys.RegisterHotkey(
{ nomod: "O" }, { nomod: "O" },
Translations.t.hotkeyDocumentation.selectOsmbasedmap, Translations.t.hotkeyDocumentation.selectOsmbasedmap,
() => setLayerCategory("osmbasedmap"), () => setLayerCategory("osmbasedmap")
) )
Hotkeys.RegisterHotkey( Hotkeys.RegisterHotkey(
{ nomod: "M" }, { nomod: "M" },
Translations.t.hotkeyDocumentation.selectMap, Translations.t.hotkeyDocumentation.selectMap,
() => setLayerCategory("map"), () => setLayerCategory("map")
) )
Hotkeys.RegisterHotkey( Hotkeys.RegisterHotkey(
{ nomod: "P" }, { nomod: "P" },
Translations.t.hotkeyDocumentation.selectAerial, Translations.t.hotkeyDocumentation.selectAerial,
() => setLayerCategory("photo"), () => setLayerCategory("photo")
) )
Hotkeys.RegisterHotkey( Hotkeys.RegisterHotkey(
{ nomod: "L" }, { nomod: "L" },
Translations.t.hotkeyDocumentation.geolocate, Translations.t.hotkeyDocumentation.geolocate,
() => { () => {
this.geolocationControl.handleClick() this.geolocationControl.handleClick()
}, }
) )
return true return true
}) })
@ -694,7 +697,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
Translations.t.hotkeyDocumentation.translationMode, Translations.t.hotkeyDocumentation.translationMode,
() => { () => {
Locale.showLinkToWeblate.setData(!Locale.showLinkToWeblate.data) Locale.showLinkToWeblate.setData(!Locale.showLinkToWeblate.data)
}, }
) )
} }
@ -705,7 +708,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
const normalLayers = this.layout.layers.filter( const normalLayers = this.layout.layers.filter(
(l) => (l) =>
Constants.priviliged_layers.indexOf(<any>l.id) < 0 && Constants.priviliged_layers.indexOf(<any>l.id) < 0 &&
!l.id.startsWith("note_import"), !l.id.startsWith("note_import")
) )
const maxzoom = Math.min(...normalLayers.map((l) => l.minzoom)) const maxzoom = Math.min(...normalLayers.map((l) => l.minzoom))
@ -713,7 +716,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
(l) => (l) =>
Constants.priviliged_layers.indexOf(<any>l.id) < 0 && Constants.priviliged_layers.indexOf(<any>l.id) < 0 &&
l.source.geojsonSource === undefined && l.source.geojsonSource === undefined &&
l.doCount, l.doCount
) )
const summaryTileSource = new SummaryTileSource( const summaryTileSource = new SummaryTileSource(
Constants.SummaryServer, Constants.SummaryServer,
@ -722,7 +725,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.mapProperties, this.mapProperties,
{ {
isActive: this.mapProperties.zoom.map((z) => z < maxzoom), isActive: this.mapProperties.zoom.map((z) => z < maxzoom),
}, }
) )
return new SummaryTileSourceRewriter(summaryTileSource, this.layerState.filteredLayers) return new SummaryTileSourceRewriter(summaryTileSource, this.layerState.filteredLayers)
@ -743,12 +746,12 @@ export default class ThemeViewState implements SpecialVisualizationState {
gps_location_history: this.geolocation.historicalUserLocations, gps_location_history: this.geolocation.historicalUserLocations,
gps_track: this.geolocation.historicalUserLocationsTrack, gps_track: this.geolocation.historicalUserLocationsTrack,
selected_element: new StaticFeatureSource( selected_element: new StaticFeatureSource(
this.selectedElement.map((f) => (f === undefined ? empty : [f])), this.selectedElement.map((f) => (f === undefined ? empty : [f]))
), ),
range: new StaticFeatureSource( range: new StaticFeatureSource(
this.mapProperties.maxbounds.map((bbox) => this.mapProperties.maxbounds.map((bbox) =>
bbox === undefined ? empty : <Feature[]>[bbox.asGeoJson({ id: "range" })], bbox === undefined ? empty : <Feature[]>[bbox.asGeoJson({ id: "range" })]
), )
), ),
current_view: this.currentView, current_view: this.currentView,
favourite: this.favourites, favourite: this.favourites,
@ -763,7 +766,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
ShowDataLayer.showRange( ShowDataLayer.showRange(
this.map, this.map,
new StaticFeatureSource([bbox.asGeoJson({ id: "range" })]), new StaticFeatureSource([bbox.asGeoJson({ id: "range" })]),
this.featureSwitches.featureSwitchIsTesting, this.featureSwitches.featureSwitchIsTesting
) )
} }
const currentViewLayer = this.layout.layers.find((l) => l.id === "current_view") const currentViewLayer = this.layout.layers.find((l) => l.id === "current_view")
@ -777,7 +780,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
currentViewLayer, currentViewLayer,
this.layout, this.layout,
this.osmObjectDownloader, this.osmObjectDownloader,
this.featureProperties, this.featureProperties
) )
}) })
} }
@ -821,20 +824,20 @@ export default class ThemeViewState implements SpecialVisualizationState {
const lastClickLayerConfig = new LayerConfig( const lastClickLayerConfig = new LayerConfig(
<LayerConfigJson>last_click_layerconfig, <LayerConfigJson>last_click_layerconfig,
"last_click", "last_click"
) )
const lastClickFiltered = const lastClickFiltered =
lastClickLayerConfig.isShown === undefined lastClickLayerConfig.isShown === undefined
? specialLayers.last_click ? specialLayers.last_click
: specialLayers.last_click.features.mapD((fs) => : specialLayers.last_click.features.mapD((fs) =>
fs.filter((f) => { fs.filter((f) => {
const matches = lastClickLayerConfig.isShown.matchesProperties( const matches = lastClickLayerConfig.isShown.matchesProperties(
f.properties, f.properties
) )
console.debug("LastClick ", f, "matches", matches) console.debug("LastClick ", f, "matches", matches)
return matches return matches
}), })
) )
new ShowDataLayer(this.map, { new ShowDataLayer(this.map, {
features: new StaticFeatureSource(lastClickFiltered), features: new StaticFeatureSource(lastClickFiltered),
layer: lastClickLayerConfig, layer: lastClickLayerConfig,
@ -881,7 +884,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.mapProperties.rasterLayer, this.mapProperties.rasterLayer,
this.availableLayers, this.availableLayers,
this.featureSwitches.backgroundLayerId, this.featureSwitches.backgroundLayerId,
this.userRelatedState.preferredBackgroundLayer, this.userRelatedState.preferredBackgroundLayer
) )
} }
@ -897,7 +900,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
? ">>> _Not_ reporting error to report server as testmode is on" ? ">>> _Not_ reporting error to report server as testmode is on"
: ">>> Reporting error to", : ">>> Reporting error to",
Constants.ErrorReportServer, Constants.ErrorReportServer,
message, message
) )
if (isTesting) { if (isTesting) {
return return

View file

@ -21,7 +21,7 @@
class={$classnames} class={$classnames}
> >
{#if $icon} {#if $icon}
<Icon clss="w-4 h-4" icon={$icon}/> <Icon clss="w-4 h-4" icon={$icon} />
{/if} {/if}
{@html $text} {@html $text}
</a> </a>

View file

@ -2,7 +2,7 @@ import { Utils } from "../../Utils"
import BaseUIElement from "../BaseUIElement" import BaseUIElement from "../BaseUIElement"
/** /**
* @deprecated * @deprecated
*/ */
export default class Img extends BaseUIElement { export default class Img extends BaseUIElement {
private readonly _src: string private readonly _src: string
private readonly _rawSvg: boolean private readonly _rawSvg: boolean

View file

@ -12,14 +12,13 @@
export let cls = "m-0.5 p-0.5 sm:p-1 md:m-1" export let cls = "m-0.5 p-0.5 sm:p-1 md:m-1"
export let enabled: Store<boolean> = new ImmutableStore(true) export let enabled: Store<boolean> = new ImmutableStore(true)
export let arialabel: Translation = undefined export let arialabel: Translation = undefined
export let arialabelDynamic : Store<Translation> = new ImmutableStore(arialabel) export let arialabelDynamic: Store<Translation> = new ImmutableStore(arialabel)
let arialabelString = arialabelDynamic.bind(tr => tr?.current) let arialabelString = arialabelDynamic.bind((tr) => tr?.current)
export let htmlElem: UIEventSource<HTMLElement> = undefined export let htmlElem: UIEventSource<HTMLElement> = undefined
let _htmlElem: HTMLElement let _htmlElem: HTMLElement
$: { $: {
htmlElem?.setData(_htmlElem) htmlElem?.setData(_htmlElem)
} }
</script> </script>
<button <button

View file

@ -40,10 +40,7 @@
style={svelteElem.getStyle()} style={svelteElem.getStyle()}
/> />
{:else} {:else}
<svelte:component <svelte:component this={svelteElem?._svelteComponent} {...svelteElem._props} />
this={svelteElem?._svelteComponent}
{...svelteElem._props}
/>
{/if} {/if}
{:else} {:else}
<span bind:this={elem} /> <span bind:this={elem} />

View file

@ -21,14 +21,14 @@
{#if $txt} {#if $txt}
{#if cls} {#if cls}
<span class={cls}> <span class={cls}>
<span lang={$lang}> <span lang={$lang}>
{@html Utils.purify($txt)} {@html Utils.purify($txt)}
</span>
<WeblateLink context={t?.context} />
</span> </span>
<WeblateLink context={t?.context} />
</span>
{:else} {:else}
<span lang={$lang}> <span lang={$lang}>
{@html Utils.purify($txt)} {@html Utils.purify($txt)}
</span> </span>
<WeblateLink context={t?.context} /> <WeblateLink context={t?.context} />

View file

@ -31,7 +31,7 @@
target="_blank" target="_blank"
tabindex="-1" tabindex="-1"
> >
<LanguageIcon class="font-gray"/> <LanguageIcon class="font-gray" />
</a> </a>
{/if} {/if}
{/if} {/if}

View file

@ -52,7 +52,9 @@
{#if layout.official} {#if layout.official}
<a <a
class="flex" class="flex"
href={"https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Themes/" + layout.id + ".md"} href={"https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Themes/" +
layout.id +
".md"}
target="_blank" target="_blank"
> >
<DocumentMagnifyingGlass class="h-6 w-6" /> <DocumentMagnifyingGlass class="h-6 w-6" />
@ -65,7 +67,7 @@
<a class="flex" href={Utils.OsmChaLinkFor(31, layout.id)}> <a class="flex" href={Utils.OsmChaLinkFor(31, layout.id)}>
<DocumentChartBar class="h-6 w-6" /> <DocumentChartBar class="h-6 w-6" />
<Tr t={Translations.t.general.attribution.openOsmcha.Subs({theme: layout.title})}/> <Tr t={Translations.t.general.attribution.openOsmcha.Subs({ theme: layout.title })} />
</a> </a>
{/if} {/if}

View file

@ -16,7 +16,7 @@
import { TranslateIcon } from "@rgossiaux/svelte-heroicons/solid" import { TranslateIcon } from "@rgossiaux/svelte-heroicons/solid"
import Osm_logo from "../../assets/svg/Osm_logo.svelte" import Osm_logo from "../../assets/svg/Osm_logo.svelte"
import Generic_map from "../../assets/svg/Generic_map.svelte" import Generic_map from "../../assets/svg/Generic_map.svelte"
import { UserGroupIcon} from "@babeard/svelte-heroicons/solid" import { UserGroupIcon } from "@babeard/svelte-heroicons/solid"
import Marker from "../Map/Marker.svelte" import Marker from "../Map/Marker.svelte"
export let state: SpecialVisualizationState export let state: SpecialVisualizationState

View file

@ -27,10 +27,7 @@
{:else if $pending.length === 1} {:else if $pending.length === 1}
<Tr cls="alert" t={Translations.t.general.uploadPendingSingle} /> <Tr cls="alert" t={Translations.t.general.uploadPendingSingle} />
{:else if $pending.length > 1} {:else if $pending.length > 1}
<Tr <Tr cls="alert" t={Translations.t.general.uploadPending.Subs({ count: $pending.length })} />
cls="alert"
t={Translations.t.general.uploadPending.Subs({ count: $pending.length })}
/>
{/if} {/if}
{#each $errors as error} {#each $errors as error}
@ -43,24 +40,19 @@
</button> </button>
<ul> <ul>
{#each $pending as pending} {#each $pending as pending}
<li> <li>
{#if pending.changes !== undefined} {#if pending.changes !== undefined}
Create {pending.type}/{pending.id} {JSON.stringify(TagUtils.KVObjtoProperties(pending.tags))} Create {pending.type}/{pending.id}
{JSON.stringify(TagUtils.KVObjtoProperties(pending.tags))}
{:else} {:else}
Modify {pending.type}/{pending.id} {JSON.stringify(pending.tags)} Modify {pending.type}/{pending.id} {JSON.stringify(pending.tags)}
{/if} {/if}
{#if pending.type === "way" && pending.changes?.nodes} {#if pending.type === "way" && pending.changes?.nodes}
{pending.changes.nodes.join(" ")} {pending.changes.nodes.join(" ")}
{/if} {/if}
</li> </li>
{/each} {/each}
</ul> </ul>
{/if} {/if}
</div> </div>

View file

@ -17,11 +17,11 @@
export let highlightedRendering: UIEventSource<string> = undefined export let highlightedRendering: UIEventSource<string> = undefined
export let tags: UIEventSource<Record<string, string>> = state?.featureProperties?.getStore( export let tags: UIEventSource<Record<string, string>> = state?.featureProperties?.getStore(
selectedElement.properties.id, selectedElement.properties.id
) )
let isAddNew = tags.mapD( let isAddNew = tags.mapD(
(t) => t?.id?.startsWith(LastClickFeatureSource.newPointElementId) ?? false, (t) => t?.id?.startsWith(LastClickFeatureSource.newPointElementId) ?? false
) )
export let layer: LayerConfig export let layer: LayerConfig
@ -32,29 +32,32 @@
onDestroy( onDestroy(
state.userRelatedState.preferencesAsTags.addCallbackAndRun((tags) => { state.userRelatedState.preferencesAsTags.addCallbackAndRun((tags) => {
_metatags = tags _metatags = tags
}), })
) )
} }
let knownTagRenderings: Store<TagRenderingConfig[]> = tags.mapD((tgs) => let knownTagRenderings: Store<TagRenderingConfig[]> = tags.mapD((tgs) =>
layer?.tagRenderings?.filter( layer?.tagRenderings?.filter((config) => {
(config) => { if (mustMatchLabels !== undefined) {
if (mustMatchLabels !== undefined) { if (
if (!mustMatchLabels.has(config.id) && !config?.labels?.some(l => mustMatchLabels.has(l))) { !mustMatchLabels.has(config.id) &&
return false !config?.labels?.some((l) => mustMatchLabels.has(l))
} ) {
} else if (dontMatchLabels) {
if (dontMatchLabels.has(config.id) || config?.labels?.some(l => dontMatchLabels.has(l))) {
return false
}
}
if (!config.IsKnown(tgs)) {
return false return false
} }
return (config.condition?.matchesProperties(tgs) ?? true) && } else if (dontMatchLabels) {
(config.metacondition?.matchesProperties({ ...tgs, ..._metatags }) ?? true) if (dontMatchLabels.has(config.id) || config?.labels?.some((l) => dontMatchLabels.has(l))) {
}, return false
), }
}
if (!config.IsKnown(tgs)) {
return false
}
return (
(config.condition?.matchesProperties(tgs) ?? true) &&
(config.metacondition?.matchesProperties({ ...tgs, ..._metatags }) ?? true)
)
})
) )
</script> </script>

View file

@ -123,7 +123,7 @@
<Copyable {state} text={linkToShare} /> <Copyable {state} text={linkToShare} />
</div> </div>
<div class="flex justify-center"> <div class="flex justify-center">
<img src={new Qr(linkToShare).toImageElement(125)} style="width: 125px"/> <img src={new Qr(linkToShare).toImageElement(125)} style="width: 125px" />
</div> </div>
<Tr t={tr.embedIntro} /> <Tr t={tr.embedIntro} />

View file

@ -78,9 +78,12 @@
<div class="flex w-full flex-wrap sm:flex-nowrap"> <div class="flex w-full flex-wrap sm:flex-nowrap">
<If condition={state.featureSwitches.featureSwitchGeolocation}> <If condition={state.featureSwitches.featureSwitchGeolocation}>
<button
<button disabled={!$gpsAvailable} class:disabled={!$gpsAvailable} class="flex w-full items-center gap-x-2" on:click={jumpToCurrentLocation}> disabled={!$gpsAvailable}
class:disabled={!$gpsAvailable}
class="flex w-full items-center gap-x-2"
on:click={jumpToCurrentLocation}
>
<GeolocationIndicator {state} /> <GeolocationIndicator {state} />
<Tr t={$gpsExplanation} /> <Tr t={$gpsExplanation} />
</button> </button>

View file

@ -6,7 +6,7 @@
<Accordion> <Accordion>
<AccordionItem open={expanded} paddingDefault="p-0" inactiveClass="text-black"> <AccordionItem open={expanded} paddingDefault="p-0" inactiveClass="text-black">
<span slot="header" class="p-2 text-base w-full"> <span slot="header" class="w-full p-2 text-base">
<slot name="header" /> <slot name="header" />
</span> </span>
<div class="low-interaction rounded-b p-2"> <div class="low-interaction rounded-b p-2">

View file

@ -17,7 +17,6 @@ export default class Toggle extends VariableUiElement {
super(isEnabled?.map((isEnabled) => (isEnabled ? showEnabled : showDisabled))) super(isEnabled?.map((isEnabled) => (isEnabled ? showEnabled : showDisabled)))
this.isEnabled = isEnabled this.isEnabled = isEnabled
} }
} }
/** /**
@ -34,5 +33,4 @@ export class ClickableToggle extends Toggle {
super(showEnabled, showDisabled, isEnabled) super(showEnabled, showDisabled, isEnabled)
this.isEnabled = isEnabled this.isEnabled = isEnabled
} }
} }

View file

@ -148,7 +148,7 @@
<UserCircleIcon class={clss} {color} /> <UserCircleIcon class={clss} {color} />
{:else if Utils.isEmoji(icon)} {:else if Utils.isEmoji(icon)}
<span style={`font-size: ${emojiHeight}px; line-height: ${emojiHeight}px`}> <span style={`font-size: ${emojiHeight}px; line-height: ${emojiHeight}px`}>
{icon} {icon}
</span> </span>
{:else} {:else}
<img class={clss ?? "h-full w-full"} src={icon} aria-hidden="true" alt="" /> <img class={clss ?? "h-full w-full"} src={icon} aria-hidden="true" alt="" />

View file

@ -22,7 +22,7 @@ class SingleBackgroundHandler {
constructor( constructor(
map: Store<MLMap>, map: Store<MLMap>,
targetLayer: RasterLayerPolygon, targetLayer: RasterLayerPolygon,
background: UIEventSource<RasterLayerPolygon | undefined>, background: UIEventSource<RasterLayerPolygon | undefined>
) { ) {
this._targetLayer = targetLayer this._targetLayer = targetLayer
this._map = map this._map = map
@ -57,10 +57,9 @@ class SingleBackgroundHandler {
"Removing raster layer", "Removing raster layer",
this._targetLayer.properties.id, this._targetLayer.properties.id,
"map moved and not been used for", "map moved and not been used for",
SingleBackgroundHandler.DEACTIVATE_AFTER, SingleBackgroundHandler.DEACTIVATE_AFTER
) )
try { try {
if (map.getLayer(<string>this._targetLayer.properties.id)) { if (map.getLayer(<string>this._targetLayer.properties.id)) {
map.removeLayer(<string>this._targetLayer.properties.id) map.removeLayer(<string>this._targetLayer.properties.id)
} }
@ -157,7 +156,7 @@ class SingleBackgroundHandler {
"raster-opacity": 0, "raster-opacity": 0,
}, },
}, },
addLayerBeforeId, addLayerBeforeId
) )
this.opacity.addCallbackAndRun((o) => { this.opacity.addCallbackAndRun((o) => {
try { try {
@ -175,14 +174,14 @@ class SingleBackgroundHandler {
private fadeOut() { private fadeOut() {
Stores.Chronic( Stores.Chronic(
8, 8,
() => this.opacity.data > 0 && this._deactivationTime !== undefined, () => this.opacity.data > 0 && this._deactivationTime !== undefined
).addCallback((_) => this.opacity.setData(Math.max(0, this.opacity.data - this.fadeStep))) ).addCallback((_) => this.opacity.setData(Math.max(0, this.opacity.data - this.fadeStep)))
} }
private fadeIn() { private fadeIn() {
Stores.Chronic( Stores.Chronic(
8, 8,
() => this.opacity.data < 1.0 && this._deactivationTime === undefined, () => this.opacity.data < 1.0 && this._deactivationTime === undefined
).addCallback((_) => this.opacity.setData(Math.min(1.0, this.opacity.data + this.fadeStep))) ).addCallback((_) => this.opacity.setData(Math.min(1.0, this.opacity.data + this.fadeStep)))
} }
} }
@ -200,7 +199,7 @@ export default class RasterLayerHandler {
} }
public static prepareSource( public static prepareSource(
layer: RasterLayerProperties, layer: RasterLayerProperties
): RasterSourceSpecification | VectorSourceSpecification { ): RasterSourceSpecification | VectorSourceSpecification {
if (layer.type === "vector") { if (layer.type === "vector") {
const vs: VectorSourceSpecification = { const vs: VectorSourceSpecification = {

View file

@ -14,7 +14,7 @@
import TitledPanel from "../Base/TitledPanel.svelte" import TitledPanel from "../Base/TitledPanel.svelte"
import Loading from "../Base/Loading.svelte" import Loading from "../Base/Loading.svelte"
export let availableLayers: {store: Store<RasterLayerPolygon[]>} export let availableLayers: { store: Store<RasterLayerPolygon[]> }
export let mapproperties: MapProperties export let mapproperties: MapProperties
export let userstate: UserRelatedState export let userstate: UserRelatedState
export let map: Store<MlMap> export let map: Store<MlMap>
@ -35,7 +35,7 @@
function availableForCategory(type: CategoryType): Store<RasterLayerPolygon[]> { function availableForCategory(type: CategoryType): Store<RasterLayerPolygon[]> {
const keywords = categories[type] const keywords = categories[type]
return _availableLayers.mapD((available) => return _availableLayers.mapD((available) =>
available.filter((layer) => keywords.indexOf(<EliCategory>layer.properties.category) >= 0), available.filter((layer) => keywords.indexOf(<EliCategory>layer.properties.category) >= 0)
) )
} }
@ -57,7 +57,7 @@
<Tr slot="title" t={Translations.t.general.backgroundMap} /> <Tr slot="title" t={Translations.t.general.backgroundMap} />
{#if $_availableLayers?.length < 1} {#if $_availableLayers?.length < 1}
<Loading /> <Loading />
{:else } {:else}
<div class="grid h-full w-full grid-cols-1 gap-2 md:grid-cols-2"> <div class="grid h-full w-full grid-cols-1 gap-2 md:grid-cols-2">
<RasterLayerPicker <RasterLayerPicker
availableLayers={$photoLayers} availableLayers={$photoLayers}

View file

@ -20,7 +20,11 @@
export let favourite: UIEventSource<string> | undefined = undefined export let favourite: UIEventSource<string> | undefined = undefined
let rasterLayer = new UIEventSource<RasterLayerPolygon>(availableLayers[0]) let rasterLayer = new UIEventSource<RasterLayerPolygon>(availableLayers[0])
let rasterLayerId = rasterLayer.sync(l => l?.properties?.id, [], id => availableLayers.find(l => l.properties.id === id)) let rasterLayerId = rasterLayer.sync(
(l) => l?.properties?.id,
[],
(id) => availableLayers.find((l) => l.properties.id === id)
)
rasterLayer.setData(availableLayers[0]) rasterLayer.setData(availableLayers[0])
$: rasterLayer.setData(availableLayers[0]) $: rasterLayer.setData(availableLayers[0])
@ -32,13 +36,13 @@
return return
} }
rasterLayer.setData(fav) rasterLayer.setData(fav)
}), })
) )
onDestroy( onDestroy(
rasterLayer.addCallbackAndRunD((selected) => { rasterLayer.addCallbackAndRunD((selected) => {
favourite?.setData(selected.properties.id) favourite?.setData(selected.properties.id)
}), })
) )
} }
@ -52,7 +56,7 @@
} else { } else {
rasterLayerOnMap.setData(undefined) rasterLayerOnMap.setData(undefined)
} }
}), })
) )
} }

View file

@ -1,14 +1,12 @@
<script lang="ts"> <script lang="ts">
import { IdbLocalStorage } from "../../Logic/Web/IdbLocalStorage" import { IdbLocalStorage } from "../../Logic/Web/IdbLocalStorage"
import { Utils } from "../../Utils" import { Utils } from "../../Utils"
function clearCaches(){ function clearCaches() {
IdbLocalStorage.clearAll() IdbLocalStorage.clearAll()
Utils.download("./service-worker-clear") Utils.download("./service-worker-clear")
} }
export let msg : string export let msg: string
</script> </script>
<button on:click={() => clearCaches()} class="flex gap-x-2"> <button on:click={() => clearCaches()} class="flex gap-x-2">

View file

@ -15,13 +15,12 @@
export let header: string export let header: string
export let layer: LayerConfig export let layer: LayerConfig
let headerTr = layer.tagRenderings.find(tr => tr.id === header) let headerTr = layer.tagRenderings.find((tr) => tr.id === header)
</script> </script>
<AccordionSingle> <AccordionSingle>
<div slot="header"> <div slot="header">
<TagRenderingAnswer {tags} {layer} config={headerTr} {state} {selectedElement} /> <TagRenderingAnswer {tags} {layer} config={headerTr} {state} {selectedElement} />
</div> </div>
<SelectedElementView mustMatchLabels={new Set(labels)} {state} {layer} {tags} {selectedElement}/> <SelectedElementView mustMatchLabels={new Set(labels)} {state} {layer} {tags} {selectedElement} />
</AccordionSingle> </AccordionSingle>

View file

@ -45,7 +45,7 @@
location: new UIEventSource({ lon, lat }), location: new UIEventSource({ lon, lat }),
minzoom: new UIEventSource($reason.minZoom), minzoom: new UIEventSource($reason.minZoom),
rasterLayer: state.mapProperties.rasterLayer, rasterLayer: state.mapProperties.rasterLayer,
zoom: new UIEventSource($reason?.startZoom ?? 16) zoom: new UIEventSource($reason?.startZoom ?? 16),
} }
} }
@ -71,7 +71,7 @@
<AccordionSingle> <AccordionSingle>
<span slot="header" class="flex"> <span slot="header" class="flex">
{#if moveWizardState.reasons.length === 1} {#if moveWizardState.reasons.length === 1}
<Icon icon={moveWizardState.reasons[0].icon} clss="w-6 h-6"/> <Icon icon={moveWizardState.reasons[0].icon} clss="w-6 h-6" />
<Tr t={Translations.T(moveWizardState.reasons[0].invitingText)} /> <Tr t={Translations.T(moveWizardState.reasons[0].invitingText)} />
{:else} {:else}
<Move class="h-6 w-6" /> <Move class="h-6 w-6" />
@ -87,7 +87,7 @@
currentStep = "pick_location" currentStep = "pick_location"
}} }}
> >
<Icon icon={reasonSpec.icon} clss="w-12 h-12"/> <Icon icon={reasonSpec.icon} clss="w-12 h-12" />
<Tr t={Translations.T(reasonSpec.text)} /> <Tr t={Translations.T(reasonSpec.text)} />
</button> </button>
{/each} {/each}

View file

@ -18,7 +18,6 @@
export let minzoom: number export let minzoom: number
export let zoomMoreMessage: string export let zoomMoreMessage: string
let curZoom = state.mapProperties.zoom let curZoom = state.mapProperties.zoom
const isClosed = tags.map((tags) => (tags["closed_at"] ?? "") !== "") const isClosed = tags.map((tags) => (tags["closed_at"] ?? "") !== "")
@ -29,7 +28,6 @@
tags.data["closed_at"] = new Date().toISOString() tags.data["closed_at"] = new Date().toISOString()
tags.ping() tags.ping()
} }
</script> </script>
<LoginToggle {state}> <LoginToggle {state}>
@ -37,7 +35,6 @@
<Tr t={t.loginToClose} /> <Tr t={t.loginToClose} />
</div> </div>
{#if $isClosed} {#if $isClosed}
<Tr cls="thanks" t={t.isClosed} /> <Tr cls="thanks" t={t.isClosed} />
{:else if minzoom <= $curZoom} {:else if minzoom <= $curZoom}
@ -50,5 +47,4 @@
{:else if zoomMoreMessage} {:else if zoomMoreMessage}
{zoomMoreMessage} {zoomMoreMessage}
{/if} {/if}
</LoginToggle> </LoginToggle>

View file

@ -16,18 +16,14 @@
let [lon, lat] = GeoOperations.centerpointCoordinates(feature) let [lon, lat] = GeoOperations.centerpointCoordinates(feature)
const includeLayout = window.location.pathname const includeLayout = window.location.pathname.split("/").at(-1).startsWith("theme")
.split("/") const layout = includeLayout ? "layout=" + state.layout.id + "&" : ""
.at(-1) let id: Store<string> = tags.mapD((tags) => tags.id)
.startsWith("theme") let url = id.mapD(
const layout = includeLayout (id) =>
? "layout=" + state.layout.id + "&" `${window.location.protocol}//${window.location.host}${window.location.pathname}?${layout}lat=${lat}&lon=${lon}&z=15` +
: "" `#${id}`
let id: Store<string> = tags.mapD(tags => tags.id) )
let url = id.mapD(id => `${window.location.protocol}//${window.location.host}${window.location.pathname}?${layout}lat=${lat}&lon=${lon}&z=15` +
`#${id}`)
function toggleSize() { function toggleSize() {
if (size.data !== bigSize) { if (size.data !== bigSize) {
@ -42,5 +38,9 @@
<!-- Not yet uploaded, doesn't have a fixed ID --> <!-- Not yet uploaded, doesn't have a fixed ID -->
<Loading /> <Loading />
{:else} {:else}
<img on:click={() => toggleSize()} src={new Qr($url).toImageElement($size)} style={`width: ${$size}px; height: ${$size}px`} /> <img
on:click={() => toggleSize()}
src={new Qr($url).toImageElement($size)}
style={`width: ${$size}px; height: ${$size}px`}
/>
{/if} {/if}

View file

@ -31,7 +31,8 @@
*/ */
export let notForLabels: string[] | undefined = undefined export let notForLabels: string[] | undefined = undefined
const _notForLabels = new Set(notForLabels) const _notForLabels = new Set(notForLabels)
let showAllQuestionsAtOnce : Store<boolean>= state.userRelatedState?.showAllQuestionsAtOnce ?? new ImmutableStore(false) let showAllQuestionsAtOnce: Store<boolean> =
state.userRelatedState?.showAllQuestionsAtOnce ?? new ImmutableStore(false)
function allowed(labels: string[]) { function allowed(labels: string[]) {
if (onlyForLabels?.length > 0 && !labels.some((l) => _onlyForLabels.has(l))) { if (onlyForLabels?.length > 0 && !labels.some((l) => _onlyForLabels.has(l))) {

View file

@ -32,19 +32,18 @@
onDestroy( onDestroy(
tags.addCallbackD((tags) => { tags.addCallbackD((tags) => {
const knownNow = config.IsKnown(tags) const knownNow = config.IsKnown(tags)
if(!knownNow){ if (!knownNow) {
editMode = true editMode = true
return return
} }
if(knownNow && !knownAtTheStart) { if (knownNow && !knownAtTheStart) {
// Some other question might have set this to 'known', so we close the 'editMode' // Some other question might have set this to 'known', so we close the 'editMode'
editMode = false editMode = false
// well, not really 'known at the start', but it is known at this point in time, so it should not set 'editMode' to false automatically anymore // well, not really 'known at the start', but it is known at this point in time, so it should not set 'editMode' to false automatically anymore
knownAtTheStart = true knownAtTheStart = true
} }
})
}),
) )
} }

View file

@ -306,7 +306,8 @@
let hideMappingsUnlessSearchedFor = let hideMappingsUnlessSearchedFor =
config.mappings.length > 8 && config.mappings.some((m) => m.priorityIf !== undefined) config.mappings.length > 8 && config.mappings.some((m) => m.priorityIf !== undefined)
$: question = config.question $: question = config.question
$: hideMappingsUnlessSearchedFor = config.mappings.length > 8 && config.mappings.some((m) => m.priorityIf !== undefined) $: hideMappingsUnlessSearchedFor =
config.mappings.length > 8 && config.mappings.some((m) => m.priorityIf !== undefined)
if (state?.osmConnection) { if (state?.osmConnection) {
onDestroy( onDestroy(
@ -362,7 +363,7 @@
/> />
</div> </div>
{#if hideMappingsUnlessSearchedFor} {#if hideMappingsUnlessSearchedFor}
<div class="m-1 rounded border border-dashed border-black p-1 px-2 flex items-center"> <div class="m-1 flex items-center rounded border border-dashed border-black p-1 px-2">
<Tr t={Translations.t.general.mappingsAreHidden} /> <Tr t={Translations.t.general.mappingsAreHidden} />
</div> </div>
{/if} {/if}

View file

@ -1,8 +1,6 @@
import { RenderingSpecification, SpecialVisualization } from "./SpecialVisualization" import { RenderingSpecification, SpecialVisualization } from "./SpecialVisualization"
export default class SpecialVisualisationUtils { export default class SpecialVisualisationUtils {
/** /**
* *
* For a given string, returns a specification what parts are fixed and what parts are special renderings. * For a given string, returns a specification what parts are fixed and what parts are special renderings.
@ -27,7 +25,7 @@ export default class SpecialVisualisationUtils {
public static constructSpecification( public static constructSpecification(
template: string, template: string,
specialVisualisations: Map<string, SpecialVisualization>, specialVisualisations: Map<string, SpecialVisualization>,
extraMappings: SpecialVisualization[] = [], extraMappings: SpecialVisualization[] = []
): RenderingSpecification[] { ): RenderingSpecification[] {
if (template === "") { if (template === "") {
return [] return []
@ -36,15 +34,13 @@ export default class SpecialVisualisationUtils {
if (template["type"] !== undefined) { if (template["type"] !== undefined) {
console.trace( console.trace(
"Got a non-expanded template while constructing the specification, it still has a 'special-key':", "Got a non-expanded template while constructing the specification, it still has a 'special-key':",
template, template
) )
throw "Got a non-expanded template while constructing the specification" throw "Got a non-expanded template while constructing the specification"
} }
// Note: the '.*?' in the regex reads as 'any character, but in a non-greedy way' // Note: the '.*?' in the regex reads as 'any character, but in a non-greedy way'
const matched = template.match( const matched = template.match(new RegExp(`(.*){\([a-zA-Z_]+\)\\((.*?)\\)(:.*)?}(.*)`, "s"))
new RegExp(`(.*){\([a-zA-Z_]+\)\\((.*?)\\)(:.*)?}(.*)`, "s"),
)
if (matched === null) { if (matched === null) {
// IF we end up here, no changes have to be made - except to remove any resting {} // IF we end up here, no changes have to be made - except to remove any resting {}
return [template] return [template]
@ -52,11 +48,11 @@ export default class SpecialVisualisationUtils {
const fName = matched[2] const fName = matched[2]
let knownSpecial = specialVisualisations.get(fName) let knownSpecial = specialVisualisations.get(fName)
if(!knownSpecial && extraMappings?.length > 0){ if (!knownSpecial && extraMappings?.length > 0) {
knownSpecial = extraMappings.find(em => em.funcName === fName) knownSpecial = extraMappings.find((em) => em.funcName === fName)
} }
if(!knownSpecial){ if (!knownSpecial) {
throw "Didn't find a special visualisation: "+fName+" in "+template throw "Didn't find a special visualisation: " + fName + " in " + template
} }
// Always a boring string // Always a boring string
@ -64,13 +60,12 @@ export default class SpecialVisualisationUtils {
const argument: string = const argument: string =
matched[3] /* .trim() // We don't trim, as spaces might be relevant, e.g. "what is ... of {title()}"*/ matched[3] /* .trim() // We don't trim, as spaces might be relevant, e.g. "what is ... of {title()}"*/
const style: string = matched[4]?.substring(1) ?? "" const style: string = matched[4]?.substring(1) ?? ""
const partAfter: RenderingSpecification[] = SpecialVisualisationUtils.constructSpecification( const partAfter: RenderingSpecification[] =
matched[5], SpecialVisualisationUtils.constructSpecification(
specialVisualisations, matched[5],
extraMappings, specialVisualisations,
) extraMappings
)
const args: string[] = knownSpecial.args.map((arg) => arg.defaultValue ?? "") const args: string[] = knownSpecial.args.map((arg) => arg.defaultValue ?? "")
if (argument.length > 0) { if (argument.length > 0) {
@ -92,12 +87,10 @@ export default class SpecialVisualisationUtils {
func: knownSpecial, func: knownSpecial,
} }
partAfter.unshift(element) partAfter.unshift(element)
if(partBefore.length > 0){ if (partBefore.length > 0) {
partAfter.unshift(partBefore) partAfter.unshift(partBefore)
} }
return partAfter return partAfter
} }
private static undoEncoding(str: string) { private static undoEncoding(str: string) {

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import Translations from "../i18n/Translations" import Translations from "../i18n/Translations"
import type { ConfigMeta } from "./configMeta" import type { ConfigMeta } from "./configMeta"
import Icon from "../Map/Icon.svelte" import Icon from "../Map/Icon.svelte"
@ -11,9 +10,7 @@
import QuestionPreview from "./QuestionPreview.svelte" import QuestionPreview from "./QuestionPreview.svelte"
import SchemaBasedMultiType from "./SchemaBasedMultiType.svelte" import SchemaBasedMultiType from "./SchemaBasedMultiType.svelte"
import { EditJsonState } from "./EditLayerState" import { EditJsonState } from "./EditLayerState"
import type { import type { QuestionableTagRenderingConfigJson } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
QuestionableTagRenderingConfigJson,
} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
import { AccordionItem } from "flowbite-svelte" import { AccordionItem } from "flowbite-svelte"
export let state: EditJsonState<any> export let state: EditJsonState<any>
@ -86,10 +83,10 @@
} catch (e) { } catch (e) {
console.log( console.log(
"Warning: could not translate a title for " + "Warning: could not translate a title for " +
`${singular} ${i} with function ` + `${singular} ${i} with function ` +
schema.hints.title + schema.hints.title +
" and value " + " and value " +
JSON.stringify(value), JSON.stringify(value)
) )
} }
return Translations.T(`${singular} ${i}`) return Translations.T(`${singular} ${i}`)
@ -111,11 +108,10 @@
} }
</script> </script>
<AccordionItem open={$expanded} paddingDefault="p-0" inactiveClass="text-black m-0">
<AccordionItem open={$expanded} paddingDefault="p-0" inactiveClass="text-black m-0" > <div slot="header" class="m-0 w-full p-1 text-base text-black">
<div slot="header" class="p-1 text-base w-full m-0 text-black">
{#if !isTagRenderingBlock} {#if !isTagRenderingBlock}
<div class="flex items-center justify-between w-full"> <div class="flex w-full items-center justify-between">
<div class="m-0 flex"> <div class="m-0 flex">
{#if schema.hints.icon} {#if schema.hints.icon}
<Icon clss="w-6 h-6" icon={genIcon(value)} color={genColor(value)} /> <Icon clss="w-6 h-6" icon={genIcon(value)} color={genColor(value)} />
@ -134,30 +130,30 @@
<button <button
class="h-fit w-fit rounded-full border border-black p-1" class="h-fit w-fit rounded-full border border-black p-1"
on:click={() => { on:click={() => {
del(i) del(i)
}} }}
> >
<TrashIcon class="h-4 w-4" /> <TrashIcon class="h-4 w-4" />
</button> </button>
</div> </div>
{:else if typeof value === "string"} {:else if typeof value === "string"}
Builtin: <b>{value}</b> Builtin: <b>{value}</b>
{:else if value["builtin"]} {:else if value["builtin"]}
reused tagrendering <span class="font-bold">{JSON.stringify(value["builtin"])}</span> reused tagrendering <span class="font-bold">{JSON.stringify(value["builtin"])}</span>
{:else} {:else}
<Tr cls="font-bold" t={Translations.T(value?.question ?? value?.render)} /> <Tr cls="font-bold" t={Translations.T(value?.question ?? value?.render)} />
{/if} {/if}
</div> </div>
<div class="normal-background p-2 border border-gray-300"> <div class="normal-background border border-gray-300 p-2">
{#if usesOverride} {#if usesOverride}
This block uses an builtin/override construction and cannot be edited in Studio. This block uses an builtin/override construction and cannot be edited in Studio. Edit the code
Edit the code directly directly
{:else if isTagRenderingBlock} {:else if isTagRenderingBlock}
<QuestionPreview {state} {path} {schema}> <QuestionPreview {state} {path} {schema}>
<button <button
on:click={() => { on:click={() => {
del(i) del(i)
}} }}
> >
<TrashIcon class="h-4 w-4" /> <TrashIcon class="h-4 w-4" />
Delete this question Delete this question
@ -166,16 +162,16 @@
{#if i > 0} {#if i > 0}
<button <button
on:click={() => { on:click={() => {
moveTo(i, 0) moveTo(i, 0)
}} }}
> >
Move to front Move to front
</button> </button>
<button <button
on:click={() => { on:click={() => {
swap(i, i - 1) swap(i, i - 1)
}} }}
> >
Move up Move up
</button> </button>
@ -183,29 +179,25 @@
{#if i + 1 < $currentValue.length} {#if i + 1 < $currentValue.length}
<button <button
on:click={() => { on:click={() => {
swap(i, i + 1) swap(i, i + 1)
}} }}
> >
Move down Move down
</button> </button>
<button <button
on:click={() => { on:click={() => {
moveTo(i, $currentValue.length - 1) moveTo(i, $currentValue.length - 1)
}} }}
> >
Move to back Move to back
</button> </button>
{/if} {/if}
</QuestionPreview> </QuestionPreview>
{:else if schema.hints.types} {:else if schema.hints.types}
<SchemaBasedMultiType {state} path={[...path,i]} schema={schemaForMultitype()} /> <SchemaBasedMultiType {state} path={[...path, i]} schema={schemaForMultitype()} />
{:else} {:else}
{#each subparts as subpart} {#each subparts as subpart}
<SchemaBasedInput <SchemaBasedInput {state} path={fusePath(subpart.path)} schema={subpart} />
{state}
path={fusePath(subpart.path)}
schema={subpart}
/>
{/each} {/each}
{/if} {/if}
</div> </div>

View file

@ -23,10 +23,9 @@
<div class="flex flex-col"> <div class="flex flex-col">
<div> <div>
Deleting this layer will delete your version. If you clicked a layer made by someone else, their version will Deleting this layer will delete your version. If you clicked a layer made by someone else,
remain. their version will remain. If you ever accidentally delete a layer, contact Pietervdvn. He
might have a backup
If you ever accidentally delete a layer, contact Pietervdvn. He might have a backup
</div> </div>
<NextButton clss="primary" on:click={() => deleteLayer()}> <NextButton clss="primary" on:click={() => deleteLayer()}>
@ -35,8 +34,5 @@
Do delete this {objectType} Do delete this {objectType}
</div> </div>
</NextButton> </NextButton>
</div> </div>
</AccordionSingle> </AccordionSingle>

View file

@ -82,7 +82,7 @@
let highlightedItem: UIEventSource<HighlightedTagRendering> = state.highlightedItem let highlightedItem: UIEventSource<HighlightedTagRendering> = state.highlightedItem
</script> </script>
<div class="flex h-screen flex-col link-underline"> <div class="link-underline flex h-screen flex-col">
<div class="my-2 flex w-full flex-wrap justify-between"> <div class="my-2 flex w-full flex-wrap justify-between">
<slot /> <slot />
{#if $title === undefined} {#if $title === undefined}

View file

@ -54,7 +54,7 @@ export abstract class EditJsonState<T> {
* The EditLayerUI shows a 'schemaBasedInput' for this path to pop advanced questions out * The EditLayerUI shows a 'schemaBasedInput' for this path to pop advanced questions out
*/ */
public readonly highlightedItem: UIEventSource<HighlightedTagRendering> = new UIEventSource( public readonly highlightedItem: UIEventSource<HighlightedTagRendering> = new UIEventSource(
undefined, undefined
) )
private sendingUpdates = false private sendingUpdates = false
private readonly _stores = new Map<string, UIEventSource<any>>() private readonly _stores = new Map<string, UIEventSource<any>>()
@ -66,7 +66,7 @@ export abstract class EditJsonState<T> {
osmConnection: OsmConnection, osmConnection: OsmConnection,
options?: { options?: {
expertMode?: UIEventSource<boolean> expertMode?: UIEventSource<boolean>
}, }
) { ) {
this.osmConnection = osmConnection this.osmConnection = osmConnection
this.schema = schema this.schema = schema
@ -93,14 +93,20 @@ export abstract class EditJsonState<T> {
await this.server.update(id, config, this.category) await this.server.update(id, config, this.category)
}) })
this.messages = this.createMessagesStore() this.messages = this.createMessagesStore()
} }
public startSavingUpdates(enabled = true) { public startSavingUpdates(enabled = true) {
this.sendingUpdates = enabled this.sendingUpdates = enabled
this.register(["credits"], this.osmConnection.userDetails.mapD(u => u.name), false) this.register(
this.register(["credits:uid"], this.osmConnection.userDetails.mapD(u => u.uid), false) ["credits"],
this.osmConnection.userDetails.mapD((u) => u.name),
false
)
this.register(
["credits:uid"],
this.osmConnection.userDetails.mapD((u) => u.uid),
false
)
if (enabled) { if (enabled) {
this.configuration.ping() this.configuration.ping()
} }
@ -141,7 +147,7 @@ export abstract class EditJsonState<T> {
public register( public register(
path: ReadonlyArray<string | number>, path: ReadonlyArray<string | number>,
value: Store<any>, value: Store<any>,
noInitialSync: boolean = true, noInitialSync: boolean = true
): () => void { ): () => void {
const unsync = value.addCallback((v) => { const unsync = value.addCallback((v) => {
this.setValueAt(path, v) this.setValueAt(path, v)
@ -155,7 +161,7 @@ export abstract class EditJsonState<T> {
public getSchemaStartingWith(path: string[]) { public getSchemaStartingWith(path: string[]) {
return this.schema.filter( return this.schema.filter(
(sch) => (sch) =>
!path.some((part, i) => !(sch.path.length > path.length && sch.path[i] === part)), !path.some((part, i) => !(sch.path.length > path.length && sch.path[i] === part))
) )
} }
@ -173,11 +179,11 @@ export abstract class EditJsonState<T> {
} }
public getSchema(path: (string | number)[]): ConfigMeta[] { public getSchema(path: (string | number)[]): ConfigMeta[] {
path = path.filter(p => typeof p === "string") path = path.filter((p) => typeof p === "string")
const schemas = this.schema.filter( const schemas = this.schema.filter(
(sch) => (sch) =>
sch !== undefined && sch !== undefined &&
!path.some((part, i) => !(sch.path.length == path.length && sch.path[i] === part)), !path.some((part, i) => !(sch.path.length == path.length && sch.path[i] === part))
) )
if (schemas.length == 0) { if (schemas.length == 0) {
console.warn("No schemas found for path", path.join(".")) console.warn("No schemas found for path", path.join("."))
@ -267,12 +273,12 @@ class ContextRewritingStep<T> extends Conversion<LayerConfigJson, T> {
constructor( constructor(
state: DesugaringContext, state: DesugaringContext,
step: Conversion<LayerConfigJson, T>, step: Conversion<LayerConfigJson, T>,
getTagRenderings: (t: T) => TagRenderingConfigJson[], getTagRenderings: (t: T) => TagRenderingConfigJson[]
) { ) {
super( super(
"When validating a layer, the tagRenderings are first expanded. Some builtin tagRendering-calls (e.g. `contact`) will introduce _multiple_ tagRenderings, causing the count to be off. This class rewrites the error messages to fix this", "When validating a layer, the tagRenderings are first expanded. Some builtin tagRendering-calls (e.g. `contact`) will introduce _multiple_ tagRenderings, causing the count to be off. This class rewrites the error messages to fix this",
[], [],
"ContextRewritingStep", "ContextRewritingStep"
) )
this._state = state this._state = state
this._step = step this._step = step
@ -282,7 +288,7 @@ class ContextRewritingStep<T> extends Conversion<LayerConfigJson, T> {
convert(json: LayerConfigJson, context: ConversionContext): T { convert(json: LayerConfigJson, context: ConversionContext): T {
const converted = this._step.convert(json, context) const converted = this._step.convert(json, context)
const originalIds = json.tagRenderings?.map( const originalIds = json.tagRenderings?.map(
(tr) => (<QuestionableTagRenderingConfigJson>tr)["id"], (tr) => (<QuestionableTagRenderingConfigJson>tr)["id"]
) )
if (!originalIds) { if (!originalIds) {
return converted return converted
@ -344,7 +350,7 @@ export default class EditLayerState extends EditJsonState<LayerConfigJson> {
schema: ConfigMeta[], schema: ConfigMeta[],
server: StudioServer, server: StudioServer,
osmConnection: OsmConnection, osmConnection: OsmConnection,
options: { expertMode: UIEventSource<boolean> }, options: { expertMode: UIEventSource<boolean> }
) { ) {
super(schema, server, "layers", osmConnection, options) super(schema, server, "layers", osmConnection, options)
this.layout = { this.layout = {
@ -401,7 +407,7 @@ export default class EditLayerState extends EditJsonState<LayerConfigJson> {
return new ContextRewritingStep( return new ContextRewritingStep(
state, state,
new Pipe(new PrepareLayer(state), new ValidateLayer("dynamic", false, undefined, true)), new Pipe(new PrepareLayer(state), new ValidateLayer("dynamic", false, undefined, true)),
(t) => <TagRenderingConfigJson[]>t.raw.tagRenderings, (t) => <TagRenderingConfigJson[]>t.raw.tagRenderings
) )
} }
@ -435,7 +441,7 @@ export default class EditLayerState extends EditJsonState<LayerConfigJson> {
} }
protected async validate( protected async validate(
configuration: Partial<LayerConfigJson>, configuration: Partial<LayerConfigJson>
): Promise<ConversionMessage[]> { ): Promise<ConversionMessage[]> {
const layers = AllSharedLayers.getSharedLayersConfigs() const layers = AllSharedLayers.getSharedLayersConfigs()
@ -465,18 +471,20 @@ export class EditThemeState extends EditJsonState<LayoutConfigJson> {
schema: ConfigMeta[], schema: ConfigMeta[],
server: StudioServer, server: StudioServer,
osmConnection: OsmConnection, osmConnection: OsmConnection,
options: { expertMode: UIEventSource<boolean> }, options: { expertMode: UIEventSource<boolean> }
) { ) {
super(schema, server, "themes", osmConnection, options) super(schema, server, "themes", osmConnection, options)
this.setupFixers() this.setupFixers()
} }
protected buildValidation(state: DesugaringContext): Conversion<LayoutConfigJson, any> { protected buildValidation(state: DesugaringContext): Conversion<LayoutConfigJson, any> {
return new Pipe(new PrevalidateTheme(), return new Pipe(
new PrevalidateTheme(),
new Pipe( new Pipe(
new PrepareTheme(state), new PrepareTheme(state),
new ValidateTheme(undefined, "", false, new Set(state.tagRenderings.keys())), new ValidateTheme(undefined, "", false, new Set(state.tagRenderings.keys()))
), true, ),
true
) )
} }

View file

@ -5,9 +5,7 @@
import { ImmutableStore, Store } from "../../Logic/UIEventSource" import { ImmutableStore, Store } from "../../Logic/UIEventSource"
import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte" import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte"
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig" import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
import type { import type { QuestionableTagRenderingConfigJson } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.js"
QuestionableTagRenderingConfigJson,
} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.js"
import type { TagRenderingConfigJson } from "../../Models/ThemeConfig/Json/TagRenderingConfigJson" import type { TagRenderingConfigJson } from "../../Models/ThemeConfig/Json/TagRenderingConfigJson"
import FromHtml from "../Base/FromHtml.svelte" import FromHtml from "../Base/FromHtml.svelte"
import ShowConversionMessage from "./ShowConversionMessage.svelte" import ShowConversionMessage from "./ShowConversionMessage.svelte"
@ -44,11 +42,12 @@
if (config["builtin"]) { if (config["builtin"]) {
let override = "" let override = ""
if (config["override"]) { if (config["override"]) {
override = ". Some items are changed with an override. Editing this is not yet supported with Studio." override =
". Some items are changed with an override. Editing this is not yet supported with Studio."
} }
return new TagRenderingConfig({ return new TagRenderingConfig({
render: { render: {
"en": "This question reuses <b>" + JSON.stringify(config["builtin"]) + "</b>" + override, en: "This question reuses <b>" + JSON.stringify(config["builtin"]) + "</b>" + override,
}, },
}) })
} }
@ -69,10 +68,10 @@
<div class="flex"> <div class="flex">
<div class="m-4 flex w-full flex-col"> <div class="m-4 flex w-full flex-col">
{#if $configJson.some(config => config["builtin"] !== undefined)} {#if $configJson.some((config) => config["builtin"] !== undefined)}
<div class="interactive p-2 rounded-2xl"> <div class="interactive rounded-2xl p-2">
This question uses an advanced 'builtin'+'override' construction in the source code. This question uses an advanced 'builtin'+'override' construction in the source code. Editing
Editing this with Studio is not supported. this with Studio is not supported.
</div> </div>
{:else} {:else}
<NextButton clss="primary" on:click={() => state.highlightedItem.setData({ path, schema })}> <NextButton clss="primary" on:click={() => state.highlightedItem.setData({ path, schema })}>

View file

@ -9,14 +9,18 @@
export let state: EditLayerState | EditThemeState export let state: EditLayerState | EditThemeState
let rawConfig = state.configuration.sync(f => JSON.stringify(f, null, " "), [], json => { let rawConfig = state.configuration.sync(
try { (f) => JSON.stringify(f, null, " "),
return JSON.parse(json) [],
} catch (e) { (json) => {
console.error("Could not parse", json) try {
return undefined return JSON.parse(json)
} catch (e) {
console.error("Could not parse", json)
return undefined
}
} }
}) )
let container: HTMLDivElement let container: HTMLDivElement
let monaco: typeof Monaco let monaco: typeof Monaco
@ -88,7 +92,7 @@
model = monaco?.editor?.createModel( model = monaco?.editor?.createModel(
JSON.stringify(state.configuration.data, null, " "), JSON.stringify(state.configuration.data, null, " "),
"json", "json",
modelUri, modelUri
) )
} catch (e) { } catch (e) {
console.error("Could not create model in MOnaco Editor", e) console.error("Could not create model in MOnaco Editor", e)
@ -126,7 +130,7 @@
{:else} {:else}
<div bind:this={container} class="h-full w-full"> <div bind:this={container} class="h-full w-full">
{#if !isLoaded} {#if !isLoaded}
<div class="h-full w-full flex items-center align-center"> <div class="align-center flex h-full w-full items-center">
<Loading /> <Loading />
</div> </div>
{/if} {/if}

Some files were not shown because too many files have changed in this diff Show more