forked from MapComplete/MapComplete
		
	Chore: formatting
This commit is contained in:
		
							parent
							
								
									6ab0d45776
								
							
						
					
					
						commit
						ae89be6f01
					
				
					 97 changed files with 3350 additions and 2136 deletions
				
			
		| 
						 | 
					@ -55,7 +55,9 @@
 | 
				
			||||||
    + [minimap](#minimap)
 | 
					    + [minimap](#minimap)
 | 
				
			||||||
    + [mastodon](#mastodon)
 | 
					    + [mastodon](#mastodon)
 | 
				
			||||||
    + [contact](#contact)
 | 
					    + [contact](#contact)
 | 
				
			||||||
 | 
					    + [etymology.wikipedia-etymology](#etymologywikipedia-etymology)
 | 
				
			||||||
    + [denominations-notes](#denominations-notes)
 | 
					    + [denominations-notes](#denominations-notes)
 | 
				
			||||||
 | 
					    + [single_level](#single_level)
 | 
				
			||||||
    + [survey_date](#survey_date)
 | 
					    + [survey_date](#survey_date)
 | 
				
			||||||
    + [id_presets.shop_types](#id_presetsshop_types)
 | 
					    + [id_presets.shop_types](#id_presetsshop_types)
 | 
				
			||||||
    + [school.capacity](#schoolcapacity)
 | 
					    + [school.capacity](#schoolcapacity)
 | 
				
			||||||
| 
						 | 
					@ -442,9 +444,9 @@
 | 
				
			||||||
  - fitness_centre
 | 
					  - fitness_centre
 | 
				
			||||||
  - food
 | 
					  - food
 | 
				
			||||||
  - hackerspace
 | 
					  - hackerspace
 | 
				
			||||||
 | 
					  - indoors
 | 
				
			||||||
  - parking
 | 
					  - parking
 | 
				
			||||||
  - picnic_table
 | 
					  - picnic_table
 | 
				
			||||||
  - questions
 | 
					 | 
				
			||||||
  - railway_platforms
 | 
					  - railway_platforms
 | 
				
			||||||
  - reception_desk
 | 
					  - reception_desk
 | 
				
			||||||
  - shops
 | 
					  - shops
 | 
				
			||||||
| 
						 | 
					@ -858,6 +860,17 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### etymology.wikipedia-etymology 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - indoors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### denominations-notes 
 | 
					### denominations-notes 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -871,6 +884,17 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - questions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### survey_date 
 | 
					### survey_date 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,9 +61,6 @@
 | 
				
			||||||
    + [just_created](#just_created)
 | 
					    + [just_created](#just_created)
 | 
				
			||||||
    + [leftover-questions](#leftover-questions)
 | 
					    + [leftover-questions](#leftover-questions)
 | 
				
			||||||
    + [all-tags](#all-tags)
 | 
					    + [all-tags](#all-tags)
 | 
				
			||||||
1. [matchpoint](#matchpoint)
 | 
					 | 
				
			||||||
  - [Basic tags for this layer](#basic-tags-for-this-layer)
 | 
					 | 
				
			||||||
  - [Supported attributes](#supported-attributes)
 | 
					 | 
				
			||||||
1. [import_candidate](#import_candidate)
 | 
					1. [import_candidate](#import_candidate)
 | 
				
			||||||
  - [Basic tags for this layer](#basic-tags-for-this-layer)
 | 
					  - [Basic tags for this layer](#basic-tags-for-this-layer)
 | 
				
			||||||
  - [Supported attributes](#supported-attributes)
 | 
					  - [Supported attributes](#supported-attributes)
 | 
				
			||||||
| 
						 | 
					@ -79,9 +76,13 @@
 | 
				
			||||||
    + [inbox](#inbox)
 | 
					    + [inbox](#inbox)
 | 
				
			||||||
    + [settings-link](#settings-link)
 | 
					    + [settings-link](#settings-link)
 | 
				
			||||||
    + [logout](#logout)
 | 
					    + [logout](#logout)
 | 
				
			||||||
 | 
					    + [background-layer-readonly](#background-layer-readonly)
 | 
				
			||||||
 | 
					    + [background-layer](#background-layer)
 | 
				
			||||||
    + [picture-license](#picture-license)
 | 
					    + [picture-license](#picture-license)
 | 
				
			||||||
    + [show_tags](#show_tags)
 | 
					    + [show_tags](#show_tags)
 | 
				
			||||||
    + [all-questions-at-once](#all-questions-at-once)
 | 
					    + [all-questions-at-once](#all-questions-at-once)
 | 
				
			||||||
 | 
					    + [fixate-north](#fixate-north)
 | 
				
			||||||
 | 
					    + [mangrove-keys](#mangrove-keys)
 | 
				
			||||||
    + [translations-title](#translations-title)
 | 
					    + [translations-title](#translations-title)
 | 
				
			||||||
    + [translation-mode](#translation-mode)
 | 
					    + [translation-mode](#translation-mode)
 | 
				
			||||||
    + [translation-help](#translation-help)
 | 
					    + [translation-help](#translation-help)
 | 
				
			||||||
| 
						 | 
					@ -120,7 +121,6 @@ MapComplete has a few data layers available in the theme which have special prop
 | 
				
			||||||
  - [split_point](#split_point)
 | 
					  - [split_point](#split_point)
 | 
				
			||||||
  - [split_road](#split_road)
 | 
					  - [split_road](#split_road)
 | 
				
			||||||
  - [current_view](#current_view)
 | 
					  - [current_view](#current_view)
 | 
				
			||||||
  - [matchpoint](#matchpoint)
 | 
					 | 
				
			||||||
  - [import_candidate](#import_candidate)
 | 
					  - [import_candidate](#import_candidate)
 | 
				
			||||||
  - [usersettings](#usersettings)
 | 
					  - [usersettings](#usersettings)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -476,7 +476,9 @@ Meta-layer, simply showing a bbox in red
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - This layer is shown at zoomlevel **0** and higher
 | 
					  - This layer is shown at zoomlevel **0** and higher
 | 
				
			||||||
  - **This layer is included automatically in every theme. This layer might contain no points**
 | 
					  - **This layer is included automatically in every theme. This layer might contain no points**
 | 
				
			||||||
 | 
					  - This layer is not visible by default and must be enabled in the filter by the user. 
 | 
				
			||||||
  - Elements don't have a title set and cannot be toggled nor will they show up in the dashboard. If you import this layer in your theme, override `title` to make this toggleable.
 | 
					  - Elements don't have a title set and cannot be toggled nor will they show up in the dashboard. If you import this layer in your theme, override `title` to make this toggleable.
 | 
				
			||||||
 | 
					  - This layer is not visible by default and the visibility cannot be toggled, effectively resulting in a fully hidden layer. This can be useful, e.g. to calculate some metatags. If you want to render this layer (e.g. for debugging), enable it by setting the URL-parameter layer-<id>=true
 | 
				
			||||||
  - Not visible in the layer selection by default. If you want to make this layer toggable, override `name`
 | 
					  - Not visible in the layer selection by default. If you want to make this layer toggable, override `name`
 | 
				
			||||||
  - Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings`
 | 
					  - Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -863,47 +865,6 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 matchpoint 
 | 
					 | 
				
			||||||
============
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<img src='https://mapcomplete.org/./assets/svg/crosshair-empty.svg' height="100px"> 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The default rendering for a locationInput which snaps onto another object
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  - This layer is shown at zoomlevel **0** and higher
 | 
					 | 
				
			||||||
  - This layer can **not** be included in a theme. It is solely used by [special renderings](SpecialRenderings.md) showing a minimap with custom data.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 Basic tags for this layer 
 | 
					 | 
				
			||||||
---------------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Elements must have the all of following tags to be shown on this layer:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 Supported attributes 
 | 
					 | 
				
			||||||
----------------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 import_candidate 
 | 
					 import_candidate 
 | 
				
			||||||
==================
 | 
					==================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1043,9 +1004,12 @@ this quick overview is incomplete
 | 
				
			||||||
attribute | type | values which are supported by this layer
 | 
					attribute | type | values which are supported by this layer
 | 
				
			||||||
----------- | ------ | ------------------------------------------
 | 
					----------- | ------ | ------------------------------------------
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/__url_parameter_initialized:language#values) [__url_parameter_initialized:language](https://wiki.openstreetmap.org/wiki/Key:__url_parameter_initialized:language) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:__url_parameter_initialized:language%3Dyes)
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-preferred-background-layer#values) [mapcomplete-preferred-background-layer](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-preferred-background-layer) | Multiple choice | [](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-preferred-background-layer%3D) [osm](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-preferred-background-layer%3Dosm) [photo](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-preferred-background-layer%3Dphoto) [map](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-preferred-background-layer%3Dmap) [](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-preferred-background-layer%3D)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-pictures-license#values) [mapcomplete-pictures-license](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-pictures-license) | Multiple choice | [CC0](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-pictures-license%3DCC0) [CC-BY 4.0](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-pictures-license%3DCC-BY 4.0) [CC-BY-SA 4.0](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-pictures-license%3DCC-BY-SA 4.0)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-pictures-license#values) [mapcomplete-pictures-license](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-pictures-license) | Multiple choice | [CC0](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-pictures-license%3DCC0) [CC-BY 4.0](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-pictures-license%3DCC-BY 4.0) [CC-BY-SA 4.0](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-pictures-license%3DCC-BY-SA 4.0)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-show_tags#values) [mapcomplete-show_tags](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-show_tags) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_tags%3Dno) [](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_tags%3D) [yes](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_tags%3Dyes) [full](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_tags%3Dfull)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-show_tags#values) [mapcomplete-show_tags](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-show_tags) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_tags%3Dno) [](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_tags%3D) [yes](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_tags%3Dyes) [full](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_tags%3Dfull)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-show-all-questions#values) [mapcomplete-show-all-questions](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-show-all-questions) | Multiple choice | [true](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show-all-questions%3Dtrue) [false](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show-all-questions%3Dfalse)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-show-all-questions#values) [mapcomplete-show-all-questions](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-show-all-questions) | Multiple choice | [true](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show-all-questions%3Dtrue) [false](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show-all-questions%3Dfalse)
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-fixate-north#values) [mapcomplete-fixate-north](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-fixate-north) | Multiple choice | [](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-fixate-north%3D) [yes](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-fixate-north%3Dyes)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-translation-mode#values) [mapcomplete-translation-mode](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-translation-mode) | Multiple choice | [false](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-translation-mode%3Dfalse) [true](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-translation-mode%3Dtrue) [mobile](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-translation-mode%3Dmobile)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-translation-mode#values) [mapcomplete-translation-mode](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-translation-mode) | Multiple choice | [false](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-translation-mode%3Dfalse) [true](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-translation-mode%3Dtrue) [mobile](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-translation-mode%3Dmobile)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-translation-mode#values) [mapcomplete-translation-mode](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-translation-mode) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-translation-mode%3Dyes)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/mapcomplete-translation-mode#values) [mapcomplete-translation-mode](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-translation-mode) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-translation-mode%3Dyes)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/_translation_percentage#values) [_translation_percentage](https://wiki.openstreetmap.org/wiki/Key:_translation_percentage) | Multiple choice | [100](https://wiki.openstreetmap.org/wiki/Tag:_translation_percentage%3D100)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/_translation_percentage#values) [_translation_percentage](https://wiki.openstreetmap.org/wiki/Key:_translation_percentage) | Multiple choice | [100](https://wiki.openstreetmap.org/wiki/Tag:_translation_percentage%3D100)
 | 
				
			||||||
| 
						 | 
					@ -1093,6 +1057,11 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - *The language was set via an URL-parameter and cannot be set by the user.²*  corresponds with  `__url_parameter_initialized:language=yes`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### inbox 
 | 
					### inbox 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1103,8 +1072,8 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - *{link(Open your inbox,&LBRACE_backend&RBRACE/messages/inbox,)}*  corresponds with  `_unreadMessages=0`
 | 
					  - *{link(Open your inbox,&LBRACE_backend&RBRACE/messages/inbox,,)}*  corresponds with  `_unreadMessages=0`
 | 
				
			||||||
  - *{link(<b class='alert'>You have &LBRACE_unreadMessages&RBRACE</b><br/>Open your inbox,&LBRACE_backend&RBRACE/messages/inbox,)}*  corresponds with  `_unreadMessages>0`
 | 
					  - *{link(<b class='alert'>You have &LBRACE_unreadMessages&RBRACE</b><br/>Open your inbox,&LBRACE_backend&RBRACE/messages/inbox,,)}*  corresponds with  `_unreadMessages>0`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1129,6 +1098,39 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### background-layer-readonly 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `_theme:backgroundLayer~.+&mapcomplete-preferred-background-layer~.+&_theme:backgroundLayer!=`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### background-layer 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *What background layer should be shown by default?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - *Use the default background layer*  corresponds with  ``
 | 
				
			||||||
 | 
					  - *Use OpenStreetMap-carto as default layer*  corresponds with  `mapcomplete-preferred-background-layer=osm`
 | 
				
			||||||
 | 
					  - *Use aerial imagery as default background*  corresponds with  `mapcomplete-preferred-background-layer=photo`
 | 
				
			||||||
 | 
					  - *Use a non-openstreetmap based map as default background*  corresponds with  `mapcomplete-preferred-background-layer=map`
 | 
				
			||||||
 | 
					  - *Use the current background layer (<span class='code'>{__current_background}</span>) as default background*  corresponds with  `mapcomplete-preferred-background-layer=`
 | 
				
			||||||
 | 
					  - *Use background layer <span class='code'>{mapcomplete-preferred-background-layer}</span> as default background*  corresponds with  `mapcomplete-preferred-background-layer~.+`
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### picture-license 
 | 
					### picture-license 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1184,6 +1186,32 @@ The question is  *Should questions for unknown data fields appear one-by-one or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### fixate-north 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *Should north always be up?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - *Allow to rotate the map*  corresponds with  ``
 | 
				
			||||||
 | 
					  - *Always keep north pointing up*  corresponds with  `mapcomplete-fixate-north=yes`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### mangrove-keys 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### translations-title 
 | 
					### translations-title 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1265,8 +1293,8 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - *A link to your Mastodon-profile has been been found: <a href='{_mastodon_link}' target='_blank'>{_mastodon_link}</a>*  corresponds with  `_mastodon_link~.+`
 | 
					  - *A link to your Mastodon-profile has been been found: <a href='{_mastodon_link}' target='_blank' rel='noopener'>{_mastodon_link}</a>*  corresponds with  `_mastodon_link~.+`
 | 
				
			||||||
  - *We found a link to what looks to be a mastodon account, but it is unverified. <a href='https://www.openstreetmap.org/profile/edit' target='_blank'>Edit your profile description</a> and place the following there: <span class='code'><a href="{_mastodon_candidate}" rel="me">Mastodon</a>*  corresponds with  `_mastodon_candidate~.+`
 | 
					  - *We found a link to what looks to be a mastodon account, but it is unverified. <a href='https://www.openstreetmap.org/profile/edit' target='_blank' rel='noopener'>Edit your profile description</a> and place the following there: <span class='code'><a href="{_mastodon_candidate}" rel="me">Mastodon</a>*  corresponds with  `_mastodon_candidate~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1408,6 +1436,7 @@ The following layers are included in MapComplete:
 | 
				
			||||||
  - [dogpark](./Layers/dogpark.md)
 | 
					  - [dogpark](./Layers/dogpark.md)
 | 
				
			||||||
  - [drinking_water](./Layers/drinking_water.md)
 | 
					  - [drinking_water](./Layers/drinking_water.md)
 | 
				
			||||||
  - [elevator](./Layers/elevator.md)
 | 
					  - [elevator](./Layers/elevator.md)
 | 
				
			||||||
 | 
					  - [elongated_coin](./Layers/elongated_coin.md)
 | 
				
			||||||
  - [entrance](./Layers/entrance.md)
 | 
					  - [entrance](./Layers/entrance.md)
 | 
				
			||||||
  - [etymology](./Layers/etymology.md)
 | 
					  - [etymology](./Layers/etymology.md)
 | 
				
			||||||
  - [extinguisher](./Layers/extinguisher.md)
 | 
					  - [extinguisher](./Layers/extinguisher.md)
 | 
				
			||||||
| 
						 | 
					@ -1438,8 +1467,8 @@ The following layers are included in MapComplete:
 | 
				
			||||||
  - [map](./Layers/map.md)
 | 
					  - [map](./Layers/map.md)
 | 
				
			||||||
  - [maproulette](./Layers/maproulette.md)
 | 
					  - [maproulette](./Layers/maproulette.md)
 | 
				
			||||||
  - [maproulette_challenge](./Layers/maproulette_challenge.md)
 | 
					  - [maproulette_challenge](./Layers/maproulette_challenge.md)
 | 
				
			||||||
  - [matchpoint](./Layers/matchpoint.md)
 | 
					 | 
				
			||||||
  - [maxspeed](./Layers/maxspeed.md)
 | 
					  - [maxspeed](./Layers/maxspeed.md)
 | 
				
			||||||
 | 
					  - [memorial](./Layers/memorial.md)
 | 
				
			||||||
  - [named_streets](./Layers/named_streets.md)
 | 
					  - [named_streets](./Layers/named_streets.md)
 | 
				
			||||||
  - [nature_reserve](./Layers/nature_reserve.md)
 | 
					  - [nature_reserve](./Layers/nature_reserve.md)
 | 
				
			||||||
  - [note](./Layers/note.md)
 | 
					  - [note](./Layers/note.md)
 | 
				
			||||||
| 
						 | 
					@ -1458,6 +1487,7 @@ The following layers are included in MapComplete:
 | 
				
			||||||
  - [postboxes](./Layers/postboxes.md)
 | 
					  - [postboxes](./Layers/postboxes.md)
 | 
				
			||||||
  - [postoffices](./Layers/postoffices.md)
 | 
					  - [postoffices](./Layers/postoffices.md)
 | 
				
			||||||
  - [public_bookcase](./Layers/public_bookcase.md)
 | 
					  - [public_bookcase](./Layers/public_bookcase.md)
 | 
				
			||||||
 | 
					  - [questions](./Layers/questions.md)
 | 
				
			||||||
  - [railway_platforms](./Layers/railway_platforms.md)
 | 
					  - [railway_platforms](./Layers/railway_platforms.md)
 | 
				
			||||||
  - [rainbow_crossings](./Layers/rainbow_crossings.md)
 | 
					  - [rainbow_crossings](./Layers/rainbow_crossings.md)
 | 
				
			||||||
  - [range](./Layers/range.md)
 | 
					  - [range](./Layers/range.md)
 | 
				
			||||||
| 
						 | 
					@ -1467,6 +1497,7 @@ The following layers are included in MapComplete:
 | 
				
			||||||
  - [selected_element](./Layers/selected_element.md)
 | 
					  - [selected_element](./Layers/selected_element.md)
 | 
				
			||||||
  - [shelter](./Layers/shelter.md)
 | 
					  - [shelter](./Layers/shelter.md)
 | 
				
			||||||
  - [shops](./Layers/shops.md)
 | 
					  - [shops](./Layers/shops.md)
 | 
				
			||||||
 | 
					  - [shower](./Layers/shower.md)
 | 
				
			||||||
  - [slow_roads](./Layers/slow_roads.md)
 | 
					  - [slow_roads](./Layers/slow_roads.md)
 | 
				
			||||||
  - [speed_camera](./Layers/speed_camera.md)
 | 
					  - [speed_camera](./Layers/speed_camera.md)
 | 
				
			||||||
  - [speed_display](./Layers/speed_display.md)
 | 
					  - [speed_display](./Layers/speed_display.md)
 | 
				
			||||||
| 
						 | 
					@ -1487,6 +1518,7 @@ The following layers are included in MapComplete:
 | 
				
			||||||
  - [transit_stops](./Layers/transit_stops.md)
 | 
					  - [transit_stops](./Layers/transit_stops.md)
 | 
				
			||||||
  - [tree_node](./Layers/tree_node.md)
 | 
					  - [tree_node](./Layers/tree_node.md)
 | 
				
			||||||
  - [usersettings](./Layers/usersettings.md)
 | 
					  - [usersettings](./Layers/usersettings.md)
 | 
				
			||||||
 | 
					  - [vending_machine](./Layers/vending_machine.md)
 | 
				
			||||||
  - [veterinary](./Layers/veterinary.md)
 | 
					  - [veterinary](./Layers/veterinary.md)
 | 
				
			||||||
  - [viewpoint](./Layers/viewpoint.md)
 | 
					  - [viewpoint](./Layers/viewpoint.md)
 | 
				
			||||||
  - [village_green](./Layers/village_green.md)
 | 
					  - [village_green](./Layers/village_green.md)
 | 
				
			||||||
| 
						 | 
					@ -1497,4 +1529,4 @@ The following layers are included in MapComplete:
 | 
				
			||||||
  - [windturbine](./Layers/windturbine.md)
 | 
					  - [windturbine](./Layers/windturbine.md)
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This document is autogenerated from [Customizations/AllKnownLayouts.ts](https://github.com/pietervdvn/MapComplete/blob/develop/Customizations/AllKnownLayouts.ts)
 | 
					This document is autogenerated from [src/Customizations/AllKnownLayouts.ts](https://github.com/pietervdvn/MapComplete/blob/develop/src/Customizations/AllKnownLayouts.ts)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,8 @@ Special library layer which does not need a '.questions'-prefix before being imp
 | 
				
			||||||
    + [all_tags](#all_tags)
 | 
					    + [all_tags](#all_tags)
 | 
				
			||||||
    + [just_created](#just_created)
 | 
					    + [just_created](#just_created)
 | 
				
			||||||
    + [multilevels](#multilevels)
 | 
					    + [multilevels](#multilevels)
 | 
				
			||||||
    + [level](#level)
 | 
					    + [repeated](#repeated)
 | 
				
			||||||
 | 
					    + [single_level](#single_level)
 | 
				
			||||||
    + [smoking](#smoking)
 | 
					    + [smoking](#smoking)
 | 
				
			||||||
    + [induction-loop](#induction-loop)
 | 
					    + [induction-loop](#induction-loop)
 | 
				
			||||||
    + [internet](#internet)
 | 
					    + [internet](#internet)
 | 
				
			||||||
| 
						 | 
					@ -655,7 +656,21 @@ This is rendered with  `This elevator goes to floors {level}`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -678,6 +693,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### smoking 
 | 
					### smoking 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,7 +198,7 @@ Adds the geometry type as property. This is identical to the GoeJson geometry ty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Extract the 'level'-tag into a normalized, ';'-separated value
 | 
					Extract the 'level'-tag into a normalized, ';'-separated value called '_level' (which also includes 'repeat_on'). The `level` tag (without underscore) will be normalized with only the value of `level`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -260,7 +260,9 @@ To enable this feature,  add a field `calculatedTags` in the layer object, e.g.:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
"calculatedTags": [
 | 
					"calculatedTags": [
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    "_someKey=javascript-expression",
 | 
					    "_someKey=javascript-expression (lazy execution)",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "_some_other_key:=javascript expression (strict execution)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    "name=feat.properties.name ?? feat.properties.ref ?? feat.properties.operator",
 | 
					    "name=feat.properties.name ?? feat.properties.ref ?? feat.properties.operator",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -272,6 +274,12 @@ To enable this feature,  add a field `calculatedTags` in the layer object, e.g.:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By using `:=` as separator, the attribute will be calculated as soone as the data is loaded (strict evaluation)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The default behaviour, using `=` as separator, is lazy loading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The above code will be executed for every feature in the layer. The feature is accessible as `feat` and is an amended geojson object:
 | 
					The above code will be executed for every feature in the layer. The feature is accessible as `feat` and is an amended geojson object:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -269,7 +269,21 @@ The question is  *Is this vending machine indoors?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,6 +306,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### phone 
 | 
					### phone 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,6 @@ attribute | type | values which are supported by this layer
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/colour#values) [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)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/colour#values) [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)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/survey:date#values) [survey:date](https://wiki.openstreetmap.org/wiki/Key:survey:date) | [date](../SpecialInputElements.md#date) | [](https://wiki.openstreetmap.org/wiki/Tag:survey:date%3D)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/survey:date#values) [survey:date](https://wiki.openstreetmap.org/wiki/Key:survey:date) | [date](../SpecialInputElements.md#date) | [](https://wiki.openstreetmap.org/wiki/Tag:survey:date%3D)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/inscription#values) [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [text](../SpecialInputElements.md#text) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/inscription#values) [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [text](../SpecialInputElements.md#text) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/tourism#values) [tourism](https://wiki.openstreetmap.org/wiki/Key:tourism) | Multiple choice | [artwork](https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dartwork) [](https://wiki.openstreetmap.org/wiki/Tag:tourism%3D)
 | 
					 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/historic#values) [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)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/historic#values) [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)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/artwork_type#values) [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)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/artwork_type#values) [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)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/artist:wikidata#values) [artist:wikidata](https://wiki.openstreetmap.org/wiki/Key:artist:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/artist:wikidata#values) [artist:wikidata](https://wiki.openstreetmap.org/wiki/Key:artist:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | 
 | 
				
			||||||
| 
						 | 
					@ -263,7 +262,9 @@ The question is  *Does this bench have an artistic element?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - *This bench has an integrated artwork*  corresponds with  `tourism=artwork`
 | 
					  - *This bench has an integrated artwork*  corresponds with  `tourism=artwork`
 | 
				
			||||||
  - *This bench does not have an integrated artwork*  corresponds with  ``
 | 
					  - *This bench does not have an integrated artwork*  corresponds with  `not:tourism:artwork=yes`
 | 
				
			||||||
 | 
					  - *This bench <span class="subtle">probably</span> doesn't have an integrated artwork*  corresponds with  ``
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -254,6 +254,16 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### delete-button 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### last_edit 
 | 
					### last_edit 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -324,7 +324,21 @@ This tagrendering is only visible in the popup if the following condition is met
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -347,6 +361,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### leftover-questions 
 | 
					### leftover-questions 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,7 +97,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,6 +134,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Name 
 | 
					### Name 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1933,7 +1933,21 @@ This is rendered with  `More info on <a href='{website}'>{website}</a>`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1956,6 +1970,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### ref 
 | 
					### ref 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1931,7 +1931,21 @@ This is rendered with  `More info on <a href='{website}'>{website}</a>`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1954,6 +1968,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### ref 
 | 
					### ref 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,13 +46,13 @@ this quick overview is incomplete
 | 
				
			||||||
attribute | type | values which are supported by this layer
 | 
					attribute | type | values which are supported by this layer
 | 
				
			||||||
----------- | ------ | ------------------------------------------
 | 
					----------- | ------ | ------------------------------------------
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/level#values) [level](https://wiki.openstreetmap.org/wiki/Key:level) | [float](../SpecialInputElements.md#float) | [0](https://wiki.openstreetmap.org/wiki/Tag:level%3D0) [1](https://wiki.openstreetmap.org/wiki/Tag:level%3D1) [-1](https://wiki.openstreetmap.org/wiki/Tag:level%3D-1)
 | 
					 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [fast_food](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dfast_food) [restaurant](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Drestaurant)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [fast_food](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dfast_food) [restaurant](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Drestaurant)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | 
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/level#values) [level](https://wiki.openstreetmap.org/wiki/Key:level) | [float](../SpecialInputElements.md#float) | [0](https://wiki.openstreetmap.org/wiki/Tag:level%3D0) [1](https://wiki.openstreetmap.org/wiki/Tag:level%3D1) [-1](https://wiki.openstreetmap.org/wiki/Tag:level%3D-1)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/wheelchair#values) [wheelchair](https://wiki.openstreetmap.org/wiki/Key:wheelchair) | Multiple choice | [designated](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Ddesignated) [yes](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dno)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/wheelchair#values) [wheelchair](https://wiki.openstreetmap.org/wiki/Key:wheelchair) | Multiple choice | [designated](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Ddesignated) [yes](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dno)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/cuisine#values) [cuisine](https://wiki.openstreetmap.org/wiki/Key:cuisine) | [string](../SpecialInputElements.md#string) | [pizza](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpizza) [friture](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfriture) [pasta](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpasta) [kebab](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dkebab) [sandwich](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsandwich) [burger](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dburger) [sushi](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsushi) [coffee](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dcoffee) [italian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Ditalian) [french](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfrench) [chinese](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dchinese) [greek](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dgreek) [indian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dindian) [turkish](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dturkish) [thai](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dthai)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/cuisine#values) [cuisine](https://wiki.openstreetmap.org/wiki/Key:cuisine) | [string](../SpecialInputElements.md#string) | [pizza](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpizza) [friture](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfriture) [pasta](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpasta) [kebab](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dkebab) [sandwich](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsandwich) [burger](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dburger) [sushi](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsushi) [coffee](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dcoffee) [italian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Ditalian) [french](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfrench) [chinese](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dchinese) [greek](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dgreek) [indian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dindian) [turkish](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dturkish) [thai](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dthai)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/reservation#values) [reservation](https://wiki.openstreetmap.org/wiki/Key:reservation) | Multiple choice | [required](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drequired) [recommended](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drecommended) [yes](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dno)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/reservation#values) [reservation](https://wiki.openstreetmap.org/wiki/Key:reservation) | Multiple choice | [required](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drequired) [recommended](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drecommended) [yes](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dno)
 | 
				
			||||||
| 
						 | 
					@ -107,31 +107,6 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The question is  *On what level is this feature located?*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This rendering asks information about the property  [level](https://wiki.openstreetmap.org/wiki/Key:level) 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This is rendered with  `Located on the {level}th floor`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  - *Located underground*  corresponds with  `location=underground`
 | 
					 | 
				
			||||||
  - This option cannot be chosen as answer
 | 
					 | 
				
			||||||
  - *Located on the ground floor*  corresponds with  `level=0`
 | 
					 | 
				
			||||||
  - *Located on the ground floor*  corresponds with  ``
 | 
					 | 
				
			||||||
  - This option cannot be chosen as answer
 | 
					 | 
				
			||||||
  - *Located on the first floor*  corresponds with  `level=1`
 | 
					 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Name 
 | 
					### Name 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -262,6 +237,47 @@ The question is  *Which methods of payment are accepted here?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *On what level is this feature located?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This rendering asks information about the property  [level](https://wiki.openstreetmap.org/wiki/Key:level) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - *Located underground*  corresponds with  `location=underground`
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					  - *Located on the ground floor*  corresponds with  `level=0`
 | 
				
			||||||
 | 
					  - *Located on the ground floor*  corresponds with  ``
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					  - *Located on the first floor*  corresponds with  `level=1`
 | 
				
			||||||
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### wheelchair-access 
 | 
					### wheelchair-access 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -727,7 +743,7 @@ reservation.0 | Reservation not required | reservation=no\|reservation=optional\
 | 
				
			||||||
 | 
					
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
food-category.0 | Has a vegetarian menu (default) | 
 | 
					food-category.0 | Restaurants and fast food businesses (default) | 
 | 
				
			||||||
food-category.1 | Only fastfood businesses | amenity=fast_food
 | 
					food-category.1 | Only fastfood businesses | amenity=fast_food
 | 
				
			||||||
food-category.2 | Only restaurants | amenity=restaurant
 | 
					food-category.2 | Only restaurants | amenity=restaurant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -736,14 +752,14 @@ food-category.2 | Only restaurants | amenity=restaurant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
vegetarian.0 | Has a vegan menu | diet:vegetarian=yes\|diet:vegetarian=only\|diet:vegan=yes\|diet:vegan=only
 | 
					vegetarian.0 | Has a vegetarian menu | diet:vegetarian=yes\|diet:vegetarian=only\|diet:vegan=yes\|diet:vegan=only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
vegan.0 | Has a halal menu | diet:vegan=yes\|diet:vegan=only
 | 
					vegan.0 | Has a vegan menu | diet:vegan=yes\|diet:vegan=only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -772,6 +788,15 @@ accepts_cash.0 | Accepts cash | payment:cash=yes
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
accepts_cards.0 | Accepts payment cards | payment:cards=yes
 | 
					accepts_cards.0 | Accepts payment cards | payment:cards=yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					id | question | osmTags
 | 
				
			||||||
 | 
					---- | ---------- | ---------
 | 
				
			||||||
 | 
					dogs.0 | No preference towards dogs (default) | 
 | 
				
			||||||
 | 
					dogs.1 | Dogs allowed | dog=unleashed\|dog=yes
 | 
				
			||||||
 | 
					dogs.2 | No dogs allowed | dog=no
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This document is autogenerated from [assets/themes/pets/pets.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/pets/pets.json)
 | 
					This document is autogenerated from [assets/themes/pets/pets.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/pets/pets.json)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -384,7 +384,21 @@ The question is  *Which methods of payment are accepted here?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -407,6 +421,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### copyshop-print-sizes 
 | 
					### copyshop-print-sizes 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -297,7 +297,21 @@ The question is  *Is the penny press indoors?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,6 +334,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### check_date 
 | 
					### check_date 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,7 +93,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,6 +130,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Entrance type 
 | 
					### Entrance type 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -206,7 +206,21 @@ The question is  *Is this place accessible with a wheelchair?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -229,6 +243,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### reviews 
 | 
					### reviews 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,13 +50,13 @@ this quick overview is incomplete
 | 
				
			||||||
attribute | type | values which are supported by this layer
 | 
					attribute | type | values which are supported by this layer
 | 
				
			||||||
----------- | ------ | ------------------------------------------
 | 
					----------- | ------ | ------------------------------------------
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/level#values) [level](https://wiki.openstreetmap.org/wiki/Key:level) | [float](../SpecialInputElements.md#float) | [0](https://wiki.openstreetmap.org/wiki/Tag:level%3D0) [1](https://wiki.openstreetmap.org/wiki/Tag:level%3D1) [-1](https://wiki.openstreetmap.org/wiki/Tag:level%3D-1)
 | 
					 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [fast_food](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dfast_food) [restaurant](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Drestaurant)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [fast_food](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dfast_food) [restaurant](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Drestaurant)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | 
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/level#values) [level](https://wiki.openstreetmap.org/wiki/Key:level) | [float](../SpecialInputElements.md#float) | [0](https://wiki.openstreetmap.org/wiki/Tag:level%3D0) [1](https://wiki.openstreetmap.org/wiki/Tag:level%3D1) [-1](https://wiki.openstreetmap.org/wiki/Tag:level%3D-1)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/wheelchair#values) [wheelchair](https://wiki.openstreetmap.org/wiki/Key:wheelchair) | Multiple choice | [designated](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Ddesignated) [yes](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dno)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/wheelchair#values) [wheelchair](https://wiki.openstreetmap.org/wiki/Key:wheelchair) | Multiple choice | [designated](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Ddesignated) [yes](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dno)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/cuisine#values) [cuisine](https://wiki.openstreetmap.org/wiki/Key:cuisine) | [string](../SpecialInputElements.md#string) | [pizza](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpizza) [friture](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfriture) [pasta](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpasta) [kebab](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dkebab) [sandwich](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsandwich) [burger](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dburger) [sushi](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsushi) [coffee](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dcoffee) [italian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Ditalian) [french](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfrench) [chinese](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dchinese) [greek](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dgreek) [indian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dindian) [turkish](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dturkish) [thai](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dthai)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/cuisine#values) [cuisine](https://wiki.openstreetmap.org/wiki/Key:cuisine) | [string](../SpecialInputElements.md#string) | [pizza](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpizza) [friture](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfriture) [pasta](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpasta) [kebab](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dkebab) [sandwich](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsandwich) [burger](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dburger) [sushi](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsushi) [coffee](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dcoffee) [italian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Ditalian) [french](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfrench) [chinese](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dchinese) [greek](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dgreek) [indian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dindian) [turkish](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dturkish) [thai](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dthai)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/reservation#values) [reservation](https://wiki.openstreetmap.org/wiki/Key:reservation) | Multiple choice | [required](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drequired) [recommended](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drecommended) [yes](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dno)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/reservation#values) [reservation](https://wiki.openstreetmap.org/wiki/Key:reservation) | Multiple choice | [required](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drequired) [recommended](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drecommended) [yes](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dno)
 | 
				
			||||||
| 
						 | 
					@ -111,31 +111,6 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The question is  *On what level is this feature located?*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This rendering asks information about the property  [level](https://wiki.openstreetmap.org/wiki/Key:level) 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This is rendered with  `Located on the {level}th floor`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  - *Located underground*  corresponds with  `location=underground`
 | 
					 | 
				
			||||||
  - This option cannot be chosen as answer
 | 
					 | 
				
			||||||
  - *Located on the ground floor*  corresponds with  `level=0`
 | 
					 | 
				
			||||||
  - *Located on the ground floor*  corresponds with  ``
 | 
					 | 
				
			||||||
  - This option cannot be chosen as answer
 | 
					 | 
				
			||||||
  - *Located on the first floor*  corresponds with  `level=1`
 | 
					 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Name 
 | 
					### Name 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -266,6 +241,47 @@ The question is  *Which methods of payment are accepted here?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *On what level is this feature located?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This rendering asks information about the property  [level](https://wiki.openstreetmap.org/wiki/Key:level) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - *Located underground*  corresponds with  `location=underground`
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					  - *Located on the ground floor*  corresponds with  `level=0`
 | 
				
			||||||
 | 
					  - *Located on the ground floor*  corresponds with  ``
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					  - *Located on the first floor*  corresponds with  `level=1`
 | 
				
			||||||
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### wheelchair-access 
 | 
					### wheelchair-access 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -731,7 +747,7 @@ reservation.0 | Reservation not required | reservation=no\|reservation=optional\
 | 
				
			||||||
 | 
					
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
food-category.0 | Has a vegetarian menu (default) | 
 | 
					food-category.0 | Restaurants and fast food businesses (default) | 
 | 
				
			||||||
food-category.1 | Only fastfood businesses | amenity=fast_food
 | 
					food-category.1 | Only fastfood businesses | amenity=fast_food
 | 
				
			||||||
food-category.2 | Only restaurants | amenity=restaurant
 | 
					food-category.2 | Only restaurants | amenity=restaurant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -740,14 +756,14 @@ food-category.2 | Only restaurants | amenity=restaurant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
vegetarian.0 | Has a vegan menu | diet:vegetarian=yes\|diet:vegetarian=only\|diet:vegan=yes\|diet:vegan=only
 | 
					vegetarian.0 | Has a vegetarian menu | diet:vegetarian=yes\|diet:vegetarian=only\|diet:vegan=yes\|diet:vegan=only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
vegan.0 | Has a halal menu | diet:vegan=yes\|diet:vegan=only
 | 
					vegan.0 | Has a vegan menu | diet:vegan=yes\|diet:vegan=only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -776,6 +792,15 @@ accepts_cash.0 | Accepts cash | payment:cash=yes
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
accepts_cards.0 | Accepts payment cards | payment:cards=yes
 | 
					accepts_cards.0 | Accepts payment cards | payment:cards=yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					id | question | osmTags
 | 
				
			||||||
 | 
					---- | ---------- | ---------
 | 
				
			||||||
 | 
					dogs.0 | No preference towards dogs (default) | 
 | 
				
			||||||
 | 
					dogs.1 | Dogs allowed | dog=unleashed\|dog=yes
 | 
				
			||||||
 | 
					dogs.2 | No dogs allowed | dog=no
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This document is autogenerated from [assets/layers/food/food.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/food/food.json)
 | 
					This document is autogenerated from [assets/layers/food/food.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/food/food.json)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,13 +46,13 @@ this quick overview is incomplete
 | 
				
			||||||
attribute | type | values which are supported by this layer
 | 
					attribute | type | values which are supported by this layer
 | 
				
			||||||
----------- | ------ | ------------------------------------------
 | 
					----------- | ------ | ------------------------------------------
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/level#values) [level](https://wiki.openstreetmap.org/wiki/Key:level) | [float](../SpecialInputElements.md#float) | [0](https://wiki.openstreetmap.org/wiki/Tag:level%3D0) [1](https://wiki.openstreetmap.org/wiki/Tag:level%3D1) [-1](https://wiki.openstreetmap.org/wiki/Tag:level%3D-1)
 | 
					 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [fast_food](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dfast_food) [restaurant](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Drestaurant)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [fast_food](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dfast_food) [restaurant](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Drestaurant)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | 
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/level#values) [level](https://wiki.openstreetmap.org/wiki/Key:level) | [float](../SpecialInputElements.md#float) | [0](https://wiki.openstreetmap.org/wiki/Tag:level%3D0) [1](https://wiki.openstreetmap.org/wiki/Tag:level%3D1) [-1](https://wiki.openstreetmap.org/wiki/Tag:level%3D-1)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/wheelchair#values) [wheelchair](https://wiki.openstreetmap.org/wiki/Key:wheelchair) | Multiple choice | [designated](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Ddesignated) [yes](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dno)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/wheelchair#values) [wheelchair](https://wiki.openstreetmap.org/wiki/Key:wheelchair) | Multiple choice | [designated](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Ddesignated) [yes](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dlimited) [no](https://wiki.openstreetmap.org/wiki/Tag:wheelchair%3Dno)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/cuisine#values) [cuisine](https://wiki.openstreetmap.org/wiki/Key:cuisine) | [string](../SpecialInputElements.md#string) | [pizza](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpizza) [friture](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfriture) [pasta](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpasta) [kebab](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dkebab) [sandwich](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsandwich) [burger](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dburger) [sushi](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsushi) [coffee](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dcoffee) [italian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Ditalian) [french](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfrench) [chinese](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dchinese) [greek](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dgreek) [indian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dindian) [turkish](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dturkish) [thai](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dthai)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/cuisine#values) [cuisine](https://wiki.openstreetmap.org/wiki/Key:cuisine) | [string](../SpecialInputElements.md#string) | [pizza](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpizza) [friture](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfriture) [pasta](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dpasta) [kebab](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dkebab) [sandwich](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsandwich) [burger](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dburger) [sushi](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dsushi) [coffee](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dcoffee) [italian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Ditalian) [french](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dfrench) [chinese](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dchinese) [greek](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dgreek) [indian](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dindian) [turkish](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dturkish) [thai](https://wiki.openstreetmap.org/wiki/Tag:cuisine%3Dthai)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/reservation#values) [reservation](https://wiki.openstreetmap.org/wiki/Key:reservation) | Multiple choice | [required](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drequired) [recommended](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drecommended) [yes](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dno)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/reservation#values) [reservation](https://wiki.openstreetmap.org/wiki/Key:reservation) | Multiple choice | [required](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drequired) [recommended](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Drecommended) [yes](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:reservation%3Dno)
 | 
				
			||||||
| 
						 | 
					@ -107,31 +107,6 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The question is  *On what level is this feature located?*
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This rendering asks information about the property  [level](https://wiki.openstreetmap.org/wiki/Key:level) 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This is rendered with  `Located on the {level}th floor`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  - *Located underground*  corresponds with  `location=underground`
 | 
					 | 
				
			||||||
  - This option cannot be chosen as answer
 | 
					 | 
				
			||||||
  - *Located on the ground floor*  corresponds with  `level=0`
 | 
					 | 
				
			||||||
  - *Located on the ground floor*  corresponds with  ``
 | 
					 | 
				
			||||||
  - This option cannot be chosen as answer
 | 
					 | 
				
			||||||
  - *Located on the first floor*  corresponds with  `level=1`
 | 
					 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Name 
 | 
					### Name 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -262,6 +237,47 @@ The question is  *Which methods of payment are accepted here?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *On what level is this feature located?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This rendering asks information about the property  [level](https://wiki.openstreetmap.org/wiki/Key:level) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - *Located underground*  corresponds with  `location=underground`
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					  - *Located on the ground floor*  corresponds with  `level=0`
 | 
				
			||||||
 | 
					  - *Located on the ground floor*  corresponds with  ``
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					  - *Located on the first floor*  corresponds with  `level=1`
 | 
				
			||||||
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### wheelchair-access 
 | 
					### wheelchair-access 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -727,7 +743,7 @@ reservation.0 | Reservation not required | reservation=no\|reservation=optional\
 | 
				
			||||||
 | 
					
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
food-category.0 | Has a vegetarian menu (default) | 
 | 
					food-category.0 | Restaurants and fast food businesses (default) | 
 | 
				
			||||||
food-category.1 | Only fastfood businesses | amenity=fast_food
 | 
					food-category.1 | Only fastfood businesses | amenity=fast_food
 | 
				
			||||||
food-category.2 | Only restaurants | amenity=restaurant
 | 
					food-category.2 | Only restaurants | amenity=restaurant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -736,14 +752,14 @@ food-category.2 | Only restaurants | amenity=restaurant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
vegetarian.0 | Has a vegan menu | diet:vegetarian=yes\|diet:vegetarian=only\|diet:vegan=yes\|diet:vegan=only
 | 
					vegetarian.0 | Has a vegetarian menu | diet:vegetarian=yes\|diet:vegetarian=only\|diet:vegan=yes\|diet:vegan=only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
vegan.0 | Has a halal menu | diet:vegan=yes\|diet:vegan=only
 | 
					vegan.0 | Has a vegan menu | diet:vegan=yes\|diet:vegan=only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -772,6 +788,15 @@ accepts_cash.0 | Accepts cash | payment:cash=yes
 | 
				
			||||||
id | question | osmTags
 | 
					id | question | osmTags
 | 
				
			||||||
---- | ---------- | ---------
 | 
					---- | ---------- | ---------
 | 
				
			||||||
accepts_cards.0 | Accepts payment cards | payment:cards=yes
 | 
					accepts_cards.0 | Accepts payment cards | payment:cards=yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					id | question | osmTags
 | 
				
			||||||
 | 
					---- | ---------- | ---------
 | 
				
			||||||
 | 
					dogs.0 | No preference towards dogs (default) | 
 | 
				
			||||||
 | 
					dogs.1 | Dogs allowed | dog=unleashed\|dog=yes
 | 
				
			||||||
 | 
					dogs.2 | No dogs allowed | dog=no
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This document is autogenerated from [assets/themes/fritures/fritures.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/fritures/fritures.json)
 | 
					This document is autogenerated from [assets/themes/fritures/fritures.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/fritures/fritures.json)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,7 +126,21 @@ This is rendered with  `This hackerspace is named <b>{name}</b>`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,6 +163,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### website 
 | 
					### website 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,8 +49,12 @@ this quick overview is incomplete
 | 
				
			||||||
attribute | type | values which are supported by this layer
 | 
					attribute | type | values which are supported by this layer
 | 
				
			||||||
----------- | ------ | ------------------------------------------
 | 
					----------- | ------ | ------------------------------------------
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/level#values) [level](https://wiki.openstreetmap.org/wiki/Key:level) | [float](../SpecialInputElements.md#float) | [0](https://wiki.openstreetmap.org/wiki/Tag:level%3D0) [1](https://wiki.openstreetmap.org/wiki/Tag:level%3D1) [-1](https://wiki.openstreetmap.org/wiki/Tag:level%3D-1)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/ref#values) [ref](https://wiki.openstreetmap.org/wiki/Key:ref) | [string](../SpecialInputElements.md#string) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/ref#values) [ref](https://wiki.openstreetmap.org/wiki/Key:ref) | [string](../SpecialInputElements.md#string) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | 
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/room#values) [room](https://wiki.openstreetmap.org/wiki/Key:room) | Multiple choice | [administration](https://wiki.openstreetmap.org/wiki/Tag:room%3Dadministration) [auditorium](https://wiki.openstreetmap.org/wiki/Tag:room%3Dauditorium) [bedroom](https://wiki.openstreetmap.org/wiki/Tag:room%3Dbedroom) [chapel](https://wiki.openstreetmap.org/wiki/Tag:room%3Dchapel) [class](https://wiki.openstreetmap.org/wiki/Tag:room%3Dclass) [computer](https://wiki.openstreetmap.org/wiki/Tag:room%3Dcomputer) [conference](https://wiki.openstreetmap.org/wiki/Tag:room%3Dconference) [crypt](https://wiki.openstreetmap.org/wiki/Tag:room%3Dcrypt) [kitchen](https://wiki.openstreetmap.org/wiki/Tag:room%3Dkitchen) [laboratory](https://wiki.openstreetmap.org/wiki/Tag:room%3Dlaboratory) [library](https://wiki.openstreetmap.org/wiki/Tag:room%3Dlibrary) [locker](https://wiki.openstreetmap.org/wiki/Tag:room%3Dlocker) [nursery](https://wiki.openstreetmap.org/wiki/Tag:room%3Dnursery) [office](https://wiki.openstreetmap.org/wiki/Tag:room%3Doffice) [prison_cell](https://wiki.openstreetmap.org/wiki/Tag:room%3Dprison_cell) [restaurant](https://wiki.openstreetmap.org/wiki/Tag:room%3Drestaurant) [security_check](https://wiki.openstreetmap.org/wiki/Tag:room%3Dsecurity_check) [sport](https://wiki.openstreetmap.org/wiki/Tag:room%3Dsport) [storage](https://wiki.openstreetmap.org/wiki/Tag:room%3Dstorage) [technical](https://wiki.openstreetmap.org/wiki/Tag:room%3Dtechnical) [toilets](https://wiki.openstreetmap.org/wiki/Tag:room%3Dtoilets) [waiting](https://wiki.openstreetmap.org/wiki/Tag:room%3Dwaiting)
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/capacity#values) [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) | [pnat](../SpecialInputElements.md#pnat) | 
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/name:etymology:wikidata#values) [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,6 +90,47 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *On what level is this feature located?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This rendering asks information about the property  [level](https://wiki.openstreetmap.org/wiki/Key:level) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - *Located underground*  corresponds with  `location=underground`
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					  - *Located on the ground floor*  corresponds with  `level=0`
 | 
				
			||||||
 | 
					  - *Located on the ground floor*  corresponds with  ``
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					  - *Located on the first floor*  corresponds with  `level=1`
 | 
				
			||||||
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### ref 
 | 
					### ref 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,6 +163,74 @@ This tagrendering is only visible in the popup if the following condition is met
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### room-type 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *What type of room is this?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - *This is a administrative room*  corresponds with  `room=administration`
 | 
				
			||||||
 | 
					  - *This is a auditorium*  corresponds with  `room=auditorium`
 | 
				
			||||||
 | 
					  - *This is a bedroom*  corresponds with  `room=bedroom`
 | 
				
			||||||
 | 
					  - *This is a chapel*  corresponds with  `room=chapel`
 | 
				
			||||||
 | 
					  - *This is a classroom*  corresponds with  `room=class`
 | 
				
			||||||
 | 
					  - *This is a classroom*  corresponds with  `room=classroom`
 | 
				
			||||||
 | 
					  - This option cannot be chosen as answer
 | 
				
			||||||
 | 
					  - *This is a computer room*  corresponds with  `room=computer`
 | 
				
			||||||
 | 
					  - *This is a conference room*  corresponds with  `room=conference`
 | 
				
			||||||
 | 
					  - *This is a crypt*  corresponds with  `room=crypt`
 | 
				
			||||||
 | 
					  - *This is a kitchen*  corresponds with  `room=kitchen`
 | 
				
			||||||
 | 
					  - *This is a laboratory*  corresponds with  `room=laboratory`
 | 
				
			||||||
 | 
					  - *This is a library*  corresponds with  `room=library`
 | 
				
			||||||
 | 
					  - *This is a locker room*  corresponds with  `room=locker`
 | 
				
			||||||
 | 
					  - *This is a nursery*  corresponds with  `room=nursery`
 | 
				
			||||||
 | 
					  - *This is an office*  corresponds with  `room=office`
 | 
				
			||||||
 | 
					  - *This is a prison_cell*  corresponds with  `room=prison_cell`
 | 
				
			||||||
 | 
					  - *This is a restaurant*  corresponds with  `room=restaurant`
 | 
				
			||||||
 | 
					  - *This is a room to perform security checks*  corresponds with  `room=security_check`
 | 
				
			||||||
 | 
					  - *This is a sport room*  corresponds with  `room=sport`
 | 
				
			||||||
 | 
					  - *This is a storage room*  corresponds with  `room=storage`
 | 
				
			||||||
 | 
					  - *This is a technical room*  corresponds with  `room=technical`
 | 
				
			||||||
 | 
					  - *These are toilets*  corresponds with  `room=toilets`
 | 
				
			||||||
 | 
					  - *This is a waiting room*  corresponds with  `room=waiting`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### room-capacity 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *How much people can at most fit in this room?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This rendering asks information about the property  [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is rendered with  `At most {capacity} people fit this room`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `room=waiting|room=restaurant|room=office|room=nursery|room=conference|room=auditorium|room=chapel|room=bedroom|room=classroom`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### wikipedia-etymology 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *What is the Wikidata-item that this object is named after?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This rendering asks information about the property  [name:etymology:wikidata](https://wiki.openstreetmap.org/wiki/Key:name:etymology:wikidata) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is rendered with  `<h3>Wikipedia article of the name giver</h3>{wikipedia(name:etymology:wikidata):max-height:20rem}`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### leftover-questions 
 | 
					### leftover-questions 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -384,7 +384,21 @@ The question is  *Which methods of payment are accepted here?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -407,6 +421,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### copyshop-print-sizes 
 | 
					### copyshop-print-sizes 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,6 +125,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### parking-type 
 | 
					### parking-type 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,6 +123,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### picnic_table-material 
 | 
					### picnic_table-material 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,21 @@ This is rendered with  `Platform {ref}`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -97,6 +111,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### leftover-questions 
 | 
					### leftover-questions 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -85,7 +85,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,6 +122,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### desk-height 
 | 
					### desk-height 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,8 @@ Schools giving primary and secondary education and post-secondary, non-tertiary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - This layer is shown at zoomlevel **12** and higher
 | 
					  - This layer is shown at zoomlevel **12** and higher
 | 
				
			||||||
 | 
					  - This layer will automatically load  [school](./school.md)  into the layout as it depends on it:  a calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _enclosing)
 | 
				
			||||||
 | 
					  - This layer is needed as dependency for layer [school](#school)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -389,7 +389,21 @@ The question is  *Which methods of payment are accepted here?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -412,6 +426,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### copyshop-print-sizes 
 | 
					### copyshop-print-sizes 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -401,7 +401,21 @@ The question is  *Which methods of payment are accepted here?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -424,6 +438,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### copyshop-print-sizes 
 | 
					### copyshop-print-sizes 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,6 +125,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### access 
 | 
					### access 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -384,7 +384,21 @@ The question is  *Which methods of payment are accepted here?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -407,6 +421,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### copyshop-print-sizes 
 | 
					### copyshop-print-sizes 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@ This layer shows surveillance cameras and allows a contributor to update informa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - This layer is shown at zoomlevel **12** and higher
 | 
					  - This layer is shown at zoomlevel **12** and higher
 | 
				
			||||||
  - This layer will automatically load  [walls_and_buildings](./walls_and_buildings.md)  into the layout as it depends on it:  a preset snaps to this layer (presets[1])
 | 
					  - This layer will automatically load  [walls_and_buildings](./walls_and_buildings.md)  into the layout as it depends on it:  a preset snaps to this layer (presets[1])
 | 
				
			||||||
 | 
					  - This layer will automatically load  [walls_and_buildings](./walls_and_buildings.md)  into the layout as it depends on it:  a preset snaps to this layer (presets[3])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,6 +49,7 @@ this quick overview is incomplete
 | 
				
			||||||
attribute | type | values which are supported by this layer
 | 
					attribute | type | values which are supported by this layer
 | 
				
			||||||
----------- | ------ | ------------------------------------------
 | 
					----------- | ------ | ------------------------------------------
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | 
 | 
				
			||||||
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/surveillance:type#values) [surveillance:type](https://wiki.openstreetmap.org/wiki/Key:surveillance:type) | Multiple choice | [camera](https://wiki.openstreetmap.org/wiki/Tag:surveillance:type%3Dcamera) [ALPR](https://wiki.openstreetmap.org/wiki/Tag:surveillance:type%3DALPR)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/camera:type#values) [camera:type](https://wiki.openstreetmap.org/wiki/Key:camera:type) | Multiple choice | [fixed](https://wiki.openstreetmap.org/wiki/Tag:camera:type%3Dfixed) [dome](https://wiki.openstreetmap.org/wiki/Tag:camera:type%3Ddome) [panning](https://wiki.openstreetmap.org/wiki/Tag:camera:type%3Dpanning)
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/camera:type#values) [camera:type](https://wiki.openstreetmap.org/wiki/Key:camera:type) | Multiple choice | [fixed](https://wiki.openstreetmap.org/wiki/Tag:camera:type%3Dfixed) [dome](https://wiki.openstreetmap.org/wiki/Tag:camera:type%3Ddome) [panning](https://wiki.openstreetmap.org/wiki/Tag:camera:type%3Dpanning)
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/camera:direction#values) [camera:direction](https://wiki.openstreetmap.org/wiki/Key:camera:direction) | [direction](../SpecialInputElements.md#direction) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/camera:direction#values) [camera:direction](https://wiki.openstreetmap.org/wiki/Key:camera:direction) | [direction](../SpecialInputElements.md#direction) | 
 | 
				
			||||||
[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | 
 | 
					[<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | 
 | 
				
			||||||
| 
						 | 
					@ -91,6 +93,22 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### has_alpr 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The question is  *Can this camera automatically detect license plates?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - *This is a camera without number plate recognition.*  corresponds with  `surveillance:type=camera`
 | 
				
			||||||
 | 
					  - *This is an ALPR (Automatic License Plate Reader)*  corresponds with  `surveillance:type=ALPR`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Camera type: fixed; panning; dome 
 | 
					### Camera type: fixed; panning; dome 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,6 +123,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### operator 
 | 
					### operator 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,7 +73,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,6 +110,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### barrier 
 | 
					### barrier 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,6 +135,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### toilet-access 
 | 
					### toilet-access 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,21 @@ This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,6 +132,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### toilet-access 
 | 
					### toilet-access 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -269,7 +269,21 @@ The question is  *Is this vending machine indoors?*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### level 
 | 
					### repeated 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has no question and is thus read-only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering is only visible in the popup if the following condition is met: `repeat_on~.+`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### single_level 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,6 +306,8 @@ This is rendered with  `Located on the {level}th floor`
 | 
				
			||||||
  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
					  - *Located on the first basement level*  corresponds with  `level=-1`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This tagrendering has labels  `level`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### phone 
 | 
					### phone 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,8 +110,12 @@ In other words: use `{ "before": ..., "after": ..., "special": {"type": ..., "ar
 | 
				
			||||||
      * [Example usage of image_carousel](#example-usage-of-image_carousel)
 | 
					      * [Example usage of image_carousel](#example-usage-of-image_carousel)
 | 
				
			||||||
    + [image_upload](#image_upload)
 | 
					    + [image_upload](#image_upload)
 | 
				
			||||||
      * [Example usage of image_upload](#example-usage-of-image_upload)
 | 
					      * [Example usage of image_upload](#example-usage-of-image_upload)
 | 
				
			||||||
    + [reviews](#reviews)
 | 
					    + [rating](#rating)
 | 
				
			||||||
      * [Example usage of reviews](#example-usage-of-reviews)
 | 
					      * [Example usage of rating](#example-usage-of-rating)
 | 
				
			||||||
 | 
					    + [create_review](#create_review)
 | 
				
			||||||
 | 
					      * [Example usage of create_review](#example-usage-of-create_review)
 | 
				
			||||||
 | 
					    + [list_reviews](#list_reviews)
 | 
				
			||||||
 | 
					      * [Example usage of list_reviews](#example-usage-of-list_reviews)
 | 
				
			||||||
    + [opening_hours_table](#opening_hours_table)
 | 
					    + [opening_hours_table](#opening_hours_table)
 | 
				
			||||||
      * [Example usage of opening_hours_table](#example-usage-of-opening_hours_table)
 | 
					      * [Example usage of opening_hours_table](#example-usage-of-opening_hours_table)
 | 
				
			||||||
    + [live](#live)
 | 
					    + [live](#live)
 | 
				
			||||||
| 
						 | 
					@ -744,17 +748,49 @@ image_key | image,mapillary,image,wikidata,wikimedia_commons,image,image | The k
 | 
				
			||||||
 | 
					
 | 
				
			||||||
name | default | description
 | 
					name | default | description
 | 
				
			||||||
------ | --------- | -------------
 | 
					------ | --------- | -------------
 | 
				
			||||||
image-key | image | Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)
 | 
					image-key | _undefined_ | Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)
 | 
				
			||||||
label | Add image | The text to show on the button
 | 
					label | _undefined_ | The text to show on the button
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Example usage of image_upload 
 | 
					#### Example usage of image_upload 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 `{image_upload(image,Add image)}`
 | 
					 `{image_upload(,)}`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### reviews 
 | 
					### rating 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Shows stars which represent the avarage rating on mangrove.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 rating 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 `{rating(name,)}`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### create_review 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 Invites the contributor to leave a review. Somewhat small UI-element until interacted 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 create_review 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 `{create_review(name,)}`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### list_reviews 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 Adds an overview of the mangrove-reviews of this object. Mangrove.Reviews needs - in order to identify the reviewed object - a coordinate and a name. By default, the name of the object is given, but this can be overwritten 
 | 
					 Adds an overview of the mangrove-reviews of this object. Mangrove.Reviews needs - in order to identify the reviewed object - a coordinate and a name. By default, the name of the object is given, but this can be overwritten 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -764,7 +800,7 @@ subjectKey | name | The key to use to determine the subject. If specified, the s
 | 
				
			||||||
fallback | _undefined_ | The identifier to use, if <i>tags[subjectKey]</i> as specified above is not available. This is effectively a fallback value
 | 
					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 
 | 
					#### Example usage of list_reviews 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 `{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
 | 
					 `{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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -247,9 +247,14 @@
 | 
				
			||||||
      "description": "Layer 'Benches' shows tourism=artwork with a fixed text, namely 'This bench has an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Benches')",
 | 
					      "description": "Layer 'Benches' shows tourism=artwork with a fixed text, namely 'This bench has an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Benches')",
 | 
				
			||||||
      "value": "artwork"
 | 
					      "value": "artwork"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "not:tourism:artwork",
 | 
				
			||||||
 | 
					      "description": "Layer 'Benches' shows not:tourism:artwork=yes with a fixed text, namely 'This bench does not have an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Benches')",
 | 
				
			||||||
 | 
					      "value": "yes"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "tourism",
 | 
					      "key": "tourism",
 | 
				
			||||||
      "description": "Layer 'Benches' shows  with a fixed text, namely 'This bench does not have an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Benches') Picking this answer will delete the key tourism.",
 | 
					      "description": "Layer 'Benches' shows  with a fixed text, namely 'This bench <span class=\"subtle\">probably</span> doesn't have an integrated artwork' (in the mapcomplete.org theme 'Benches') Picking this answer will delete the key tourism.",
 | 
				
			||||||
      "value": ""
 | 
					      "value": ""
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,35 +40,6 @@
 | 
				
			||||||
      "key": "wikipedia",
 | 
					      "key": "wikipedia",
 | 
				
			||||||
      "description": "The layer 'Restaurants and fast food 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 'Restaurants and fast food 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": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Restaurants and fast food')"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "location",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
					 | 
				
			||||||
      "value": "underground"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
					 | 
				
			||||||
      "value": "0"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Restaurants and fast food') Picking this answer will delete the key level.",
 | 
					 | 
				
			||||||
      "value": ""
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
					 | 
				
			||||||
      "value": "1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
					 | 
				
			||||||
      "value": "-1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "name",
 | 
					      "key": "name",
 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Restaurants and fast food')"
 | 
					      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Restaurants and fast food')"
 | 
				
			||||||
| 
						 | 
					@ -126,6 +97,35 @@
 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
					      "description": "Layer 'Restaurants and fast food' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
				
			||||||
      "value": "yes"
 | 
					      "value": "yes"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Restaurants and fast food')"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "location",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
				
			||||||
 | 
					      "value": "underground"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
				
			||||||
 | 
					      "value": "0"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Restaurants and fast food') Picking this answer will delete the key level.",
 | 
				
			||||||
 | 
					      "value": ""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
				
			||||||
 | 
					      "value": "1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Restaurants and fast food')",
 | 
				
			||||||
 | 
					      "value": "-1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "wheelchair",
 | 
					      "key": "wheelchair",
 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' 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 'Restaurants and fast food')",
 | 
					      "description": "Layer 'Restaurants and fast food' 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 'Restaurants and fast food')",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,35 +44,6 @@
 | 
				
			||||||
      "key": "wikipedia",
 | 
					      "key": "wikipedia",
 | 
				
			||||||
      "description": "The layer 'Fries shop 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 'Fries shop 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": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Fries shop' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Fries shops')"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "location",
 | 
					 | 
				
			||||||
      "description": "Layer 'Fries shop' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Fries shops')",
 | 
					 | 
				
			||||||
      "value": "underground"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Fries shop' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Fries shops')",
 | 
					 | 
				
			||||||
      "value": "0"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Fries shop' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Fries shops') Picking this answer will delete the key level.",
 | 
					 | 
				
			||||||
      "value": ""
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Fries shop' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Fries shops')",
 | 
					 | 
				
			||||||
      "value": "1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Fries shop' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Fries shops')",
 | 
					 | 
				
			||||||
      "value": "-1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "name",
 | 
					      "key": "name",
 | 
				
			||||||
      "description": "Layer 'Fries shop' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Fries shops')"
 | 
					      "description": "Layer 'Fries shop' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Fries shops')"
 | 
				
			||||||
| 
						 | 
					@ -130,6 +101,35 @@
 | 
				
			||||||
      "description": "Layer 'Fries shop' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'Fries shops')",
 | 
					      "description": "Layer 'Fries shop' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'Fries shops')",
 | 
				
			||||||
      "value": "yes"
 | 
					      "value": "yes"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Fries shop' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Fries shops')"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "location",
 | 
				
			||||||
 | 
					      "description": "Layer 'Fries shop' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Fries shops')",
 | 
				
			||||||
 | 
					      "value": "underground"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Fries shop' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Fries shops')",
 | 
				
			||||||
 | 
					      "value": "0"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Fries shop' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Fries shops') Picking this answer will delete the key level.",
 | 
				
			||||||
 | 
					      "value": ""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Fries shop' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Fries shops')",
 | 
				
			||||||
 | 
					      "value": "1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Fries shop' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Fries shops')",
 | 
				
			||||||
 | 
					      "value": "-1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "wheelchair",
 | 
					      "key": "wheelchair",
 | 
				
			||||||
      "description": "Layer 'Fries shop' 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 'Fries shops')",
 | 
					      "description": "Layer 'Fries shop' 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 'Fries shops')",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,35 @@
 | 
				
			||||||
      "key": "wikipedia",
 | 
					      "key": "wikipedia",
 | 
				
			||||||
      "description": "The layer 'Indoors 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 'Indoors 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": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Indoors')"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "location",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "underground"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "0"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Indoors') Picking this answer will delete the key level.",
 | 
				
			||||||
 | 
					      "value": ""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "-1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "ref",
 | 
					      "key": "ref",
 | 
				
			||||||
      "description": "Layer 'Indoors' shows and asks freeform values for key 'ref' (in the mapcomplete.org theme 'Indoors') (This is only shown if indoor=room|indoor=area|indoor=corridor)"
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'ref' (in the mapcomplete.org theme 'Indoors') (This is only shown if indoor=room|indoor=area|indoor=corridor)"
 | 
				
			||||||
| 
						 | 
					@ -63,6 +92,129 @@
 | 
				
			||||||
      "key": "name",
 | 
					      "key": "name",
 | 
				
			||||||
      "description": "Layer 'Indoors' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Indoors') (This is only shown if indoor=room|indoor=area|indoor=corridor)"
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Indoors') (This is only shown if indoor=room|indoor=area|indoor=corridor)"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=administration with a fixed text, namely 'This is a administrative room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "administration"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=auditorium with a fixed text, namely 'This is a auditorium' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "auditorium"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=bedroom with a fixed text, namely 'This is a bedroom' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "bedroom"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=chapel with a fixed text, namely 'This is a chapel' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "chapel"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=class with a fixed text, namely 'This is a classroom' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "class"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=classroom with a fixed text, namely 'This is a classroom' (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "classroom"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=computer with a fixed text, namely 'This is a computer room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "computer"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=conference with a fixed text, namely 'This is a conference room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "conference"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=crypt with a fixed text, namely 'This is a crypt' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "crypt"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=kitchen with a fixed text, namely 'This is a kitchen' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "kitchen"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=laboratory with a fixed text, namely 'This is a laboratory' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "laboratory"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=library with a fixed text, namely 'This is a library' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "library"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=locker with a fixed text, namely 'This is a locker room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "locker"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=nursery with a fixed text, namely 'This is a nursery' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "nursery"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=office with a fixed text, namely 'This is an office' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "office"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=prison_cell with a fixed text, namely 'This is a prison_cell' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "prison_cell"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=restaurant with a fixed text, namely 'This is a restaurant' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "restaurant"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=security_check with a fixed text, namely 'This is a room to perform security checks' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "security_check"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=sport with a fixed text, namely 'This is a sport room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "sport"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=storage with a fixed text, namely 'This is a storage room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "storage"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=technical with a fixed text, namely 'This is a technical room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "technical"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=toilets with a fixed text, namely 'These are toilets' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "toilets"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=waiting with a fixed text, namely 'This is a waiting room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Indoors')",
 | 
				
			||||||
 | 
					      "value": "waiting"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "capacity",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'capacity' (in the mapcomplete.org theme 'Indoors') (This is only shown if room=waiting|room=restaurant|room=office|room=nursery|room=conference|room=auditorium|room=chapel|room=bedroom|room=classroom)"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "name:etymology:wikidata",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'name:etymology:wikidata' (in the mapcomplete.org theme 'Indoors') (This is only shown if name:etymology!=unknown)"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "highway",
 | 
					      "key": "highway",
 | 
				
			||||||
      "description": "The MapComplete theme Indoors has a layer Pedestrian paths showing features with this tag",
 | 
					      "description": "The MapComplete theme Indoors has a layer Pedestrian paths showing features with this tag",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -668,9 +668,14 @@
 | 
				
			||||||
      "description": "Layer 'Benches' shows tourism=artwork with a fixed text, namely 'This bench has an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Into nature')",
 | 
					      "description": "Layer 'Benches' shows tourism=artwork with a fixed text, namely 'This bench has an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Into nature')",
 | 
				
			||||||
      "value": "artwork"
 | 
					      "value": "artwork"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "not:tourism:artwork",
 | 
				
			||||||
 | 
					      "description": "Layer 'Benches' shows not:tourism:artwork=yes with a fixed text, namely 'This bench does not have an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Into nature')",
 | 
				
			||||||
 | 
					      "value": "yes"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "tourism",
 | 
					      "key": "tourism",
 | 
				
			||||||
      "description": "Layer 'Benches' shows  with a fixed text, namely 'This bench does not have an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Into nature') Picking this answer will delete the key tourism.",
 | 
					      "description": "Layer 'Benches' shows  with a fixed text, namely 'This bench <span class=\"subtle\">probably</span> doesn't have an integrated artwork' (in the mapcomplete.org theme 'Into nature') Picking this answer will delete the key tourism.",
 | 
				
			||||||
      "value": ""
 | 
					      "value": ""
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -550,35 +550,6 @@
 | 
				
			||||||
      "key": "wikipedia",
 | 
					      "key": "wikipedia",
 | 
				
			||||||
      "description": "The layer 'Restaurants and fast food 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 'Restaurants and fast food 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": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'OnWheels')"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "location",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'OnWheels')",
 | 
					 | 
				
			||||||
      "value": "underground"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
 | 
					 | 
				
			||||||
      "value": "0"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'OnWheels') Picking this answer will delete the key level.",
 | 
					 | 
				
			||||||
      "value": ""
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
 | 
					 | 
				
			||||||
      "value": "1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
 | 
					 | 
				
			||||||
      "value": "-1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "name",
 | 
					      "key": "name",
 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'OnWheels')"
 | 
					      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'OnWheels')"
 | 
				
			||||||
| 
						 | 
					@ -636,6 +607,35 @@
 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
 | 
					      "description": "Layer 'Restaurants and fast food' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
 | 
				
			||||||
      "value": "yes"
 | 
					      "value": "yes"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'OnWheels')"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "location",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'OnWheels')",
 | 
				
			||||||
 | 
					      "value": "underground"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
 | 
				
			||||||
 | 
					      "value": "0"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'OnWheels') Picking this answer will delete the key level.",
 | 
				
			||||||
 | 
					      "value": ""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
 | 
				
			||||||
 | 
					      "value": "1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'OnWheels')",
 | 
				
			||||||
 | 
					      "value": "-1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "wheelchair",
 | 
					      "key": "wheelchair",
 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' 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 'Restaurants and fast food' 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')",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -979,9 +979,14 @@
 | 
				
			||||||
      "description": "Layer 'Benches' shows tourism=artwork with a fixed text, namely 'This bench has an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
					      "description": "Layer 'Benches' shows tourism=artwork with a fixed text, namely 'This bench has an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
      "value": "artwork"
 | 
					      "value": "artwork"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "not:tourism:artwork",
 | 
				
			||||||
 | 
					      "description": "Layer 'Benches' shows not:tourism:artwork=yes with a fixed text, namely 'This bench does not have an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "yes"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "tourism",
 | 
					      "key": "tourism",
 | 
				
			||||||
      "description": "Layer 'Benches' shows  with a fixed text, namely 'This bench does not have an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme') Picking this answer will delete the key tourism.",
 | 
					      "description": "Layer 'Benches' shows  with a fixed text, namely 'This bench <span class=\"subtle\">probably</span> doesn't have an integrated artwork' (in the mapcomplete.org theme 'Personal theme') Picking this answer will delete the key tourism.",
 | 
				
			||||||
      "value": ""
 | 
					      "value": ""
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -7305,35 +7310,6 @@
 | 
				
			||||||
      "key": "wikipedia",
 | 
					      "key": "wikipedia",
 | 
				
			||||||
      "description": "The layer 'Restaurants and fast food 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 'Restaurants and fast food 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": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Personal theme')"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "location",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Personal theme')",
 | 
					 | 
				
			||||||
      "value": "underground"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
					 | 
				
			||||||
      "value": "0"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Personal theme') Picking this answer will delete the key level.",
 | 
					 | 
				
			||||||
      "value": ""
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
					 | 
				
			||||||
      "value": "1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
					 | 
				
			||||||
      "value": "-1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "name",
 | 
					      "key": "name",
 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Personal theme')"
 | 
					      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Personal theme')"
 | 
				
			||||||
| 
						 | 
					@ -7391,6 +7367,35 @@
 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
					      "description": "Layer 'Restaurants and fast food' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
      "value": "yes"
 | 
					      "value": "yes"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Personal theme')"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "location",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "underground"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "0"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Personal theme') Picking this answer will delete the key level.",
 | 
				
			||||||
 | 
					      "value": ""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Restaurants and fast food' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "-1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "wheelchair",
 | 
					      "key": "wheelchair",
 | 
				
			||||||
      "description": "Layer 'Restaurants and fast food' 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')",
 | 
					      "description": "Layer 'Restaurants and fast food' 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')",
 | 
				
			||||||
| 
						 | 
					@ -8383,6 +8388,35 @@
 | 
				
			||||||
      "key": "wikipedia",
 | 
					      "key": "wikipedia",
 | 
				
			||||||
      "description": "The layer 'Indoors 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 'Indoors 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": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Personal theme')"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "location",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "underground"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "0"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Personal theme') Picking this answer will delete the key level.",
 | 
				
			||||||
 | 
					      "value": ""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "-1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "ref",
 | 
					      "key": "ref",
 | 
				
			||||||
      "description": "Layer 'Indoors' shows and asks freeform values for key 'ref' (in the mapcomplete.org theme 'Personal theme') (This is only shown if indoor=room|indoor=area|indoor=corridor)"
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'ref' (in the mapcomplete.org theme 'Personal theme') (This is only shown if indoor=room|indoor=area|indoor=corridor)"
 | 
				
			||||||
| 
						 | 
					@ -8391,6 +8425,129 @@
 | 
				
			||||||
      "key": "name",
 | 
					      "key": "name",
 | 
				
			||||||
      "description": "Layer 'Indoors' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Personal theme') (This is only shown if indoor=room|indoor=area|indoor=corridor)"
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Personal theme') (This is only shown if indoor=room|indoor=area|indoor=corridor)"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=administration with a fixed text, namely 'This is a administrative room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "administration"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=auditorium with a fixed text, namely 'This is a auditorium' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "auditorium"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=bedroom with a fixed text, namely 'This is a bedroom' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "bedroom"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=chapel with a fixed text, namely 'This is a chapel' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "chapel"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=class with a fixed text, namely 'This is a classroom' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "class"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=classroom with a fixed text, namely 'This is a classroom' (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "classroom"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=computer with a fixed text, namely 'This is a computer room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "computer"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=conference with a fixed text, namely 'This is a conference room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "conference"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=crypt with a fixed text, namely 'This is a crypt' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "crypt"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=kitchen with a fixed text, namely 'This is a kitchen' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "kitchen"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=laboratory with a fixed text, namely 'This is a laboratory' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "laboratory"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=library with a fixed text, namely 'This is a library' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "library"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=locker with a fixed text, namely 'This is a locker room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "locker"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=nursery with a fixed text, namely 'This is a nursery' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "nursery"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=office with a fixed text, namely 'This is an office' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "office"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=prison_cell with a fixed text, namely 'This is a prison_cell' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "prison_cell"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=restaurant with a fixed text, namely 'This is a restaurant' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "restaurant"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=security_check with a fixed text, namely 'This is a room to perform security checks' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "security_check"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=sport with a fixed text, namely 'This is a sport room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "sport"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=storage with a fixed text, namely 'This is a storage room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "storage"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=technical with a fixed text, namely 'This is a technical room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "technical"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=toilets with a fixed text, namely 'These are toilets' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "toilets"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "room",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows room=waiting with a fixed text, namely 'This is a waiting room' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "waiting"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "capacity",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'capacity' (in the mapcomplete.org theme 'Personal theme') (This is only shown if room=waiting|room=restaurant|room=office|room=nursery|room=conference|room=auditorium|room=chapel|room=bedroom|room=classroom)"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "name:etymology:wikidata",
 | 
				
			||||||
 | 
					      "description": "Layer 'Indoors' shows and asks freeform values for key 'name:etymology:wikidata' (in the mapcomplete.org theme 'Personal theme') (This is only shown if name:etymology!=unknown)"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "information",
 | 
					      "key": "information",
 | 
				
			||||||
      "description": "The MapComplete theme Personal theme has a layer Information boards showing features with this tag",
 | 
					      "description": "The MapComplete theme Personal theme has a layer Information boards showing features with this tag",
 | 
				
			||||||
| 
						 | 
					@ -12686,6 +12843,16 @@
 | 
				
			||||||
      "key": "wikipedia",
 | 
					      "key": "wikipedia",
 | 
				
			||||||
      "description": "The layer 'Surveillance camera's 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 'Surveillance camera's 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": "surveillance:type",
 | 
				
			||||||
 | 
					      "description": "Layer 'Surveillance camera's' shows surveillance:type=camera with a fixed text, namely 'This is a camera without number plate recognition.' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "camera"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "surveillance:type",
 | 
				
			||||||
 | 
					      "description": "Layer 'Surveillance camera's' shows surveillance:type=ALPR with a fixed text, namely 'This is an ALPR (Automatic License Plate Reader)' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
 | 
					      "value": "ALPR"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "camera:type",
 | 
					      "key": "camera:type",
 | 
				
			||||||
      "description": "Layer 'Surveillance camera's' shows camera:type=fixed with a fixed text, namely 'A fixed (non-moving) camera' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
					      "description": "Layer 'Surveillance camera's' shows camera:type=fixed with a fixed text, namely 'A fixed (non-moving) camera' and allows to pick this as a default answer (in the mapcomplete.org theme 'Personal theme')",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,35 +114,6 @@
 | 
				
			||||||
      "key": "wikipedia",
 | 
					      "key": "wikipedia",
 | 
				
			||||||
      "description": "The layer 'Dog friendly eateries 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 'Dog friendly eateries 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": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Dog friendly eateries' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "location",
 | 
					 | 
				
			||||||
      "description": "Layer 'Dog friendly eateries' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
					 | 
				
			||||||
      "value": "underground"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Dog friendly eateries' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
					 | 
				
			||||||
      "value": "0"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Dog friendly eateries' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities') Picking this answer will delete the key level.",
 | 
					 | 
				
			||||||
      "value": ""
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Dog friendly eateries' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
					 | 
				
			||||||
      "value": "1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      "key": "level",
 | 
					 | 
				
			||||||
      "description": "Layer 'Dog friendly eateries' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
					 | 
				
			||||||
      "value": "-1"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "name",
 | 
					      "key": "name",
 | 
				
			||||||
      "description": "Layer 'Dog friendly eateries' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')"
 | 
					      "description": "Layer 'Dog friendly eateries' shows and asks freeform values for key 'name' (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')"
 | 
				
			||||||
| 
						 | 
					@ -200,6 +171,35 @@
 | 
				
			||||||
      "description": "Layer 'Dog friendly eateries' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
					      "description": "Layer 'Dog friendly eateries' shows payment:qr_code=yes with a fixed text, namely 'Payment by QR-code is possible here' and allows to pick this as a default answer (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
				
			||||||
      "value": "yes"
 | 
					      "value": "yes"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Dog friendly eateries' shows and asks freeform values for key 'level' (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "location",
 | 
				
			||||||
 | 
					      "description": "Layer 'Dog friendly eateries' shows location=underground with a fixed text, namely 'Located underground' (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
				
			||||||
 | 
					      "value": "underground"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Dog friendly eateries' shows level=0 with a fixed text, namely 'Located on the ground floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
				
			||||||
 | 
					      "value": "0"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Dog friendly eateries' shows  with a fixed text, namely 'Located on the ground floor' (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities') Picking this answer will delete the key level.",
 | 
				
			||||||
 | 
					      "value": ""
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Dog friendly eateries' shows level=1 with a fixed text, namely 'Located on the first floor' and allows to pick this as a default answer (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
				
			||||||
 | 
					      "value": "1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "level",
 | 
				
			||||||
 | 
					      "description": "Layer 'Dog friendly eateries' shows level=-1 with a fixed text, namely 'Located on the first basement level' and allows to pick this as a default answer (in the mapcomplete.org theme 'Veterinarians, dog parks and other pet-amenities')",
 | 
				
			||||||
 | 
					      "value": "-1"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "wheelchair",
 | 
					      "key": "wheelchair",
 | 
				
			||||||
      "description": "Layer 'Dog friendly eateries' 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 'Veterinarians, dog parks and other pet-amenities')",
 | 
					      "description": "Layer 'Dog friendly eateries' 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 'Veterinarians, dog parks and other pet-amenities')",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -340,9 +340,14 @@
 | 
				
			||||||
      "description": "Layer 'Benches' shows tourism=artwork with a fixed text, namely 'This bench has an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Playgrounds')",
 | 
					      "description": "Layer 'Benches' shows tourism=artwork with a fixed text, namely 'This bench has an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Playgrounds')",
 | 
				
			||||||
      "value": "artwork"
 | 
					      "value": "artwork"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "not:tourism:artwork",
 | 
				
			||||||
 | 
					      "description": "Layer 'Benches' shows not:tourism:artwork=yes with a fixed text, namely 'This bench does not have an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Playgrounds')",
 | 
				
			||||||
 | 
					      "value": "yes"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "tourism",
 | 
					      "key": "tourism",
 | 
				
			||||||
      "description": "Layer 'Benches' shows  with a fixed text, namely 'This bench does not have an integrated artwork' and allows to pick this as a default answer (in the mapcomplete.org theme 'Playgrounds') Picking this answer will delete the key tourism.",
 | 
					      "description": "Layer 'Benches' shows  with a fixed text, namely 'This bench <span class=\"subtle\">probably</span> doesn't have an integrated artwork' (in the mapcomplete.org theme 'Playgrounds') Picking this answer will delete the key tourism.",
 | 
				
			||||||
      "value": ""
 | 
					      "value": ""
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,16 @@
 | 
				
			||||||
      "key": "wikipedia",
 | 
					      "key": "wikipedia",
 | 
				
			||||||
      "description": "The layer 'Surveillance camera's 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 'Surveillance camera's 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": "surveillance:type",
 | 
				
			||||||
 | 
					      "description": "Layer 'Surveillance camera's' shows surveillance:type=camera with a fixed text, namely 'This is a camera without number plate recognition.' and allows to pick this as a default answer (in the mapcomplete.org theme 'Surveillance under Surveillance')",
 | 
				
			||||||
 | 
					      "value": "camera"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "key": "surveillance:type",
 | 
				
			||||||
 | 
					      "description": "Layer 'Surveillance camera's' shows surveillance:type=ALPR with a fixed text, namely 'This is an ALPR (Automatic License Plate Reader)' and allows to pick this as a default answer (in the mapcomplete.org theme 'Surveillance under Surveillance')",
 | 
				
			||||||
 | 
					      "value": "ALPR"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "key": "camera:type",
 | 
					      "key": "camera:type",
 | 
				
			||||||
      "description": "Layer 'Surveillance camera's' shows camera:type=fixed with a fixed text, namely 'A fixed (non-moving) camera' and allows to pick this as a default answer (in the mapcomplete.org theme 'Surveillance under Surveillance')",
 | 
					      "description": "Layer 'Surveillance camera's' shows camera:type=fixed with a fixed text, namely 'A fixed (non-moving) camera' and allows to pick this as a default answer (in the mapcomplete.org theme 'Surveillance under Surveillance')",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -346,7 +346,7 @@ This documentation is defined in the source code at [FeatureSwitchState.ts](/src
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L199)
 | 
					This documentation is defined in the source code at [FeatureSwitchState.ts](/src/Logic/State/FeatureSwitchState.ts#L199)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 The default value is _osm_
 | 
					 No default value set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5294,4 +5294,4 @@
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "neededChangesets": 10
 | 
					    "neededChangesets": 10
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,2 +1,2 @@
 | 
				
			||||||
SPDX-FileCopyrightText: OpenClipArt
 | 
					SPDX-FileCopyrightText: OpenClipArt
 | 
				
			||||||
SPDX-License-Identifier: PD
 | 
					SPDX-License-Identifier: PUBLIC-DOMAIN
 | 
				
			||||||
| 
						 | 
					@ -1,2 +1,2 @@
 | 
				
			||||||
SPDX-FileCopyrightText:  	NPS Graphics, converted by User:ZyMOS
 | 
					SPDX-FileCopyrightText:  	NPS Graphics, converted by User:ZyMOS
 | 
				
			||||||
SPDX-License-Identifier: PD
 | 
					SPDX-License-Identifier: PUBLIC-DOMAIN
 | 
				
			||||||
							
								
								
									
										2
									
								
								assets/svg/mangrove_logo.svg.license
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								assets/svg/mangrove_logo.svg.license
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					SPDX-FileCopyrightText: Mangrove.reviews
 | 
				
			||||||
 | 
					SPDX-License-Identifier: LicenseRef-LOGO
 | 
				
			||||||
							
								
								
									
										16
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										16
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -1,12 +1,12 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  "name": "mapcomplete",
 | 
					  "name": "mapcomplete",
 | 
				
			||||||
  "version": "0.33.1",
 | 
					  "version": "0.33.5",
 | 
				
			||||||
  "lockfileVersion": 2,
 | 
					  "lockfileVersion": 2,
 | 
				
			||||||
  "requires": true,
 | 
					  "requires": true,
 | 
				
			||||||
  "packages": {
 | 
					  "packages": {
 | 
				
			||||||
    "": {
 | 
					    "": {
 | 
				
			||||||
      "name": "mapcomplete",
 | 
					      "name": "mapcomplete",
 | 
				
			||||||
      "version": "0.33.1",
 | 
					      "version": "0.33.5",
 | 
				
			||||||
      "license": "GPL-3.0-or-later",
 | 
					      "license": "GPL-3.0-or-later",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "@rgossiaux/svelte-headlessui": "^1.0.2",
 | 
					        "@rgossiaux/svelte-headlessui": "^1.0.2",
 | 
				
			||||||
| 
						 | 
					@ -4970,9 +4970,9 @@
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/caniuse-lite": {
 | 
					    "node_modules/caniuse-lite": {
 | 
				
			||||||
      "version": "1.0.30001538",
 | 
					      "version": "1.0.30001541",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001541.tgz",
 | 
				
			||||||
      "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==",
 | 
					      "integrity": "sha512-bLOsqxDgTqUBkzxbNlSBt8annkDpQB9NdzdTbO2ooJ+eC/IQcvDspDc058g84ejCelF7vHUx57KIOjEecOHXaw==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "funding": [
 | 
					      "funding": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					@ -17021,9 +17021,9 @@
 | 
				
			||||||
      "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
 | 
					      "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "caniuse-lite": {
 | 
					    "caniuse-lite": {
 | 
				
			||||||
      "version": "1.0.30001538",
 | 
					      "version": "1.0.30001541",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001541.tgz",
 | 
				
			||||||
      "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==",
 | 
					      "integrity": "sha512-bLOsqxDgTqUBkzxbNlSBt8annkDpQB9NdzdTbO2ooJ+eC/IQcvDspDc058g84ejCelF7vHUx57KIOjEecOHXaw==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "canvg": {
 | 
					    "canvg": {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,6 @@
 | 
				
			||||||
  "main": "index.ts",
 | 
					  "main": "index.ts",
 | 
				
			||||||
  "type": "module",
 | 
					  "type": "module",
 | 
				
			||||||
  "config": {
 | 
					  "config": {
 | 
				
			||||||
    "#": "Various endpoints that are instance-specific. This is the default configuration, which is re-exported in 'Constants.ts'.",
 | 
					 | 
				
			||||||
    "#": "Use MAPCOMPLETE_CONFIGURATION to use an additional configuration, e.g. `MAPCOMPLETE_CONFIGURATION=config_hetzner`",
 | 
					    "#": "Use MAPCOMPLETE_CONFIGURATION to use an additional configuration, e.g. `MAPCOMPLETE_CONFIGURATION=config_hetzner`",
 | 
				
			||||||
    "#oauth_credentials:comment": [
 | 
					    "#oauth_credentials:comment": [
 | 
				
			||||||
      "`oauth_credentials` are the OAuth-2 credentials for the production-OSM server and the test-server.",
 | 
					      "`oauth_credentials` are the OAuth-2 credentials for the production-OSM server and the test-server.",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
import { Store, UIEventSource } from "../UIEventSource";
 | 
					import { Store, UIEventSource } from "../UIEventSource"
 | 
				
			||||||
import { RasterLayerPolygon } from "../../Models/RasterLayers";
 | 
					import { RasterLayerPolygon } from "../../Models/RasterLayers"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Selects the appropriate raster layer as background for the given query parameter, theme setting, user preference or default value.
 | 
					 * Selects the appropriate raster layer as background for the given query parameter, theme setting, user preference or default value.
 | 
				
			||||||
| 
						 | 
					@ -7,40 +7,47 @@ import { RasterLayerPolygon } from "../../Models/RasterLayers";
 | 
				
			||||||
 * It the requested layer is not available, a layer of the same type will be selected.
 | 
					 * It the requested layer is not available, a layer of the same type will be selected.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class PreferredRasterLayerSelector {
 | 
					export class PreferredRasterLayerSelector {
 | 
				
			||||||
    private readonly _rasterLayerSetting: UIEventSource<RasterLayerPolygon>;
 | 
					    private readonly _rasterLayerSetting: UIEventSource<RasterLayerPolygon>
 | 
				
			||||||
    private readonly _availableLayers: Store<RasterLayerPolygon[]>;
 | 
					    private readonly _availableLayers: Store<RasterLayerPolygon[]>
 | 
				
			||||||
    private readonly _preferredBackgroundLayer: UIEventSource<string | "photo" | "map" | "osmbasedmap" | undefined>;
 | 
					    private readonly _preferredBackgroundLayer: UIEventSource<
 | 
				
			||||||
    private readonly _queryParameter: UIEventSource<string>;
 | 
					        string | "photo" | "map" | "osmbasedmap" | undefined
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					    private readonly _queryParameter: UIEventSource<string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(rasterLayerSetting: UIEventSource<RasterLayerPolygon>, availableLayers: Store<RasterLayerPolygon[]>, queryParameter: UIEventSource<string>, preferredBackgroundLayer: UIEventSource<string | "photo" | "map" | "osmbasedmap" | undefined>) {
 | 
					    constructor(
 | 
				
			||||||
        this._rasterLayerSetting = rasterLayerSetting;
 | 
					        rasterLayerSetting: UIEventSource<RasterLayerPolygon>,
 | 
				
			||||||
        this._availableLayers = availableLayers;
 | 
					        availableLayers: Store<RasterLayerPolygon[]>,
 | 
				
			||||||
        this._queryParameter = queryParameter;
 | 
					        queryParameter: UIEventSource<string>,
 | 
				
			||||||
        this._preferredBackgroundLayer = preferredBackgroundLayer;
 | 
					        preferredBackgroundLayer: UIEventSource<
 | 
				
			||||||
        const self = this;
 | 
					            string | "photo" | "map" | "osmbasedmap" | undefined
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        this._rasterLayerSetting = rasterLayerSetting
 | 
				
			||||||
 | 
					        this._availableLayers = availableLayers
 | 
				
			||||||
 | 
					        this._queryParameter = queryParameter
 | 
				
			||||||
 | 
					        this._preferredBackgroundLayer = preferredBackgroundLayer
 | 
				
			||||||
 | 
					        const self = this
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this._rasterLayerSetting.addCallbackD(layer => {
 | 
					        this._rasterLayerSetting.addCallbackD((layer) => {
 | 
				
			||||||
            if (layer.properties.id !== this._queryParameter.data) {
 | 
					            if (layer.properties.id !== this._queryParameter.data) {
 | 
				
			||||||
                this._queryParameter.setData(undefined);
 | 
					                this._queryParameter.setData(undefined)
 | 
				
			||||||
                return true;
 | 
					                return true
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this._queryParameter.addCallbackAndRunD((_) => {
 | 
				
			||||||
        this._queryParameter.addCallbackAndRunD(_ => {
 | 
					            const isApplied = self.updateLayer()
 | 
				
			||||||
            const isApplied = self.updateLayer();
 | 
					 | 
				
			||||||
            if (!isApplied) {
 | 
					            if (!isApplied) {
 | 
				
			||||||
                // A different layer was set as background
 | 
					                // A different layer was set as background
 | 
				
			||||||
                // We remove this queryParameter instead
 | 
					                // We remove this queryParameter instead
 | 
				
			||||||
                self._queryParameter.setData(undefined);
 | 
					                self._queryParameter.setData(undefined)
 | 
				
			||||||
                return true; // Unregister
 | 
					                return true // Unregister
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this._preferredBackgroundLayer.addCallbackD(_ => self.updateLayer());
 | 
					        this._preferredBackgroundLayer.addCallbackD((_) => self.updateLayer())
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this._availableLayers.addCallbackD(_ => self.updateLayer());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this._availableLayers.addCallbackD((_) => self.updateLayer())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -48,20 +55,19 @@ export class PreferredRasterLayerSelector {
 | 
				
			||||||
     * @private
 | 
					     * @private
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private updateLayer() {
 | 
					    private updateLayer() {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // What is the ID of the layer we have to (try to) load?
 | 
					        // What is the ID of the layer we have to (try to) load?
 | 
				
			||||||
        const targetLayerId = this._queryParameter.data ?? this._preferredBackgroundLayer.data;
 | 
					        const targetLayerId = this._queryParameter.data ?? this._preferredBackgroundLayer.data
 | 
				
			||||||
        const available = this._availableLayers.data;
 | 
					        const available = this._availableLayers.data
 | 
				
			||||||
        const isCategory = targetLayerId === "photo" || targetLayerId === "osmbasedmap" || targetLayerId === "map"
 | 
					        const isCategory =
 | 
				
			||||||
        const foundLayer = isCategory ? available.find(l => l.properties.category === targetLayerId) : available.find(l => l.properties.id === targetLayerId);
 | 
					            targetLayerId === "photo" || targetLayerId === "osmbasedmap" || targetLayerId === "map"
 | 
				
			||||||
 | 
					        const foundLayer = isCategory
 | 
				
			||||||
 | 
					            ? available.find((l) => l.properties.category === targetLayerId)
 | 
				
			||||||
 | 
					            : available.find((l) => l.properties.id === targetLayerId)
 | 
				
			||||||
        if (foundLayer) {
 | 
					        if (foundLayer) {
 | 
				
			||||||
            this._rasterLayerSetting.setData(foundLayer);
 | 
					            this._rasterLayerSetting.setData(foundLayer)
 | 
				
			||||||
            return true;
 | 
					            return true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // The current layer is not in view
 | 
					        // The current layer is not in view
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,159 +1,159 @@
 | 
				
			||||||
import { ImageUploader } from "./ImageUploader";
 | 
					import { ImageUploader } from "./ImageUploader"
 | 
				
			||||||
import LinkImageAction from "../Osm/Actions/LinkImageAction";
 | 
					import LinkImageAction from "../Osm/Actions/LinkImageAction"
 | 
				
			||||||
import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore";
 | 
					import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore"
 | 
				
			||||||
import { OsmId, OsmTags } from "../../Models/OsmFeature";
 | 
					import { OsmId, OsmTags } from "../../Models/OsmFeature"
 | 
				
			||||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
 | 
					import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
 | 
				
			||||||
import { Store, UIEventSource } from "../UIEventSource";
 | 
					import { Store, UIEventSource } from "../UIEventSource"
 | 
				
			||||||
import { OsmConnection } from "../Osm/OsmConnection";
 | 
					import { OsmConnection } from "../Osm/OsmConnection"
 | 
				
			||||||
import { Changes } from "../Osm/Changes";
 | 
					import { Changes } from "../Osm/Changes"
 | 
				
			||||||
import Translations from "../../UI/i18n/Translations";
 | 
					import Translations from "../../UI/i18n/Translations"
 | 
				
			||||||
import NoteCommentElement from "../../UI/Popup/NoteCommentElement";
 | 
					import NoteCommentElement from "../../UI/Popup/NoteCommentElement"
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The ImageUploadManager has a
 | 
					 * The ImageUploadManager has a
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class ImageUploadManager {
 | 
					export class ImageUploadManager {
 | 
				
			||||||
 | 
					    private readonly _uploader: ImageUploader
 | 
				
			||||||
 | 
					    private readonly _featureProperties: FeaturePropertiesStore
 | 
				
			||||||
 | 
					    private readonly _layout: LayoutConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private readonly _uploader: ImageUploader;
 | 
					    private readonly _uploadStarted: Map<string, UIEventSource<number>> = new Map()
 | 
				
			||||||
  private readonly _featureProperties: FeaturePropertiesStore;
 | 
					    private readonly _uploadFinished: Map<string, UIEventSource<number>> = new Map()
 | 
				
			||||||
  private readonly _layout: LayoutConfig;
 | 
					    private readonly _uploadFailed: Map<string, UIEventSource<number>> = new Map()
 | 
				
			||||||
 | 
					    private readonly _uploadRetried: Map<string, UIEventSource<number>> = new Map()
 | 
				
			||||||
 | 
					    private readonly _uploadRetriedSuccess: Map<string, UIEventSource<number>> = new Map()
 | 
				
			||||||
 | 
					    private readonly _osmConnection: OsmConnection
 | 
				
			||||||
 | 
					    private readonly _changes: Changes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private readonly _uploadStarted: Map<string, UIEventSource<number>> = new Map();
 | 
					    constructor(
 | 
				
			||||||
  private readonly _uploadFinished: Map<string, UIEventSource<number>> = new Map();
 | 
					        layout: LayoutConfig,
 | 
				
			||||||
  private readonly _uploadFailed: Map<string, UIEventSource<number>> = new Map();
 | 
					        uploader: ImageUploader,
 | 
				
			||||||
  private readonly _uploadRetried: Map<string, UIEventSource<number>> = new Map();
 | 
					        featureProperties: FeaturePropertiesStore,
 | 
				
			||||||
  private readonly _uploadRetriedSuccess: Map<string, UIEventSource<number>> = new Map();
 | 
					        osmConnection: OsmConnection,
 | 
				
			||||||
  private readonly _osmConnection: OsmConnection;
 | 
					        changes: Changes
 | 
				
			||||||
  private readonly _changes: Changes;
 | 
					    ) {
 | 
				
			||||||
 | 
					        this._uploader = uploader
 | 
				
			||||||
  constructor(layout: LayoutConfig, uploader: ImageUploader, featureProperties: FeaturePropertiesStore, osmConnection: OsmConnection, changes: Changes) {
 | 
					        this._featureProperties = featureProperties
 | 
				
			||||||
    this._uploader = uploader;
 | 
					        this._layout = layout
 | 
				
			||||||
    this._featureProperties = featureProperties;
 | 
					        this._osmConnection = osmConnection
 | 
				
			||||||
    this._layout = layout;
 | 
					        this._changes = changes
 | 
				
			||||||
    this._osmConnection = osmConnection;
 | 
					 | 
				
			||||||
    this._changes = changes;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Gets various counters.
 | 
					 | 
				
			||||||
   * Note that counters can only increase
 | 
					 | 
				
			||||||
   * If a retry was a success, both 'retrySuccess' _and_ 'uploadFinished' will be increased
 | 
					 | 
				
			||||||
   * @param featureId: the id of the feature you want information for. '*' has a global counter
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public getCountsFor(featureId: string | "*"): {
 | 
					 | 
				
			||||||
    retried: Store<number>;
 | 
					 | 
				
			||||||
    uploadStarted: Store<number>;
 | 
					 | 
				
			||||||
    retrySuccess: Store<number>;
 | 
					 | 
				
			||||||
    failed: Store<number>;
 | 
					 | 
				
			||||||
    uploadFinished: Store<number>
 | 
					 | 
				
			||||||
  } {
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
      uploadStarted: this.getCounterFor(this._uploadStarted, featureId),
 | 
					 | 
				
			||||||
      uploadFinished: this.getCounterFor(this._uploadFinished, featureId),
 | 
					 | 
				
			||||||
      retried: this.getCounterFor(this._uploadRetried, featureId),
 | 
					 | 
				
			||||||
      failed: this.getCounterFor(this._uploadFailed, featureId),
 | 
					 | 
				
			||||||
      retrySuccess: this.getCounterFor(this._uploadRetriedSuccess, featureId)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Uploads the given image, applies the correct title and license for the known user.
 | 
					 | 
				
			||||||
   * Will then add this image to the OSM-feature or the OSM-note
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  public async uploadImageAndApply(file: File, tagsStore: UIEventSource<OsmTags>) : Promise<void>{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const sizeInBytes = file.size;
 | 
					 | 
				
			||||||
    const tags= tagsStore.data
 | 
					 | 
				
			||||||
    const featureId = <OsmId>tags.id;
 | 
					 | 
				
			||||||
    const self = this;
 | 
					 | 
				
			||||||
    if (sizeInBytes > this._uploader.maxFileSizeInMegabytes * 1000000) {
 | 
					 | 
				
			||||||
      this.increaseCountFor(this._uploadStarted, featureId);
 | 
					 | 
				
			||||||
      this.increaseCountFor(this._uploadFailed, featureId);
 | 
					 | 
				
			||||||
      throw (
 | 
					 | 
				
			||||||
        Translations.t.image.toBig.Subs({
 | 
					 | 
				
			||||||
          actual_size: Math.floor(sizeInBytes / 1000000) + "MB",
 | 
					 | 
				
			||||||
          max_size: self._uploader.maxFileSizeInMegabytes + "MB"
 | 
					 | 
				
			||||||
        }).txt
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
    const licenseStore = this._osmConnection?.GetPreference("pictures-license", "CC0");
 | 
					     * Gets various counters.
 | 
				
			||||||
    const license = licenseStore?.data ?? "CC0";
 | 
					     * Note that counters can only increase
 | 
				
			||||||
 | 
					     * If a retry was a success, both 'retrySuccess' _and_ 'uploadFinished' will be increased
 | 
				
			||||||
    const matchingLayer = this._layout?.getMatchingLayer(tags);
 | 
					     * @param featureId: the id of the feature you want information for. '*' has a global counter
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    const title =
 | 
					    public getCountsFor(featureId: string | "*"): {
 | 
				
			||||||
      matchingLayer?.title?.GetRenderValue(tags)?.Subs(tags)?.textFor("en") ??
 | 
					        retried: Store<number>
 | 
				
			||||||
      tags.name ??
 | 
					        uploadStarted: Store<number>
 | 
				
			||||||
      "https//osm.org/" + tags.id;
 | 
					        retrySuccess: Store<number>
 | 
				
			||||||
    const description = [
 | 
					        failed: Store<number>
 | 
				
			||||||
      "author:" + this._osmConnection.userDetails.data.name,
 | 
					        uploadFinished: Store<number>
 | 
				
			||||||
      "license:" + license,
 | 
					    } {
 | 
				
			||||||
      "osmid:" + tags.id
 | 
					        return {
 | 
				
			||||||
    ].join("\n");
 | 
					            uploadStarted: this.getCounterFor(this._uploadStarted, featureId),
 | 
				
			||||||
 | 
					            uploadFinished: this.getCounterFor(this._uploadFinished, featureId),
 | 
				
			||||||
    console.log("Upload done, creating ");
 | 
					            retried: this.getCounterFor(this._uploadRetried, featureId),
 | 
				
			||||||
    const action = await this.uploadImageWithLicense(featureId, title, description, file);
 | 
					            failed: this.getCounterFor(this._uploadFailed, featureId),
 | 
				
			||||||
    if(!isNaN(Number( featureId))){
 | 
					            retrySuccess: this.getCounterFor(this._uploadRetriedSuccess, featureId),
 | 
				
			||||||
      // THis is a map note
 | 
					        }
 | 
				
			||||||
      const url = action._url
 | 
					 | 
				
			||||||
      await this._osmConnection.addCommentToNote(featureId, url)
 | 
					 | 
				
			||||||
      NoteCommentElement.addCommentTo(url, <UIEventSource<any>> tagsStore, {osmConnection: this._osmConnection})
 | 
					 | 
				
			||||||
      return
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    await this._changes.applyAction(action);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async uploadImageWithLicense(
 | 
					    /**
 | 
				
			||||||
    featureId: OsmId,
 | 
					     * Uploads the given image, applies the correct title and license for the known user.
 | 
				
			||||||
    title: string, description: string, blob: File
 | 
					     * Will then add this image to the OSM-feature or the OSM-note
 | 
				
			||||||
  ): Promise<LinkImageAction> {
 | 
					     */
 | 
				
			||||||
    this.increaseCountFor(this._uploadStarted, featureId);
 | 
					    public async uploadImageAndApply(file: File, tagsStore: UIEventSource<OsmTags>): Promise<void> {
 | 
				
			||||||
    const properties = this._featureProperties.getStore(featureId);
 | 
					        const sizeInBytes = file.size
 | 
				
			||||||
    let key: string;
 | 
					        const tags = tagsStore.data
 | 
				
			||||||
    let value: string;
 | 
					        const featureId = <OsmId>tags.id
 | 
				
			||||||
    try {
 | 
					        const self = this
 | 
				
			||||||
      ({ key, value } = await this._uploader.uploadImage(title, description, blob));
 | 
					        if (sizeInBytes > this._uploader.maxFileSizeInMegabytes * 1000000) {
 | 
				
			||||||
    } catch (e) {
 | 
					            this.increaseCountFor(this._uploadStarted, featureId)
 | 
				
			||||||
      this.increaseCountFor(this._uploadRetried, featureId);
 | 
					            this.increaseCountFor(this._uploadFailed, featureId)
 | 
				
			||||||
      console.error("Could not upload image, trying again:", e);
 | 
					            throw Translations.t.image.toBig.Subs({
 | 
				
			||||||
      try {
 | 
					                actual_size: Math.floor(sizeInBytes / 1000000) + "MB",
 | 
				
			||||||
 | 
					                max_size: self._uploader.maxFileSizeInMegabytes + "MB",
 | 
				
			||||||
 | 
					            }).txt
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ({ key, value } = await this._uploader.uploadImage(title, description, blob));
 | 
					        const licenseStore = this._osmConnection?.GetPreference("pictures-license", "CC0")
 | 
				
			||||||
        this.increaseCountFor(this._uploadRetriedSuccess, featureId);
 | 
					        const license = licenseStore?.data ?? "CC0"
 | 
				
			||||||
      } catch (e) {
 | 
					 | 
				
			||||||
        console.error("Could again not upload image due to", e);
 | 
					 | 
				
			||||||
        this.increaseCountFor(this._uploadFailed, featureId);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const matchingLayer = this._layout?.getMatchingLayer(tags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const title =
 | 
				
			||||||
 | 
					            matchingLayer?.title?.GetRenderValue(tags)?.Subs(tags)?.textFor("en") ??
 | 
				
			||||||
 | 
					            tags.name ??
 | 
				
			||||||
 | 
					            "https//osm.org/" + tags.id
 | 
				
			||||||
 | 
					        const description = [
 | 
				
			||||||
 | 
					            "author:" + this._osmConnection.userDetails.data.name,
 | 
				
			||||||
 | 
					            "license:" + license,
 | 
				
			||||||
 | 
					            "osmid:" + tags.id,
 | 
				
			||||||
 | 
					        ].join("\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        console.log("Upload done, creating ")
 | 
				
			||||||
 | 
					        const action = await this.uploadImageWithLicense(featureId, title, description, file)
 | 
				
			||||||
 | 
					        if (!isNaN(Number(featureId))) {
 | 
				
			||||||
 | 
					            // THis is a map note
 | 
				
			||||||
 | 
					            const url = action._url
 | 
				
			||||||
 | 
					            await this._osmConnection.addCommentToNote(featureId, url)
 | 
				
			||||||
 | 
					            NoteCommentElement.addCommentTo(url, <UIEventSource<any>>tagsStore, {
 | 
				
			||||||
 | 
					                osmConnection: this._osmConnection,
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        await this._changes.applyAction(action)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    console.log("Uploading done, creating action for", featureId);
 | 
					 | 
				
			||||||
    const action = new LinkImageAction(featureId, key, value, properties, {
 | 
					 | 
				
			||||||
      theme: this._layout.id,
 | 
					 | 
				
			||||||
      changeType: "add-image"
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    this.increaseCountFor(this._uploadFinished, featureId);
 | 
					 | 
				
			||||||
    return action;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private getCounterFor(collection: Map<string, UIEventSource<number>>, key: string | "*") {
 | 
					    private async uploadImageWithLicense(
 | 
				
			||||||
    if (this._featureProperties.aliases.has(key)) {
 | 
					        featureId: OsmId,
 | 
				
			||||||
      key = this._featureProperties.aliases.get(key);
 | 
					        title: string,
 | 
				
			||||||
 | 
					        description: string,
 | 
				
			||||||
 | 
					        blob: File
 | 
				
			||||||
 | 
					    ): Promise<LinkImageAction> {
 | 
				
			||||||
 | 
					        this.increaseCountFor(this._uploadStarted, featureId)
 | 
				
			||||||
 | 
					        const properties = this._featureProperties.getStore(featureId)
 | 
				
			||||||
 | 
					        let key: string
 | 
				
			||||||
 | 
					        let value: string
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            ;({ key, value } = await this._uploader.uploadImage(title, description, blob))
 | 
				
			||||||
 | 
					        } catch (e) {
 | 
				
			||||||
 | 
					            this.increaseCountFor(this._uploadRetried, featureId)
 | 
				
			||||||
 | 
					            console.error("Could not upload image, trying again:", e)
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                ;({ key, value } = await this._uploader.uploadImage(title, description, blob))
 | 
				
			||||||
 | 
					                this.increaseCountFor(this._uploadRetriedSuccess, featureId)
 | 
				
			||||||
 | 
					            } catch (e) {
 | 
				
			||||||
 | 
					                console.error("Could again not upload image due to", e)
 | 
				
			||||||
 | 
					                this.increaseCountFor(this._uploadFailed, featureId)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        console.log("Uploading done, creating action for", featureId)
 | 
				
			||||||
 | 
					        const action = new LinkImageAction(featureId, key, value, properties, {
 | 
				
			||||||
 | 
					            theme: this._layout.id,
 | 
				
			||||||
 | 
					            changeType: "add-image",
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        this.increaseCountFor(this._uploadFinished, featureId)
 | 
				
			||||||
 | 
					        return action
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!collection.has(key)) {
 | 
					
 | 
				
			||||||
      collection.set(key, new UIEventSource<number>(0));
 | 
					    private getCounterFor(collection: Map<string, UIEventSource<number>>, key: string | "*") {
 | 
				
			||||||
 | 
					        if (this._featureProperties.aliases.has(key)) {
 | 
				
			||||||
 | 
					            key = this._featureProperties.aliases.get(key)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!collection.has(key)) {
 | 
				
			||||||
 | 
					            collection.set(key, new UIEventSource<number>(0))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return collection.get(key)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return collection.get(key);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  private increaseCountFor(collection: Map<string, UIEventSource<number>>, key: string | "*") {
 | 
					 | 
				
			||||||
    const counter = this.getCounterFor(collection, key);
 | 
					 | 
				
			||||||
    counter.setData(counter.data + 1);
 | 
					 | 
				
			||||||
    const global = this.getCounterFor(collection, "*");
 | 
					 | 
				
			||||||
    global.setData(counter.data + 1);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private increaseCountFor(collection: Map<string, UIEventSource<number>>, key: string | "*") {
 | 
				
			||||||
 | 
					        const counter = this.getCounterFor(collection, key)
 | 
				
			||||||
 | 
					        counter.setData(counter.data + 1)
 | 
				
			||||||
 | 
					        const global = this.getCounterFor(collection, "*")
 | 
				
			||||||
 | 
					        global.setData(counter.data + 1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
export interface ImageUploader {
 | 
					export interface ImageUploader {
 | 
				
			||||||
  maxFileSizeInMegabytes?: number;
 | 
					    maxFileSizeInMegabytes?: number
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Uploads the 'blob' as image, with some metadata.
 | 
					     * Uploads the 'blob' as image, with some metadata.
 | 
				
			||||||
     * Returns the URL to be linked + the appropriate key to add this to OSM
 | 
					     * Returns the URL to be linked + the appropriate key to add this to OSM
 | 
				
			||||||
| 
						 | 
					@ -11,5 +11,5 @@ export interface ImageUploader {
 | 
				
			||||||
        title: string,
 | 
					        title: string,
 | 
				
			||||||
        description: string,
 | 
					        description: string,
 | 
				
			||||||
        blob: File
 | 
					        blob: File
 | 
				
			||||||
    ): Promise<{ key: string, value: string }>;
 | 
					    ): Promise<{ key: string; value: string }>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,15 @@
 | 
				
			||||||
import ImageProvider, { ProvidedImage } from "./ImageProvider";
 | 
					import ImageProvider, { ProvidedImage } from "./ImageProvider"
 | 
				
			||||||
import BaseUIElement from "../../UI/BaseUIElement";
 | 
					import BaseUIElement from "../../UI/BaseUIElement"
 | 
				
			||||||
import { Utils } from "../../Utils";
 | 
					import { Utils } from "../../Utils"
 | 
				
			||||||
import Constants from "../../Models/Constants";
 | 
					import Constants from "../../Models/Constants"
 | 
				
			||||||
import { LicenseInfo } from "./LicenseInfo";
 | 
					import { LicenseInfo } from "./LicenseInfo"
 | 
				
			||||||
import { ImageUploader } from "./ImageUploader";
 | 
					import { ImageUploader } from "./ImageUploader"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class Imgur extends ImageProvider implements ImageUploader{
 | 
					export class Imgur extends ImageProvider implements ImageUploader {
 | 
				
			||||||
    public static readonly defaultValuePrefix = ["https://i.imgur.com"]
 | 
					    public static readonly defaultValuePrefix = ["https://i.imgur.com"]
 | 
				
			||||||
    public static readonly singleton = new Imgur()
 | 
					    public static readonly singleton = new Imgur()
 | 
				
			||||||
    public readonly defaultKeyPrefixes: string[] = ["image"]
 | 
					    public readonly defaultKeyPrefixes: string[] = ["image"]
 | 
				
			||||||
    public readonly  maxFileSizeInMegabytes = 10
 | 
					    public readonly maxFileSizeInMegabytes = 10
 | 
				
			||||||
    private constructor() {
 | 
					    private constructor() {
 | 
				
			||||||
        super()
 | 
					        super()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ export class Imgur extends ImageProvider implements ImageUploader{
 | 
				
			||||||
        title: string,
 | 
					        title: string,
 | 
				
			||||||
        description: string,
 | 
					        description: string,
 | 
				
			||||||
        blob: File
 | 
					        blob: File
 | 
				
			||||||
    ): Promise<{ key: string, value: string }> {
 | 
					    ): Promise<{ key: string; value: string }> {
 | 
				
			||||||
        const apiUrl = "https://api.imgur.com/3/image"
 | 
					        const apiUrl = "https://api.imgur.com/3/image"
 | 
				
			||||||
        const apiKey = Constants.ImgurApiKey
 | 
					        const apiKey = Constants.ImgurApiKey
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,6 @@ export class Imgur extends ImageProvider implements ImageUploader{
 | 
				
			||||||
        formData.append("title", title)
 | 
					        formData.append("title", title)
 | 
				
			||||||
        formData.append("description", description)
 | 
					        formData.append("description", description)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        const settings: RequestInit = {
 | 
					        const settings: RequestInit = {
 | 
				
			||||||
            method: "POST",
 | 
					            method: "POST",
 | 
				
			||||||
            body: formData,
 | 
					            body: formData,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,15 @@
 | 
				
			||||||
import ChangeTagAction from "./ChangeTagAction";
 | 
					import ChangeTagAction from "./ChangeTagAction"
 | 
				
			||||||
import { Tag } from "../../Tags/Tag";
 | 
					import { Tag } from "../../Tags/Tag"
 | 
				
			||||||
import OsmChangeAction from "./OsmChangeAction";
 | 
					import OsmChangeAction from "./OsmChangeAction"
 | 
				
			||||||
import { Changes } from "../Changes";
 | 
					import { Changes } from "../Changes"
 | 
				
			||||||
import { ChangeDescription } from "./ChangeDescription";
 | 
					import { ChangeDescription } from "./ChangeDescription"
 | 
				
			||||||
import { Store } from "../../UIEventSource";
 | 
					import { Store } from "../../UIEventSource"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class LinkImageAction extends OsmChangeAction {
 | 
					export default class LinkImageAction extends OsmChangeAction {
 | 
				
			||||||
    private readonly _proposedKey: "image" | "mapillary" | "wiki_commons" | string;
 | 
					    private readonly _proposedKey: "image" | "mapillary" | "wiki_commons" | string
 | 
				
			||||||
    public readonly _url: string;
 | 
					    public readonly _url: string
 | 
				
			||||||
    private readonly _currentTags: Store<Record<string, string>>;
 | 
					    private readonly _currentTags: Store<Record<string, string>>
 | 
				
			||||||
    private readonly _meta: { theme: string; changeType: "add-image" | "link-image" };
 | 
					    private readonly _meta: { theme: string; changeType: "add-image" | "link-image" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Adds an image-link to a feature
 | 
					     * Adds an image-link to a feature
 | 
				
			||||||
| 
						 | 
					@ -31,10 +31,10 @@ export default class LinkImageAction extends OsmChangeAction {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        super(elementId, true)
 | 
					        super(elementId, true)
 | 
				
			||||||
        this._proposedKey = proposedKey;
 | 
					        this._proposedKey = proposedKey
 | 
				
			||||||
        this._url = url;
 | 
					        this._url = url
 | 
				
			||||||
        this._currentTags = currentTags;
 | 
					        this._currentTags = currentTags
 | 
				
			||||||
        this._meta = meta;
 | 
					        this._meta = meta
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected CreateChangeDescriptions(): Promise<ChangeDescription[]> {
 | 
					    protected CreateChangeDescriptions(): Promise<ChangeDescription[]> {
 | 
				
			||||||
| 
						 | 
					@ -46,9 +46,12 @@ export default class LinkImageAction extends OsmChangeAction {
 | 
				
			||||||
            key = this._proposedKey + ":" + i
 | 
					            key = this._proposedKey + ":" + i
 | 
				
			||||||
            i++
 | 
					            i++
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const tagChangeAction = new ChangeTagAction ( this.mainObjectId, new Tag(key, url), currentTags, this._meta)
 | 
					        const tagChangeAction = new ChangeTagAction(
 | 
				
			||||||
 | 
					            this.mainObjectId,
 | 
				
			||||||
 | 
					            new Tag(key, url),
 | 
				
			||||||
 | 
					            currentTags,
 | 
				
			||||||
 | 
					            this._meta
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
        return tagChangeAction.CreateChangeDescriptions()
 | 
					        return tagChangeAction.CreateChangeDescriptions()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ import Locale from "../../UI/i18n/Locale"
 | 
				
			||||||
import Constants from "../../Models/Constants"
 | 
					import Constants from "../../Models/Constants"
 | 
				
			||||||
import { Changes } from "./Changes"
 | 
					import { Changes } from "./Changes"
 | 
				
			||||||
import { Utils } from "../../Utils"
 | 
					import { Utils } from "../../Utils"
 | 
				
			||||||
import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore";
 | 
					import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ChangesetTag {
 | 
					export interface ChangesetTag {
 | 
				
			||||||
    key: string
 | 
					    key: string
 | 
				
			||||||
| 
						 | 
					@ -30,11 +30,14 @@ export class ChangesetHandler {
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        dryRun: Store<boolean>,
 | 
					        dryRun: Store<boolean>,
 | 
				
			||||||
        osmConnection: OsmConnection,
 | 
					        osmConnection: OsmConnection,
 | 
				
			||||||
        allElements: FeaturePropertiesStore |  { addAlias: (id0: string, id1: string) => void } | undefined,
 | 
					        allElements:
 | 
				
			||||||
 | 
					            | FeaturePropertiesStore
 | 
				
			||||||
 | 
					            | { addAlias: (id0: string, id1: string) => void }
 | 
				
			||||||
 | 
					            | undefined,
 | 
				
			||||||
        changes: Changes
 | 
					        changes: Changes
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        this.osmConnection = osmConnection
 | 
					        this.osmConnection = osmConnection
 | 
				
			||||||
        this.allElements = <FeaturePropertiesStore> allElements
 | 
					        this.allElements = <FeaturePropertiesStore>allElements
 | 
				
			||||||
        this.changes = changes
 | 
					        this.changes = changes
 | 
				
			||||||
        this._dryRun = dryRun
 | 
					        this._dryRun = dryRun
 | 
				
			||||||
        this.userDetails = osmConnection.userDetails
 | 
					        this.userDetails = osmConnection.userDetails
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -1,13 +1,13 @@
 | 
				
			||||||
import { UIEventSource } from "../UIEventSource";
 | 
					import { UIEventSource } from "../UIEventSource"
 | 
				
			||||||
import { LocalStorageSource } from "../Web/LocalStorageSource";
 | 
					import { LocalStorageSource } from "../Web/LocalStorageSource"
 | 
				
			||||||
import { QueryParameters } from "../Web/QueryParameters";
 | 
					import { QueryParameters } from "../Web/QueryParameters"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type GeolocationPermissionState = "prompt" | "requested" | "granted" | "denied"
 | 
					export type GeolocationPermissionState = "prompt" | "requested" | "granted" | "denied"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface GeoLocationPointProperties extends GeolocationCoordinates {
 | 
					export interface GeoLocationPointProperties extends GeolocationCoordinates {
 | 
				
			||||||
    id: "gps";
 | 
					    id: "gps"
 | 
				
			||||||
    "user:location": "yes";
 | 
					    "user:location": "yes"
 | 
				
			||||||
    date: string;
 | 
					    date: string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -23,22 +23,22 @@ export class GeoLocationState {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public readonly permission: UIEventSource<GeolocationPermissionState> = new UIEventSource(
 | 
					    public readonly permission: UIEventSource<GeolocationPermissionState> = new UIEventSource(
 | 
				
			||||||
        "prompt"
 | 
					        "prompt"
 | 
				
			||||||
    );
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Important to determine e.g. if we move automatically on fix or not
 | 
					     * Important to determine e.g. if we move automatically on fix or not
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public readonly requestMoment: UIEventSource<Date | undefined> = new UIEventSource(undefined);
 | 
					    public readonly requestMoment: UIEventSource<Date | undefined> = new UIEventSource(undefined)
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * If true: the map will center (and re-center) to this location
 | 
					     * If true: the map will center (and re-center) to this location
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public readonly allowMoving: UIEventSource<boolean> = new UIEventSource<boolean>(true);
 | 
					    public readonly allowMoving: UIEventSource<boolean> = new UIEventSource<boolean>(true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The latest GeoLocationCoordinates, as given by the WebAPI
 | 
					     * The latest GeoLocationCoordinates, as given by the WebAPI
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public readonly currentGPSLocation: UIEventSource<GeolocationCoordinates | undefined> =
 | 
					    public readonly currentGPSLocation: UIEventSource<GeolocationCoordinates | undefined> =
 | 
				
			||||||
        new UIEventSource<GeolocationCoordinates | undefined>(undefined);
 | 
					        new UIEventSource<GeolocationCoordinates | undefined>(undefined)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A small flag on localstorage. If the user previously granted the geolocation, it will be set.
 | 
					     * A small flag on localstorage. If the user previously granted the geolocation, it will be set.
 | 
				
			||||||
| 
						 | 
					@ -50,46 +50,46 @@ export class GeoLocationState {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private readonly _previousLocationGrant: UIEventSource<"true" | "false"> = <any>(
 | 
					    private readonly _previousLocationGrant: UIEventSource<"true" | "false"> = <any>(
 | 
				
			||||||
        LocalStorageSource.Get("geolocation-permissions")
 | 
					        LocalStorageSource.Get("geolocation-permissions")
 | 
				
			||||||
    );
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Used to detect a permission retraction
 | 
					     * Used to detect a permission retraction
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private readonly _grantedThisSession: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
					    private readonly _grantedThisSession: UIEventSource<boolean> = new UIEventSource<boolean>(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        const self = this;
 | 
					        const self = this
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.permission.addCallbackAndRunD(async (state) => {
 | 
					        this.permission.addCallbackAndRunD(async (state) => {
 | 
				
			||||||
            if (state === "granted") {
 | 
					            if (state === "granted") {
 | 
				
			||||||
                self._previousLocationGrant.setData("true");
 | 
					                self._previousLocationGrant.setData("true")
 | 
				
			||||||
                self._grantedThisSession.setData(true);
 | 
					                self._grantedThisSession.setData(true)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (state === "prompt" && self._grantedThisSession.data) {
 | 
					            if (state === "prompt" && self._grantedThisSession.data) {
 | 
				
			||||||
                // This is _really_ weird: we had a grant earlier, but it's 'prompt' now?
 | 
					                // This is _really_ weird: we had a grant earlier, but it's 'prompt' now?
 | 
				
			||||||
                // This means that the rights have been revoked again!
 | 
					                // This means that the rights have been revoked again!
 | 
				
			||||||
                self._previousLocationGrant.setData("false");
 | 
					                self._previousLocationGrant.setData("false")
 | 
				
			||||||
                self.permission.setData("denied");
 | 
					                self.permission.setData("denied")
 | 
				
			||||||
                self.currentGPSLocation.setData(undefined);
 | 
					                self.currentGPSLocation.setData(undefined)
 | 
				
			||||||
                console.warn("Detected a downgrade in permissions!");
 | 
					                console.warn("Detected a downgrade in permissions!")
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (state === "denied") {
 | 
					            if (state === "denied") {
 | 
				
			||||||
                self._previousLocationGrant.setData("false");
 | 
					                self._previousLocationGrant.setData("false")
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        })
 | 
				
			||||||
        console.log("Previous location grant:", this._previousLocationGrant.data);
 | 
					        console.log("Previous location grant:", this._previousLocationGrant.data)
 | 
				
			||||||
        if (this._previousLocationGrant.data === "true") {
 | 
					        if (this._previousLocationGrant.data === "true") {
 | 
				
			||||||
            // A previous visit successfully granted permission. Chance is high that we are allowed to use it again!
 | 
					            // A previous visit successfully granted permission. Chance is high that we are allowed to use it again!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // We set the flag to false again. If the user only wanted to share their location once, we are not gonna keep bothering them
 | 
					            // We set the flag to false again. If the user only wanted to share their location once, we are not gonna keep bothering them
 | 
				
			||||||
            this._previousLocationGrant.setData("false");
 | 
					            this._previousLocationGrant.setData("false")
 | 
				
			||||||
            console.log("Requesting access to GPS as this was previously granted");
 | 
					            console.log("Requesting access to GPS as this was previously granted")
 | 
				
			||||||
            const latLonGivenViaUrl =
 | 
					            const latLonGivenViaUrl =
 | 
				
			||||||
                QueryParameters.wasInitialized("lat") || QueryParameters.wasInitialized("lon");
 | 
					                QueryParameters.wasInitialized("lat") || QueryParameters.wasInitialized("lon")
 | 
				
			||||||
            if (!latLonGivenViaUrl) {
 | 
					            if (!latLonGivenViaUrl) {
 | 
				
			||||||
                this.requestMoment.setData(new Date());
 | 
					                this.requestMoment.setData(new Date())
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            this.requestPermission();
 | 
					            this.requestPermission()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,37 +101,36 @@ export class GeoLocationState {
 | 
				
			||||||
    public requestPermission() {
 | 
					    public requestPermission() {
 | 
				
			||||||
        if (typeof navigator === "undefined") {
 | 
					        if (typeof navigator === "undefined") {
 | 
				
			||||||
            // Not compatible with this browser
 | 
					            // Not compatible with this browser
 | 
				
			||||||
            this.permission.setData("denied");
 | 
					            this.permission.setData("denied")
 | 
				
			||||||
            return;
 | 
					            return
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (this.permission.data !== "prompt" && this.permission.data !== "requested") {
 | 
					        if (this.permission.data !== "prompt" && this.permission.data !== "requested") {
 | 
				
			||||||
            // If the user denies the first prompt, revokes the deny and then tries again, we have to run the flow as well
 | 
					            // If the user denies the first prompt, revokes the deny and then tries again, we have to run the flow as well
 | 
				
			||||||
            // Hence that we continue the flow if it is "requested"
 | 
					            // Hence that we continue the flow if it is "requested"
 | 
				
			||||||
            return;
 | 
					            return
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.permission.setData("requested");
 | 
					        this.permission.setData("requested")
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            navigator?.permissions
 | 
					            navigator?.permissions
 | 
				
			||||||
                ?.query({ name: "geolocation" })
 | 
					                ?.query({ name: "geolocation" })
 | 
				
			||||||
                .then((status) => {
 | 
					                .then((status) => {
 | 
				
			||||||
                    const self = this;
 | 
					                    const self = this
 | 
				
			||||||
                    if(status.state === "granted" || status.state === "denied"){
 | 
					                    if (status.state === "granted" || status.state === "denied") {
 | 
				
			||||||
                        self.permission.setData(status.state)
 | 
					                        self.permission.setData(status.state)
 | 
				
			||||||
                        return
 | 
					                        return
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    status.addEventListener("change", (e) => {
 | 
					                    status.addEventListener("change", (e) => {
 | 
				
			||||||
                        self.permission.setData(status.state);
 | 
					                        self.permission.setData(status.state)
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                    // The code above might have reset it to 'prompt', but we _did_ request permission!
 | 
					                    // The code above might have reset it to 'prompt', but we _did_ request permission!
 | 
				
			||||||
                    this.permission.setData("requested")
 | 
					                    this.permission.setData("requested")
 | 
				
			||||||
                    // We _must_ call 'startWatching', as that is the actual trigger for the popup...
 | 
					                    // We _must_ call 'startWatching', as that is the actual trigger for the popup...
 | 
				
			||||||
                    self.startWatching();
 | 
					                    self.startWatching()
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .catch((e) => console.error("Could not get geopermission", e));
 | 
					                .catch((e) => console.error("Could not get geopermission", e))
 | 
				
			||||||
        } catch (e) {
 | 
					        } catch (e) {
 | 
				
			||||||
            console.error("Could not get permission:", e);
 | 
					            console.error("Could not get permission:", e)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,18 +139,18 @@ export class GeoLocationState {
 | 
				
			||||||
     * @private
 | 
					     * @private
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private async startWatching() {
 | 
					    private async startWatching() {
 | 
				
			||||||
        const self = this;
 | 
					        const self = this
 | 
				
			||||||
        navigator.geolocation.watchPosition(
 | 
					        navigator.geolocation.watchPosition(
 | 
				
			||||||
            function(position) {
 | 
					            function (position) {
 | 
				
			||||||
                self.currentGPSLocation.setData(position.coords);
 | 
					                self.currentGPSLocation.setData(position.coords)
 | 
				
			||||||
                self._previousLocationGrant.setData("true");
 | 
					                self._previousLocationGrant.setData("true")
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            function() {
 | 
					            function () {
 | 
				
			||||||
                console.warn("Could not get location with navigator.geolocation");
 | 
					                console.warn("Could not get location with navigator.geolocation")
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                enableHighAccuracy: true
 | 
					                enableHighAccuracy: true,
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        );
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,23 +1,23 @@
 | 
				
			||||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
 | 
					import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
 | 
				
			||||||
import { OsmConnection } from "../Osm/OsmConnection";
 | 
					import { OsmConnection } from "../Osm/OsmConnection"
 | 
				
			||||||
import { MangroveIdentity } from "../Web/MangroveReviews";
 | 
					import { MangroveIdentity } from "../Web/MangroveReviews"
 | 
				
			||||||
import { Store, Stores, UIEventSource } from "../UIEventSource";
 | 
					import { Store, Stores, UIEventSource } from "../UIEventSource"
 | 
				
			||||||
import StaticFeatureSource from "../FeatureSource/Sources/StaticFeatureSource";
 | 
					import StaticFeatureSource from "../FeatureSource/Sources/StaticFeatureSource"
 | 
				
			||||||
import { FeatureSource } from "../FeatureSource/FeatureSource";
 | 
					import { FeatureSource } from "../FeatureSource/FeatureSource"
 | 
				
			||||||
import { Feature } from "geojson";
 | 
					import { Feature } from "geojson"
 | 
				
			||||||
import { Utils } from "../../Utils";
 | 
					import { Utils } from "../../Utils"
 | 
				
			||||||
import translators from "../../assets/translators.json";
 | 
					import translators from "../../assets/translators.json"
 | 
				
			||||||
import codeContributors from "../../assets/contributors.json";
 | 
					import codeContributors from "../../assets/contributors.json"
 | 
				
			||||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
 | 
					import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
 | 
				
			||||||
import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson";
 | 
					import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
 | 
				
			||||||
import usersettings from "../../../src/assets/generated/layers/usersettings.json";
 | 
					import usersettings from "../../../src/assets/generated/layers/usersettings.json"
 | 
				
			||||||
import Locale from "../../UI/i18n/Locale";
 | 
					import Locale from "../../UI/i18n/Locale"
 | 
				
			||||||
import LinkToWeblate from "../../UI/Base/LinkToWeblate";
 | 
					import LinkToWeblate from "../../UI/Base/LinkToWeblate"
 | 
				
			||||||
import FeatureSwitchState from "./FeatureSwitchState";
 | 
					import FeatureSwitchState from "./FeatureSwitchState"
 | 
				
			||||||
import Constants from "../../Models/Constants";
 | 
					import Constants from "../../Models/Constants"
 | 
				
			||||||
import { QueryParameters } from "../Web/QueryParameters";
 | 
					import { QueryParameters } from "../Web/QueryParameters"
 | 
				
			||||||
import { ThemeMetaTagging } from "./UserSettingsMetaTagging";
 | 
					import { ThemeMetaTagging } from "./UserSettingsMetaTagging"
 | 
				
			||||||
import { MapProperties } from "../../Models/MapProperties";
 | 
					import { MapProperties } from "../../Models/MapProperties"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The part of the state which keeps track of user-related stuff, e.g. the OSM-connection,
 | 
					 * The part of the state which keeps track of user-related stuff, e.g. the OSM-connection,
 | 
				
			||||||
| 
						 | 
					@ -42,8 +42,10 @@ export default class UserRelatedState {
 | 
				
			||||||
    public readonly fixateNorth: UIEventSource<undefined | "yes">
 | 
					    public readonly fixateNorth: UIEventSource<undefined | "yes">
 | 
				
			||||||
    public readonly homeLocation: FeatureSource
 | 
					    public readonly homeLocation: FeatureSource
 | 
				
			||||||
    public readonly language: UIEventSource<string>
 | 
					    public readonly language: UIEventSource<string>
 | 
				
			||||||
    public readonly preferredBackgroundLayer: UIEventSource<string | "photo" | "map" | "osmbasedmap" | undefined>
 | 
					    public readonly preferredBackgroundLayer: UIEventSource<
 | 
				
			||||||
    public readonly imageLicense : UIEventSource<string>
 | 
					        string | "photo" | "map" | "osmbasedmap" | undefined
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					    public readonly imageLicense: UIEventSource<string>
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The number of seconds that the GPS-locations are stored in memory.
 | 
					     * The number of seconds that the GPS-locations are stored in memory.
 | 
				
			||||||
     * Time in seconds
 | 
					     * Time in seconds
 | 
				
			||||||
| 
						 | 
					@ -61,7 +63,7 @@ export default class UserRelatedState {
 | 
				
			||||||
     * Note: these are linked via OsmConnection.preferences which exports all preferences as UIEventSource
 | 
					     * Note: these are linked via OsmConnection.preferences which exports all preferences as UIEventSource
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public readonly preferencesAsTags: UIEventSource<Record<string, string>>
 | 
					    public readonly preferencesAsTags: UIEventSource<Record<string, string>>
 | 
				
			||||||
    private readonly _mapProperties: MapProperties;
 | 
					    private readonly _mapProperties: MapProperties
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        osmConnection: OsmConnection,
 | 
					        osmConnection: OsmConnection,
 | 
				
			||||||
| 
						 | 
					@ -71,7 +73,7 @@ export default class UserRelatedState {
 | 
				
			||||||
        mapProperties?: MapProperties
 | 
					        mapProperties?: MapProperties
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        this.osmConnection = osmConnection
 | 
					        this.osmConnection = osmConnection
 | 
				
			||||||
        this._mapProperties = mapProperties;
 | 
					        this._mapProperties = mapProperties
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            const translationMode: UIEventSource<undefined | "true" | "false" | "mobile" | string> =
 | 
					            const translationMode: UIEventSource<undefined | "true" | "false" | "mobile" | string> =
 | 
				
			||||||
                this.osmConnection.GetPreference("translation-mode", "false")
 | 
					                this.osmConnection.GetPreference("translation-mode", "false")
 | 
				
			||||||
| 
						 | 
					@ -104,12 +106,17 @@ export default class UserRelatedState {
 | 
				
			||||||
        this.mangroveIdentity = new MangroveIdentity(
 | 
					        this.mangroveIdentity = new MangroveIdentity(
 | 
				
			||||||
            this.osmConnection.GetLongPreference("identity", "mangrove")
 | 
					            this.osmConnection.GetLongPreference("identity", "mangrove")
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        this.preferredBackgroundLayer= this.osmConnection.GetPreference("preferred-background-layer", undefined, {
 | 
					        this.preferredBackgroundLayer = this.osmConnection.GetPreference(
 | 
				
			||||||
            documentation: "The ID of a layer or layer category that MapComplete uses by default"
 | 
					            "preferred-background-layer",
 | 
				
			||||||
        })
 | 
					            undefined,
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                documentation:
 | 
				
			||||||
 | 
					                    "The ID of a layer or layer category that MapComplete uses by default",
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.imageLicense =  this.osmConnection.GetPreference("pictures-license", "CC0", {
 | 
					        this.imageLicense = this.osmConnection.GetPreference("pictures-license", "CC0", {
 | 
				
			||||||
            documentation: "The license under which new images are uploaded"
 | 
					            documentation: "The license under which new images are uploaded",
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        this.installedUserThemes = this.InitInstalledUserThemes()
 | 
					        this.installedUserThemes = this.InitInstalledUserThemes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -277,7 +284,6 @@ export default class UserRelatedState {
 | 
				
			||||||
            amendedPrefs.data["__url_parameter_initialized:" + key] = "yes"
 | 
					            amendedPrefs.data["__url_parameter_initialized:" + key] = "yes"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        const osmConnection = this.osmConnection
 | 
					        const osmConnection = this.osmConnection
 | 
				
			||||||
        osmConnection.preferencesHandler.preferences.addCallback((newPrefs) => {
 | 
					        osmConnection.preferencesHandler.preferences.addCallback((newPrefs) => {
 | 
				
			||||||
            for (const k in newPrefs) {
 | 
					            for (const k in newPrefs) {
 | 
				
			||||||
| 
						 | 
					@ -405,13 +411,11 @@ export default class UserRelatedState {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this._mapProperties?.rasterLayer?.addCallbackAndRun((l) => {
 | 
				
			||||||
        this._mapProperties?.rasterLayer?.addCallbackAndRun(l => {
 | 
					 | 
				
			||||||
            amendedPrefs.data["__current_background"] = l?.properties?.id
 | 
					            amendedPrefs.data["__current_background"] = l?.properties?.id
 | 
				
			||||||
            amendedPrefs.ping()
 | 
					            amendedPrefs.ping()
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return amendedPrefs
 | 
					        return amendedPrefs
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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(/</g,'<')?.replace(/>/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(/</g, "<")?.replace(/>/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"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,35 +1,34 @@
 | 
				
			||||||
import { ImmutableStore, Store, UIEventSource } from "../UIEventSource";
 | 
					import { ImmutableStore, Store, UIEventSource } from "../UIEventSource"
 | 
				
			||||||
import { MangroveReviews, Review } from "mangrove-reviews-typescript";
 | 
					import { MangroveReviews, Review } from "mangrove-reviews-typescript"
 | 
				
			||||||
import { Utils } from "../../Utils";
 | 
					import { Utils } from "../../Utils"
 | 
				
			||||||
import { Feature, Position } from "geojson";
 | 
					import { Feature, Position } from "geojson"
 | 
				
			||||||
import { GeoOperations } from "../GeoOperations";
 | 
					import { GeoOperations } from "../GeoOperations"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class MangroveIdentity {
 | 
					export class MangroveIdentity {
 | 
				
			||||||
    public readonly keypair: Store<CryptoKeyPair>;
 | 
					    public readonly keypair: Store<CryptoKeyPair>
 | 
				
			||||||
    public readonly key_id: Store<string>;
 | 
					    public readonly key_id: Store<string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(mangroveIdentity: UIEventSource<string>) {
 | 
					    constructor(mangroveIdentity: UIEventSource<string>) {
 | 
				
			||||||
        const key_id = new UIEventSource<string>(undefined);
 | 
					        const key_id = new UIEventSource<string>(undefined)
 | 
				
			||||||
        this.key_id = key_id;
 | 
					        this.key_id = key_id
 | 
				
			||||||
        const keypairEventSource = new UIEventSource<CryptoKeyPair>(undefined);
 | 
					        const keypairEventSource = new UIEventSource<CryptoKeyPair>(undefined)
 | 
				
			||||||
        this.keypair = keypairEventSource;
 | 
					        this.keypair = keypairEventSource
 | 
				
			||||||
        mangroveIdentity.addCallbackAndRunD(async (data) => {
 | 
					        mangroveIdentity.addCallbackAndRunD(async (data) => {
 | 
				
			||||||
            if (data === "") {
 | 
					            if (data === "") {
 | 
				
			||||||
                return;
 | 
					                return
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            const keypair = await MangroveReviews.jwkToKeypair(JSON.parse(data));
 | 
					            const keypair = await MangroveReviews.jwkToKeypair(JSON.parse(data))
 | 
				
			||||||
            keypairEventSource.setData(keypair);
 | 
					            keypairEventSource.setData(keypair)
 | 
				
			||||||
            const pem = await MangroveReviews.publicToPem(keypair.publicKey);
 | 
					            const pem = await MangroveReviews.publicToPem(keypair.publicKey)
 | 
				
			||||||
            key_id.setData(pem);
 | 
					            key_id.setData(pem)
 | 
				
			||||||
        });
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            if (!Utils.runningFromConsole && (mangroveIdentity.data ?? "") === "") {
 | 
					            if (!Utils.runningFromConsole && (mangroveIdentity.data ?? "") === "") {
 | 
				
			||||||
                MangroveIdentity.CreateIdentity(mangroveIdentity).then((_) => {
 | 
					                MangroveIdentity.CreateIdentity(mangroveIdentity).then((_) => {})
 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch (e) {
 | 
					        } catch (e) {
 | 
				
			||||||
            console.error("Could not create identity: ", e);
 | 
					            console.error("Could not create identity: ", e)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,13 +38,13 @@ export class MangroveIdentity {
 | 
				
			||||||
     * @constructor
 | 
					     * @constructor
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private static async CreateIdentity(identity: UIEventSource<string>): Promise<void> {
 | 
					    private static async CreateIdentity(identity: UIEventSource<string>): Promise<void> {
 | 
				
			||||||
        const keypair = await MangroveReviews.generateKeypair();
 | 
					        const keypair = await MangroveReviews.generateKeypair()
 | 
				
			||||||
        const jwk = await MangroveReviews.keypairToJwk(keypair);
 | 
					        const jwk = await MangroveReviews.keypairToJwk(keypair)
 | 
				
			||||||
        if ((identity.data ?? "") !== "") {
 | 
					        if ((identity.data ?? "") !== "") {
 | 
				
			||||||
            // Identity has been loaded via osmPreferences by now - we don't overwrite
 | 
					            // Identity has been loaded via osmPreferences by now - we don't overwrite
 | 
				
			||||||
            return;
 | 
					            return
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        identity.setData(JSON.stringify(jwk));
 | 
					        identity.setData(JSON.stringify(jwk))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,18 +52,18 @@ export class MangroveIdentity {
 | 
				
			||||||
 * Tracks all reviews of a given feature, allows to create a new review
 | 
					 * Tracks all reviews of a given feature, allows to create a new review
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class FeatureReviews {
 | 
					export default class FeatureReviews {
 | 
				
			||||||
    private static readonly _featureReviewsCache: Record<string, FeatureReviews> = {};
 | 
					    private static readonly _featureReviewsCache: Record<string, FeatureReviews> = {}
 | 
				
			||||||
    public readonly subjectUri: Store<string>;
 | 
					    public readonly subjectUri: Store<string>
 | 
				
			||||||
    public readonly average: Store<number | null>;
 | 
					    public readonly average: Store<number | null>
 | 
				
			||||||
    private readonly _reviews: UIEventSource<(Review & { madeByLoggedInUser: Store<boolean> })[]> =
 | 
					    private readonly _reviews: UIEventSource<(Review & { madeByLoggedInUser: Store<boolean> })[]> =
 | 
				
			||||||
        new UIEventSource([]);
 | 
					        new UIEventSource([])
 | 
				
			||||||
    public readonly reviews: Store<(Review & { madeByLoggedInUser: Store<boolean> })[]> =
 | 
					    public readonly reviews: Store<(Review & { madeByLoggedInUser: Store<boolean> })[]> =
 | 
				
			||||||
        this._reviews;
 | 
					        this._reviews
 | 
				
			||||||
    private readonly _lat: number;
 | 
					    private readonly _lat: number
 | 
				
			||||||
    private readonly _lon: number;
 | 
					    private readonly _lon: number
 | 
				
			||||||
    private readonly _uncertainty: number;
 | 
					    private readonly _uncertainty: number
 | 
				
			||||||
    private readonly _name: Store<string>;
 | 
					    private readonly _name: Store<string>
 | 
				
			||||||
    private readonly _identity: MangroveIdentity;
 | 
					    private readonly _identity: MangroveIdentity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private constructor(
 | 
					    private constructor(
 | 
				
			||||||
        feature: Feature,
 | 
					        feature: Feature,
 | 
				
			||||||
| 
						 | 
					@ -77,72 +76,72 @@ export default class FeatureReviews {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        const centerLonLat = GeoOperations.centerpointCoordinates(feature)
 | 
					        const centerLonLat = GeoOperations.centerpointCoordinates(feature)
 | 
				
			||||||
        ;[this._lon, this._lat] = centerLonLat;
 | 
					        ;[this._lon, this._lat] = centerLonLat
 | 
				
			||||||
        this._identity =
 | 
					        this._identity =
 | 
				
			||||||
            mangroveIdentity ?? new MangroveIdentity(new UIEventSource<string>(undefined));
 | 
					            mangroveIdentity ?? new MangroveIdentity(new UIEventSource<string>(undefined))
 | 
				
			||||||
        const nameKey = options?.nameKey ?? "name";
 | 
					        const nameKey = options?.nameKey ?? "name"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (feature.geometry.type === "Point") {
 | 
					        if (feature.geometry.type === "Point") {
 | 
				
			||||||
            this._uncertainty = options?.uncertaintyRadius ?? 10;
 | 
					            this._uncertainty = options?.uncertaintyRadius ?? 10
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            let coordss: Position[][];
 | 
					            let coordss: Position[][]
 | 
				
			||||||
            if (feature.geometry.type === "LineString") {
 | 
					            if (feature.geometry.type === "LineString") {
 | 
				
			||||||
                coordss = [feature.geometry.coordinates];
 | 
					                coordss = [feature.geometry.coordinates]
 | 
				
			||||||
            } else if (
 | 
					            } else if (
 | 
				
			||||||
                feature.geometry.type === "MultiLineString" ||
 | 
					                feature.geometry.type === "MultiLineString" ||
 | 
				
			||||||
                feature.geometry.type === "Polygon"
 | 
					                feature.geometry.type === "Polygon"
 | 
				
			||||||
            ) {
 | 
					            ) {
 | 
				
			||||||
                coordss = feature.geometry.coordinates;
 | 
					                coordss = feature.geometry.coordinates
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            let maxDistance = 0;
 | 
					            let maxDistance = 0
 | 
				
			||||||
            for (const coords of coordss) {
 | 
					            for (const coords of coordss) {
 | 
				
			||||||
                for (const coord of coords) {
 | 
					                for (const coord of coords) {
 | 
				
			||||||
                    maxDistance = Math.max(
 | 
					                    maxDistance = Math.max(
 | 
				
			||||||
                        maxDistance,
 | 
					                        maxDistance,
 | 
				
			||||||
                        GeoOperations.distanceBetween(centerLonLat, coord)
 | 
					                        GeoOperations.distanceBetween(centerLonLat, coord)
 | 
				
			||||||
                    );
 | 
					                    )
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this._uncertainty = options?.uncertaintyRadius ?? maxDistance;
 | 
					            this._uncertainty = options?.uncertaintyRadius ?? maxDistance
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this._name = tagsSource.map((tags) => tags[nameKey] ?? options?.fallbackName);
 | 
					        this._name = tagsSource.map((tags) => tags[nameKey] ?? options?.fallbackName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.subjectUri = this.ConstructSubjectUri();
 | 
					        this.subjectUri = this.ConstructSubjectUri()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const self = this;
 | 
					        const self = this
 | 
				
			||||||
        this.subjectUri.addCallbackAndRunD(async (sub) => {
 | 
					        this.subjectUri.addCallbackAndRunD(async (sub) => {
 | 
				
			||||||
            const reviews = await MangroveReviews.getReviews({ sub });
 | 
					            const reviews = await MangroveReviews.getReviews({ sub })
 | 
				
			||||||
            self.addReviews(reviews.reviews);
 | 
					            self.addReviews(reviews.reviews)
 | 
				
			||||||
        });
 | 
					        })
 | 
				
			||||||
        /* We also construct all subject queries _without_ encoding the name to work around a previous bug
 | 
					        /* We also construct all subject queries _without_ encoding the name to work around a previous bug
 | 
				
			||||||
         * See https://github.com/giggls/opencampsitemap/issues/30
 | 
					         * See https://github.com/giggls/opencampsitemap/issues/30
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        this.ConstructSubjectUri(true).addCallbackAndRunD(async (sub) => {
 | 
					        this.ConstructSubjectUri(true).addCallbackAndRunD(async (sub) => {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                const reviews = await MangroveReviews.getReviews({ sub });
 | 
					                const reviews = await MangroveReviews.getReviews({ sub })
 | 
				
			||||||
                self.addReviews(reviews.reviews);
 | 
					                self.addReviews(reviews.reviews)
 | 
				
			||||||
            } catch (e) {
 | 
					            } catch (e) {
 | 
				
			||||||
                console.log("Could not fetch reviews for partially incorrect query ", sub);
 | 
					                console.log("Could not fetch reviews for partially incorrect query ", sub)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        })
 | 
				
			||||||
        this.average = this._reviews.map(reviews => {
 | 
					        this.average = this._reviews.map((reviews) => {
 | 
				
			||||||
            if (!reviews) {
 | 
					            if (!reviews) {
 | 
				
			||||||
                return null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if(reviews.length === 0){
 | 
					 | 
				
			||||||
                return null
 | 
					                return null
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            let sum = 0;
 | 
					            if (reviews.length === 0) {
 | 
				
			||||||
            let count = 0;
 | 
					                return null
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            let sum = 0
 | 
				
			||||||
 | 
					            let count = 0
 | 
				
			||||||
            for (const review of reviews) {
 | 
					            for (const review of reviews) {
 | 
				
			||||||
                if (review.rating !== undefined) {
 | 
					                if (review.rating !== undefined) {
 | 
				
			||||||
                    count++;
 | 
					                    count++
 | 
				
			||||||
                    sum += review.rating;
 | 
					                    sum += review.rating
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return Math.round(sum / count)
 | 
					            return Math.round(sum / count)
 | 
				
			||||||
        });
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -158,14 +157,14 @@ export default class FeatureReviews {
 | 
				
			||||||
            uncertaintyRadius?: number
 | 
					            uncertaintyRadius?: number
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        const key = feature.properties.id;
 | 
					        const key = feature.properties.id
 | 
				
			||||||
        const cached = FeatureReviews._featureReviewsCache[key];
 | 
					        const cached = FeatureReviews._featureReviewsCache[key]
 | 
				
			||||||
        if (cached !== undefined) {
 | 
					        if (cached !== undefined) {
 | 
				
			||||||
            return cached;
 | 
					            return cached
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const featureReviews = new FeatureReviews(feature, tagsSource, mangroveIdentity, options);
 | 
					        const featureReviews = new FeatureReviews(feature, tagsSource, mangroveIdentity, options)
 | 
				
			||||||
        FeatureReviews._featureReviewsCache[key] = featureReviews;
 | 
					        FeatureReviews._featureReviewsCache[key] = featureReviews
 | 
				
			||||||
        return featureReviews;
 | 
					        return featureReviews
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -174,15 +173,15 @@ export default class FeatureReviews {
 | 
				
			||||||
    public async createReview(review: Omit<Review, "sub">): Promise<void> {
 | 
					    public async createReview(review: Omit<Review, "sub">): Promise<void> {
 | 
				
			||||||
        const r: Review = {
 | 
					        const r: Review = {
 | 
				
			||||||
            sub: this.subjectUri.data,
 | 
					            sub: this.subjectUri.data,
 | 
				
			||||||
            ...review
 | 
					            ...review,
 | 
				
			||||||
        };
 | 
					        }
 | 
				
			||||||
        const keypair: CryptoKeyPair = this._identity.keypair.data;
 | 
					        const keypair: CryptoKeyPair = this._identity.keypair.data
 | 
				
			||||||
        console.log(r);
 | 
					        console.log(r)
 | 
				
			||||||
        const jwt = await MangroveReviews.signReview(keypair, r);
 | 
					        const jwt = await MangroveReviews.signReview(keypair, r)
 | 
				
			||||||
        console.log("Signed:", jwt);
 | 
					        console.log("Signed:", jwt)
 | 
				
			||||||
        await MangroveReviews.submitReview(jwt);
 | 
					        await MangroveReviews.submitReview(jwt)
 | 
				
			||||||
        this._reviews.data.push({ ...r, madeByLoggedInUser: new ImmutableStore(true) });
 | 
					        this._reviews.data.push({ ...r, madeByLoggedInUser: new ImmutableStore(true) })
 | 
				
			||||||
        this._reviews.ping();
 | 
					        this._reviews.ping()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -191,48 +190,48 @@ export default class FeatureReviews {
 | 
				
			||||||
     * @private
 | 
					     * @private
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private addReviews(reviews: { payload: Review; kid: string }[]) {
 | 
					    private addReviews(reviews: { payload: Review; kid: string }[]) {
 | 
				
			||||||
        const self = this;
 | 
					        const self = this
 | 
				
			||||||
        const alreadyKnown = new Set(self._reviews.data.map((r) => r.rating + " " + r.opinion));
 | 
					        const alreadyKnown = new Set(self._reviews.data.map((r) => r.rating + " " + r.opinion))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let hasNew = false;
 | 
					        let hasNew = false
 | 
				
			||||||
        for (const reviewData of reviews) {
 | 
					        for (const reviewData of reviews) {
 | 
				
			||||||
            const review = reviewData.payload;
 | 
					            const review = reviewData.payload
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                const url = new URL(review.sub);
 | 
					                const url = new URL(review.sub)
 | 
				
			||||||
                console.log("URL is", url);
 | 
					                console.log("URL is", url)
 | 
				
			||||||
                if (url.protocol === "geo:") {
 | 
					                if (url.protocol === "geo:") {
 | 
				
			||||||
                    const coordinate = <[number, number]>(
 | 
					                    const coordinate = <[number, number]>(
 | 
				
			||||||
                        url.pathname.split(",").map((n) => Number(n))
 | 
					                        url.pathname.split(",").map((n) => Number(n))
 | 
				
			||||||
                    );
 | 
					                    )
 | 
				
			||||||
                    const distance = GeoOperations.distanceBetween(
 | 
					                    const distance = GeoOperations.distanceBetween(
 | 
				
			||||||
                        [this._lat, this._lon],
 | 
					                        [this._lat, this._lon],
 | 
				
			||||||
                        coordinate
 | 
					                        coordinate
 | 
				
			||||||
                    );
 | 
					                    )
 | 
				
			||||||
                    if (distance > this._uncertainty) {
 | 
					                    if (distance > this._uncertainty) {
 | 
				
			||||||
                        continue;
 | 
					                        continue
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } catch (e) {
 | 
					            } catch (e) {
 | 
				
			||||||
                console.warn(e);
 | 
					                console.warn(e)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const key = review.rating + " " + review.opinion;
 | 
					            const key = review.rating + " " + review.opinion
 | 
				
			||||||
            if (alreadyKnown.has(key)) {
 | 
					            if (alreadyKnown.has(key)) {
 | 
				
			||||||
                continue;
 | 
					                continue
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            self._reviews.data.push({
 | 
					            self._reviews.data.push({
 | 
				
			||||||
                ...review,
 | 
					                ...review,
 | 
				
			||||||
                madeByLoggedInUser: this._identity.key_id.map((user_key_id) => {
 | 
					                madeByLoggedInUser: this._identity.key_id.map((user_key_id) => {
 | 
				
			||||||
                    return reviewData.kid === user_key_id;
 | 
					                    return reviewData.kid === user_key_id
 | 
				
			||||||
                })
 | 
					                }),
 | 
				
			||||||
            });
 | 
					            })
 | 
				
			||||||
            hasNew = true;
 | 
					            hasNew = true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (hasNew) {
 | 
					        if (hasNew) {
 | 
				
			||||||
            self._reviews.data.sort((a, b) => b.iat - a.iat) // Sort with most recent first
 | 
					            self._reviews.data.sort((a, b) => b.iat - a.iat) // Sort with most recent first
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self._reviews.ping();
 | 
					            self._reviews.ping()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -245,13 +244,13 @@ export default class FeatureReviews {
 | 
				
			||||||
    private ConstructSubjectUri(dontEncodeName: boolean = false): Store<string> {
 | 
					    private ConstructSubjectUri(dontEncodeName: boolean = false): Store<string> {
 | 
				
			||||||
        // https://www.rfc-editor.org/rfc/rfc5870#section-3.4.2
 | 
					        // https://www.rfc-editor.org/rfc/rfc5870#section-3.4.2
 | 
				
			||||||
        // `u` stands for `uncertainty`, https://www.rfc-editor.org/rfc/rfc5870#section-3.4.3
 | 
					        // `u` stands for `uncertainty`, https://www.rfc-editor.org/rfc/rfc5870#section-3.4.3
 | 
				
			||||||
        const self = this;
 | 
					        const self = this
 | 
				
			||||||
        return this._name.map(function(name) {
 | 
					        return this._name.map(function (name) {
 | 
				
			||||||
            let uri = `geo:${self._lat},${self._lon}?u=${self._uncertainty}`;
 | 
					            let uri = `geo:${self._lat},${self._lon}?u=${self._uncertainty}`
 | 
				
			||||||
            if (name) {
 | 
					            if (name) {
 | 
				
			||||||
                uri += "&q=" + (dontEncodeName ? name : encodeURIComponent(name));
 | 
					                uri += "&q=" + (dontEncodeName ? name : encodeURIComponent(name))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return uri;
 | 
					            return uri
 | 
				
			||||||
        });
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,41 +1,41 @@
 | 
				
			||||||
import { Feature, Polygon } from "geojson";
 | 
					import { Feature, Polygon } from "geojson"
 | 
				
			||||||
import * as editorlayerindex from "../assets/editor-layer-index.json";
 | 
					import * as editorlayerindex from "../assets/editor-layer-index.json"
 | 
				
			||||||
import * as globallayers from "../assets/global-raster-layers.json";
 | 
					import * as globallayers from "../assets/global-raster-layers.json"
 | 
				
			||||||
import { BBox } from "../Logic/BBox";
 | 
					import { BBox } from "../Logic/BBox"
 | 
				
			||||||
import { Store, Stores } from "../Logic/UIEventSource";
 | 
					import { Store, Stores } from "../Logic/UIEventSource"
 | 
				
			||||||
import { GeoOperations } from "../Logic/GeoOperations";
 | 
					import { GeoOperations } from "../Logic/GeoOperations"
 | 
				
			||||||
import { RasterLayerProperties } from "./RasterLayerProperties";
 | 
					import { RasterLayerProperties } from "./RasterLayerProperties"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class AvailableRasterLayers {
 | 
					export class AvailableRasterLayers {
 | 
				
			||||||
    public static EditorLayerIndex: (Feature<Polygon, EditorLayerIndexProperties> &
 | 
					    public static EditorLayerIndex: (Feature<Polygon, EditorLayerIndexProperties> &
 | 
				
			||||||
        RasterLayerPolygon)[] = <any>editorlayerindex.features;
 | 
					        RasterLayerPolygon)[] = <any>editorlayerindex.features
 | 
				
			||||||
    public static globalLayers: RasterLayerPolygon[] = globallayers.layers.map(
 | 
					    public static globalLayers: RasterLayerPolygon[] = globallayers.layers.map(
 | 
				
			||||||
        (properties) =>
 | 
					        (properties) =>
 | 
				
			||||||
            <RasterLayerPolygon>{
 | 
					            <RasterLayerPolygon>{
 | 
				
			||||||
                type: "Feature",
 | 
					                type: "Feature",
 | 
				
			||||||
                properties,
 | 
					                properties,
 | 
				
			||||||
                geometry: BBox.global.asGeometry()
 | 
					                geometry: BBox.global.asGeometry(),
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
    );
 | 
					    )
 | 
				
			||||||
    public static readonly osmCartoProperties: RasterLayerProperties = {
 | 
					    public static readonly osmCartoProperties: RasterLayerProperties = {
 | 
				
			||||||
        id: "osm",
 | 
					        id: "osm",
 | 
				
			||||||
        name: "OpenStreetMap",
 | 
					        name: "OpenStreetMap",
 | 
				
			||||||
        url: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
 | 
					        url: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
 | 
				
			||||||
        attribution: {
 | 
					        attribution: {
 | 
				
			||||||
            text: "OpenStreetMap",
 | 
					            text: "OpenStreetMap",
 | 
				
			||||||
            url: "https://openStreetMap.org/copyright"
 | 
					            url: "https://openStreetMap.org/copyright",
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        best: true,
 | 
					        best: true,
 | 
				
			||||||
        max_zoom: 19,
 | 
					        max_zoom: 19,
 | 
				
			||||||
        min_zoom: 0,
 | 
					        min_zoom: 0,
 | 
				
			||||||
        category: "osmbasedmap"
 | 
					        category: "osmbasedmap",
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static readonly osmCarto: RasterLayerPolygon = {
 | 
					    public static readonly osmCarto: RasterLayerPolygon = {
 | 
				
			||||||
        type: "Feature",
 | 
					        type: "Feature",
 | 
				
			||||||
        properties: AvailableRasterLayers.osmCartoProperties,
 | 
					        properties: AvailableRasterLayers.osmCartoProperties,
 | 
				
			||||||
        geometry: BBox.global.asGeometry()
 | 
					        geometry: BBox.global.asGeometry(),
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static readonly maptilerDefaultLayer: RasterLayerPolygon = {
 | 
					    public static readonly maptilerDefaultLayer: RasterLayerPolygon = {
 | 
				
			||||||
        type: "Feature",
 | 
					        type: "Feature",
 | 
				
			||||||
| 
						 | 
					@ -47,11 +47,11 @@ export class AvailableRasterLayers {
 | 
				
			||||||
            type: "vector",
 | 
					            type: "vector",
 | 
				
			||||||
            attribution: {
 | 
					            attribution: {
 | 
				
			||||||
                text: "Maptiler",
 | 
					                text: "Maptiler",
 | 
				
			||||||
                url: "https://www.maptiler.com/copyright/"
 | 
					                url: "https://www.maptiler.com/copyright/",
 | 
				
			||||||
            }
 | 
					            },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        geometry: BBox.global.asGeometry()
 | 
					        geometry: BBox.global.asGeometry(),
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static readonly maptilerCarto: RasterLayerPolygon = {
 | 
					    public static readonly maptilerCarto: RasterLayerPolygon = {
 | 
				
			||||||
        type: "Feature",
 | 
					        type: "Feature",
 | 
				
			||||||
| 
						 | 
					@ -63,11 +63,11 @@ export class AvailableRasterLayers {
 | 
				
			||||||
            type: "vector",
 | 
					            type: "vector",
 | 
				
			||||||
            attribution: {
 | 
					            attribution: {
 | 
				
			||||||
                text: "Maptiler",
 | 
					                text: "Maptiler",
 | 
				
			||||||
                url: "https://www.maptiler.com/copyright/"
 | 
					                url: "https://www.maptiler.com/copyright/",
 | 
				
			||||||
            }
 | 
					            },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        geometry: BBox.global.asGeometry()
 | 
					        geometry: BBox.global.asGeometry(),
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static readonly maptilerBackdrop: RasterLayerPolygon = {
 | 
					    public static readonly maptilerBackdrop: RasterLayerPolygon = {
 | 
				
			||||||
        type: "Feature",
 | 
					        type: "Feature",
 | 
				
			||||||
| 
						 | 
					@ -79,11 +79,11 @@ export class AvailableRasterLayers {
 | 
				
			||||||
            type: "vector",
 | 
					            type: "vector",
 | 
				
			||||||
            attribution: {
 | 
					            attribution: {
 | 
				
			||||||
                text: "Maptiler",
 | 
					                text: "Maptiler",
 | 
				
			||||||
                url: "https://www.maptiler.com/copyright/"
 | 
					                url: "https://www.maptiler.com/copyright/",
 | 
				
			||||||
            }
 | 
					            },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        geometry: BBox.global.asGeometry()
 | 
					        geometry: BBox.global.asGeometry(),
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
    public static readonly americana: RasterLayerPolygon = {
 | 
					    public static readonly americana: RasterLayerPolygon = {
 | 
				
			||||||
        type: "Feature",
 | 
					        type: "Feature",
 | 
				
			||||||
        properties: {
 | 
					        properties: {
 | 
				
			||||||
| 
						 | 
					@ -94,43 +94,45 @@ export class AvailableRasterLayers {
 | 
				
			||||||
            type: "vector",
 | 
					            type: "vector",
 | 
				
			||||||
            attribution: {
 | 
					            attribution: {
 | 
				
			||||||
                text: "Americana",
 | 
					                text: "Americana",
 | 
				
			||||||
                url: "https://github.com/ZeLonewolf/openstreetmap-americana/"
 | 
					                url: "https://github.com/ZeLonewolf/openstreetmap-americana/",
 | 
				
			||||||
            }
 | 
					            },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        geometry: BBox.global.asGeometry()
 | 
					        geometry: BBox.global.asGeometry(),
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static layersAvailableAt(
 | 
					    public static layersAvailableAt(
 | 
				
			||||||
        location: Store<{ lon: number; lat: number }>
 | 
					        location: Store<{ lon: number; lat: number }>
 | 
				
			||||||
    ): Store<RasterLayerPolygon[]> {
 | 
					    ): Store<RasterLayerPolygon[]> {
 | 
				
			||||||
        const availableLayersBboxes = Stores.ListStabilized(
 | 
					        const availableLayersBboxes = Stores.ListStabilized(
 | 
				
			||||||
            location.mapD((loc) => {
 | 
					            location.mapD((loc) => {
 | 
				
			||||||
                const lonlat: [number, number] = [loc.lon, loc.lat];
 | 
					                const lonlat: [number, number] = [loc.lon, loc.lat]
 | 
				
			||||||
                return AvailableRasterLayers.EditorLayerIndex.filter((eliPolygon) =>
 | 
					                return AvailableRasterLayers.EditorLayerIndex.filter((eliPolygon) =>
 | 
				
			||||||
                    BBox.get(eliPolygon).contains(lonlat)
 | 
					                    BBox.get(eliPolygon).contains(lonlat)
 | 
				
			||||||
                );
 | 
					                )
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        );
 | 
					        )
 | 
				
			||||||
        const available = Stores.ListStabilized(
 | 
					        const available = Stores.ListStabilized(
 | 
				
			||||||
            availableLayersBboxes.map((eliPolygons) => {
 | 
					            availableLayersBboxes.map((eliPolygons) => {
 | 
				
			||||||
                const loc = location.data;
 | 
					                const loc = location.data
 | 
				
			||||||
                const lonlat: [number, number] = [loc.lon, loc.lat];
 | 
					                const lonlat: [number, number] = [loc.lon, loc.lat]
 | 
				
			||||||
                const matching: RasterLayerPolygon[] = eliPolygons.filter((eliPolygon) => {
 | 
					                const matching: RasterLayerPolygon[] = eliPolygons.filter((eliPolygon) => {
 | 
				
			||||||
                    if (eliPolygon.geometry === null) {
 | 
					                    if (eliPolygon.geometry === null) {
 | 
				
			||||||
                        return true; // global ELI-layer
 | 
					                        return true // global ELI-layer
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    return GeoOperations.inside(lonlat, eliPolygon);
 | 
					                    return GeoOperations.inside(lonlat, eliPolygon)
 | 
				
			||||||
                });
 | 
					                })
 | 
				
			||||||
                matching.push(...AvailableRasterLayers.globalLayers);
 | 
					                matching.push(...AvailableRasterLayers.globalLayers)
 | 
				
			||||||
                matching.unshift(AvailableRasterLayers.maptilerDefaultLayer,
 | 
					                matching.unshift(
 | 
				
			||||||
 | 
					                    AvailableRasterLayers.maptilerDefaultLayer,
 | 
				
			||||||
                    AvailableRasterLayers.osmCarto,
 | 
					                    AvailableRasterLayers.osmCarto,
 | 
				
			||||||
                    AvailableRasterLayers.maptilerCarto,
 | 
					                    AvailableRasterLayers.maptilerCarto,
 | 
				
			||||||
                    AvailableRasterLayers.maptilerBackdrop,
 | 
					                    AvailableRasterLayers.maptilerBackdrop,
 | 
				
			||||||
                    AvailableRasterLayers.americana);
 | 
					                    AvailableRasterLayers.americana
 | 
				
			||||||
                return matching;
 | 
					                )
 | 
				
			||||||
 | 
					                return matching
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        );
 | 
					        )
 | 
				
			||||||
        return available;
 | 
					        return available
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,22 +150,22 @@ export class RasterLayerUtils {
 | 
				
			||||||
        preferredCategory: string,
 | 
					        preferredCategory: string,
 | 
				
			||||||
        ignoreLayer?: RasterLayerPolygon
 | 
					        ignoreLayer?: RasterLayerPolygon
 | 
				
			||||||
    ): RasterLayerPolygon {
 | 
					    ): RasterLayerPolygon {
 | 
				
			||||||
        let secondBest: RasterLayerPolygon = undefined;
 | 
					        let secondBest: RasterLayerPolygon = undefined
 | 
				
			||||||
        for (const rasterLayer of available) {
 | 
					        for (const rasterLayer of available) {
 | 
				
			||||||
            if (rasterLayer === ignoreLayer) {
 | 
					            if (rasterLayer === ignoreLayer) {
 | 
				
			||||||
                continue;
 | 
					                continue
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            const p = rasterLayer.properties;
 | 
					            const p = rasterLayer.properties
 | 
				
			||||||
            if (p.category === preferredCategory) {
 | 
					            if (p.category === preferredCategory) {
 | 
				
			||||||
                if (p.best) {
 | 
					                if (p.best) {
 | 
				
			||||||
                    return rasterLayer;
 | 
					                    return rasterLayer
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (!secondBest) {
 | 
					                if (!secondBest) {
 | 
				
			||||||
                    secondBest = rasterLayer;
 | 
					                    secondBest = rasterLayer
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return secondBest;
 | 
					        return secondBest
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -179,11 +181,11 @@ export interface EditorLayerIndexProperties extends RasterLayerProperties {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The name of the imagery source
 | 
					     * The name of the imagery source
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly name: string;
 | 
					    readonly name: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Whether the imagery name should be translated
 | 
					     * Whether the imagery name should be translated
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly i18n?: boolean;
 | 
					    readonly i18n?: boolean
 | 
				
			||||||
    readonly type:
 | 
					    readonly type:
 | 
				
			||||||
        | "tms"
 | 
					        | "tms"
 | 
				
			||||||
        | "wms"
 | 
					        | "wms"
 | 
				
			||||||
| 
						 | 
					@ -191,7 +193,7 @@ export interface EditorLayerIndexProperties extends RasterLayerProperties {
 | 
				
			||||||
        | "scanex"
 | 
					        | "scanex"
 | 
				
			||||||
        | "wms_endpoint"
 | 
					        | "wms_endpoint"
 | 
				
			||||||
        | "wmts"
 | 
					        | "wmts"
 | 
				
			||||||
        | "vector"; /* Vector is not actually part of the ELI-spec, we add it for vector layers */
 | 
					        | "vector" /* Vector is not actually part of the ELI-spec, we add it for vector layers */
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A rough categorisation of different types of layers. See https://github.com/osmlab/editor-layer-index/blob/gh-pages/CONTRIBUTING.md#categories for a description of the individual categories.
 | 
					     * A rough categorisation of different types of layers. See https://github.com/osmlab/editor-layer-index/blob/gh-pages/CONTRIBUTING.md#categories for a description of the individual categories.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
| 
						 | 
					@ -203,53 +205,53 @@ export interface EditorLayerIndexProperties extends RasterLayerProperties {
 | 
				
			||||||
        | "historicphoto"
 | 
					        | "historicphoto"
 | 
				
			||||||
        | "qa"
 | 
					        | "qa"
 | 
				
			||||||
        | "elevation"
 | 
					        | "elevation"
 | 
				
			||||||
        | "other";
 | 
					        | "other"
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A URL template for imagery tiles
 | 
					     * A URL template for imagery tiles
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly url: string;
 | 
					    readonly url: string
 | 
				
			||||||
    readonly min_zoom?: number;
 | 
					    readonly min_zoom?: number
 | 
				
			||||||
    readonly max_zoom?: number;
 | 
					    readonly max_zoom?: number
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * explicit/implicit permission by the owner for use in OSM
 | 
					     * explicit/implicit permission by the owner for use in OSM
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly permission_osm?: "explicit" | "implicit" | "no";
 | 
					    readonly permission_osm?: "explicit" | "implicit" | "no"
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A URL for the license or permissions for the imagery
 | 
					     * A URL for the license or permissions for the imagery
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly license_url?: string;
 | 
					    readonly license_url?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A URL for the privacy policy of the operator or false if there is no existing privacy policy for tis imagery.
 | 
					     * A URL for the privacy policy of the operator or false if there is no existing privacy policy for tis imagery.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly privacy_policy_url?: string | boolean;
 | 
					    readonly privacy_policy_url?: string | boolean
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A unique identifier for the source; used in imagery_used changeset tag
 | 
					     * A unique identifier for the source; used in imagery_used changeset tag
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly id: string;
 | 
					    readonly id: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A short English-language description of the source
 | 
					     * A short English-language description of the source
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly description?: string;
 | 
					    readonly description?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The ISO 3166-1 alpha-2 two letter country code in upper case. Use ZZ for unknown or multiple.
 | 
					     * The ISO 3166-1 alpha-2 two letter country code in upper case. Use ZZ for unknown or multiple.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly country_code?: string;
 | 
					    readonly country_code?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Whether this imagery should be shown in the default world-wide menu
 | 
					     * Whether this imagery should be shown in the default world-wide menu
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly default?: boolean;
 | 
					    readonly default?: boolean
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Whether this imagery is the best source for the region
 | 
					     * Whether this imagery is the best source for the region
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly best?: boolean;
 | 
					    readonly best?: boolean
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The age of the oldest imagery or data in the source, as an RFC3339 date or leading portion of one
 | 
					     * The age of the oldest imagery or data in the source, as an RFC3339 date or leading portion of one
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly start_date?: string;
 | 
					    readonly start_date?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The age of the newest imagery or data in the source, as an RFC3339 date or leading portion of one
 | 
					     * The age of the newest imagery or data in the source, as an RFC3339 date or leading portion of one
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly end_date?: string;
 | 
					    readonly end_date?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * HTTP header to check for information if the tile is invalid
 | 
					     * HTTP header to check for information if the tile is invalid
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
| 
						 | 
					@ -259,61 +261,61 @@ export interface EditorLayerIndexProperties extends RasterLayerProperties {
 | 
				
			||||||
         * via the `patternProperty` "^.*$".
 | 
					         * via the `patternProperty` "^.*$".
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        [k: string]: string[] | null
 | 
					        [k: string]: string[] | null
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 'true' if tiles are transparent and can be overlaid on another source
 | 
					     * 'true' if tiles are transparent and can be overlaid on another source
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly overlay?: boolean & string;
 | 
					    readonly overlay?: boolean & string
 | 
				
			||||||
    readonly available_projections?: string[];
 | 
					    readonly available_projections?: string[]
 | 
				
			||||||
    readonly attribution?: {
 | 
					    readonly attribution?: {
 | 
				
			||||||
        readonly url?: string
 | 
					        readonly url?: string
 | 
				
			||||||
        readonly text?: string
 | 
					        readonly text?: string
 | 
				
			||||||
        readonly html?: string
 | 
					        readonly html?: string
 | 
				
			||||||
        readonly required?: boolean
 | 
					        readonly required?: boolean
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A URL for an image, that can be displayed in the list of imagery layers next to the name
 | 
					     * A URL for an image, that can be displayed in the list of imagery layers next to the name
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly icon?: string;
 | 
					    readonly icon?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A link to an EULA text that has to be accepted by the user, before the imagery source is added. Can contain {lang} to be replaced by a current user language wiki code (like FR:) or an empty string for the default English text.
 | 
					     * A link to an EULA text that has to be accepted by the user, before the imagery source is added. Can contain {lang} to be replaced by a current user language wiki code (like FR:) or an empty string for the default English text.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly eula?: string;
 | 
					    readonly eula?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * A URL for an image, that is displayed in the mapview for attribution
 | 
					     * A URL for an image, that is displayed in the mapview for attribution
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly "logo-image"?: string;
 | 
					    readonly "logo-image"?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Customized text for the terms of use link (default is "Background Terms of Use")
 | 
					     * Customized text for the terms of use link (default is "Background Terms of Use")
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly "terms-of-use-text"?: string;
 | 
					    readonly "terms-of-use-text"?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Specify a checksum for tiles, which aren't real tiles. `type` is the digest type and can be MD5, SHA-1, SHA-256, SHA-384 and SHA-512, value is the hex encoded checksum in lower case. To create a checksum save the tile as file and upload it to e.g. https://defuse.ca/checksums.htm.
 | 
					     * Specify a checksum for tiles, which aren't real tiles. `type` is the digest type and can be MD5, SHA-1, SHA-256, SHA-384 and SHA-512, value is the hex encoded checksum in lower case. To create a checksum save the tile as file and upload it to e.g. https://defuse.ca/checksums.htm.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly "no-tile-checksum"?: string;
 | 
					    readonly "no-tile-checksum"?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * header-name attribute specifies a header returned by tile server, that will be shown as `metadata-key` attribute in Show Tile Info dialog
 | 
					     * header-name attribute specifies a header returned by tile server, that will be shown as `metadata-key` attribute in Show Tile Info dialog
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly "metadata-header"?: string;
 | 
					    readonly "metadata-header"?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Set to `true` if imagery source is properly aligned and does not need imagery offset adjustments. This is used for OSM based sources too.
 | 
					     * Set to `true` if imagery source is properly aligned and does not need imagery offset adjustments. This is used for OSM based sources too.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly "valid-georeference"?: boolean;
 | 
					    readonly "valid-georeference"?: boolean
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Size of individual tiles delivered by a TMS service
 | 
					     * Size of individual tiles delivered by a TMS service
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly "tile-size"?: number;
 | 
					    readonly "tile-size"?: number
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Whether tiles status can be accessed by appending /status to the tile URL and can be submitted for re-rendering by appending /dirty.
 | 
					     * Whether tiles status can be accessed by appending /status to the tile URL and can be submitted for re-rendering by appending /dirty.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly "mod-tile-features"?: string;
 | 
					    readonly "mod-tile-features"?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * HTTP headers to be sent to server. It has two attributes header-name and header-value. May be specified multiple times.
 | 
					     * HTTP headers to be sent to server. It has two attributes header-name and header-value. May be specified multiple times.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly "custom-http-headers"?: {
 | 
					    readonly "custom-http-headers"?: {
 | 
				
			||||||
        readonly "header-name"?: string
 | 
					        readonly "header-name"?: string
 | 
				
			||||||
        readonly "header-value"?: string
 | 
					        readonly "header-value"?: string
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Default layer to open (when using WMS_ENDPOINT type). Contains list of layer tag with two attributes - name and style, e.g. `"default-layers": ["layer": { name="Basisdata_NP_Basiskart_JanMayen_WMTS_25829" "style":"default" } ]` (not allowed in `mirror` attribute)
 | 
					     * Default layer to open (when using WMS_ENDPOINT type). Contains list of layer tag with two attributes - name and style, e.g. `"default-layers": ["layer": { name="Basisdata_NP_Basiskart_JanMayen_WMTS_25829" "style":"default" } ]` (not allowed in `mirror` attribute)
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
| 
						 | 
					@ -324,17 +326,17 @@ export interface EditorLayerIndexProperties extends RasterLayerProperties {
 | 
				
			||||||
            [k: string]: unknown
 | 
					            [k: string]: unknown
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        [k: string]: unknown
 | 
					        [k: string]: unknown
 | 
				
			||||||
    }[];
 | 
					    }[]
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * format to use when connecting tile server (when using WMS_ENDPOINT type)
 | 
					     * format to use when connecting tile server (when using WMS_ENDPOINT type)
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly format?: string;
 | 
					    readonly format?: string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * If `true` transparent tiles will be requested from WMS server
 | 
					     * If `true` transparent tiles will be requested from WMS server
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly transparent?: boolean & string;
 | 
					    readonly transparent?: boolean & string
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * minimum expiry time for tiles in seconds. The larger the value, the longer entry in cache will be considered valid
 | 
					     * minimum expiry time for tiles in seconds. The larger the value, the longer entry in cache will be considered valid
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    readonly "minimum-tile-expire"?: number;
 | 
					    readonly "minimum-tile-expire"?: number
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ import LineRenderingConfigJson from "../Json/LineRenderingConfigJson"
 | 
				
			||||||
import { LayerConfigJson } from "../Json/LayerConfigJson"
 | 
					import { LayerConfigJson } from "../Json/LayerConfigJson"
 | 
				
			||||||
import { DesugaringStep, Each, Fuse, On } from "./Conversion"
 | 
					import { DesugaringStep, Each, Fuse, On } from "./Conversion"
 | 
				
			||||||
import PointRenderingConfigJson from "../Json/PointRenderingConfigJson"
 | 
					import PointRenderingConfigJson from "../Json/PointRenderingConfigJson"
 | 
				
			||||||
import { del } from "idb-keyval";
 | 
					import { del } from "idb-keyval"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class UpdateLegacyLayer extends DesugaringStep<
 | 
					export class UpdateLegacyLayer extends DesugaringStep<
 | 
				
			||||||
    LayerConfigJson | string | { builtin; override }
 | 
					    LayerConfigJson | string | { builtin; override }
 | 
				
			||||||
| 
						 | 
					@ -197,7 +197,7 @@ class UpdateLegacyTheme extends DesugaringStep<LayoutConfigJson> {
 | 
				
			||||||
            delete oldThemeConfig.socialImage
 | 
					            delete oldThemeConfig.socialImage
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(oldThemeConfig.defaultBackgroundId === "osm"){
 | 
					        if (oldThemeConfig.defaultBackgroundId === "osm") {
 | 
				
			||||||
            console.log("Removing old background in", json.id)
 | 
					            console.log("Removing old background in", json.id)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,14 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import type { Writable } from "svelte/store";
 | 
					  import type { Writable } from "svelte/store"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * For some stupid reason, it is very hard to bind inputs
 | 
					   * For some stupid reason, it is very hard to bind inputs
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  export let selected: Writable<boolean>;
 | 
					  export let selected: Writable<boolean>
 | 
				
			||||||
  let _c: boolean = selected.data ?? true;
 | 
					  let _c: boolean = selected.data ?? true
 | 
				
			||||||
  $: selected.set(_c);
 | 
					  $: selected.set(_c)
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<label class="no-image-background flex gap-1">
 | 
					<label class="no-image-background flex gap-1">
 | 
				
			||||||
  <input bind:checked={_c} type="checkbox" />
 | 
					  <input bind:checked={_c} type="checkbox" />
 | 
				
			||||||
  <slot />
 | 
					  <slot />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,40 +1,48 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					  import { createEventDispatcher } from "svelte"
 | 
				
			||||||
 | 
					  import { twMerge } from "tailwind-merge"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  import { createEventDispatcher } from "svelte";
 | 
					  export let accept: string
 | 
				
			||||||
  import { twMerge } from "tailwind-merge";
 | 
					  export let multiple: boolean = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let accept: string;
 | 
					  const dispatcher = createEventDispatcher<{ submit: FileList }>()
 | 
				
			||||||
  export let multiple: boolean = true;
 | 
					  export let cls: string = ""
 | 
				
			||||||
 | 
					  let drawAttention = false
 | 
				
			||||||
  const dispatcher = createEventDispatcher<{ submit: FileList }>();
 | 
					  let inputElement: HTMLInputElement
 | 
				
			||||||
  export let cls: string = "";
 | 
					  let id = Math.random() * 1000000000 + ""
 | 
				
			||||||
  let drawAttention = false;
 | 
					 | 
				
			||||||
  let inputElement: HTMLInputElement;
 | 
					 | 
				
			||||||
  let id = Math.random() * 1000000000 + "";
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<form>
 | 
					<form>
 | 
				
			||||||
  <label class={twMerge(cls, drawAttention ? "glowing-shadow" : "")} for={"fileinput"+id}>
 | 
					  <label class={twMerge(cls, drawAttention ? "glowing-shadow" : "")} for={"fileinput" + id}>
 | 
				
			||||||
    <slot />
 | 
					    <slot />
 | 
				
			||||||
 | 
					 | 
				
			||||||
  </label>
 | 
					  </label>
 | 
				
			||||||
  <input {accept} bind:this={inputElement} class="hidden" id={"fileinput"  + id} {multiple} name="file-input"
 | 
					  <input
 | 
				
			||||||
         on:change|preventDefault={() => {
 | 
					    {accept}
 | 
				
			||||||
  drawAttention = false; 
 | 
					    bind:this={inputElement}
 | 
				
			||||||
  dispatcher("submit", inputElement.files)}}
 | 
					    class="hidden"
 | 
				
			||||||
         
 | 
					    id={"fileinput" + id}
 | 
				
			||||||
         on:dragend={ () => {drawAttention = false}}
 | 
					    {multiple}
 | 
				
			||||||
         on:dragover|preventDefault|stopPropagation={(e) => {
 | 
					    name="file-input"
 | 
				
			||||||
           console.log("Dragging over!")
 | 
					    on:change|preventDefault={() => {
 | 
				
			||||||
             drawAttention = true
 | 
					      drawAttention = false
 | 
				
			||||||
             e.dataTransfer.drop = "copy"
 | 
					      dispatcher("submit", inputElement.files)
 | 
				
			||||||
           }}
 | 
					    }}
 | 
				
			||||||
         on:dragstart={ () => {drawAttention = false}}
 | 
					    on:dragend={() => {
 | 
				
			||||||
         on:drop|preventDefault|stopPropagation={(e) => {
 | 
					      drawAttention = false
 | 
				
			||||||
           console.log("Got a 'drop'")
 | 
					    }}
 | 
				
			||||||
          drawAttention = false
 | 
					    on:dragover|preventDefault|stopPropagation={(e) => {
 | 
				
			||||||
          dispatcher("submit", e.dataTransfer.files)
 | 
					      console.log("Dragging over!")
 | 
				
			||||||
        }}
 | 
					      drawAttention = true
 | 
				
			||||||
         type="file"
 | 
					      e.dataTransfer.drop = "copy"
 | 
				
			||||||
  >
 | 
					    }}
 | 
				
			||||||
 | 
					    on:dragstart={() => {
 | 
				
			||||||
 | 
					      drawAttention = false
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					    on:drop|preventDefault|stopPropagation={(e) => {
 | 
				
			||||||
 | 
					      console.log("Got a 'drop'")
 | 
				
			||||||
 | 
					      drawAttention = false
 | 
				
			||||||
 | 
					      dispatcher("submit", e.dataTransfer.files)
 | 
				
			||||||
 | 
					    }}
 | 
				
			||||||
 | 
					    type="file"
 | 
				
			||||||
 | 
					  />
 | 
				
			||||||
</form>
 | 
					</form>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Given an HTML string, properly shows this
 | 
					   * Given an HTML string, properly shows this
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  import { Utils } from "../../Utils";
 | 
					  import { Utils } from "../../Utils"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let src: string
 | 
					  export let src: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,12 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import ToSvelte from "./ToSvelte.svelte";
 | 
					  import ToSvelte from "./ToSvelte.svelte"
 | 
				
			||||||
  import Svg from "../../Svg";
 | 
					  import Svg from "../../Svg"
 | 
				
			||||||
  import { twMerge } from "tailwind-merge";
 | 
					  import { twMerge } from "tailwind-merge"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let cls : string = undefined
 | 
					  export let cls: string = undefined
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class={twMerge( "flex p-1 pl-2", cls)}>
 | 
					<div class={twMerge("flex p-1 pl-2", cls)}>
 | 
				
			||||||
  <div class="min-w-6 h-6 w-6 animate-spin self-center">
 | 
					  <div class="min-w-6 h-6 w-6 animate-spin self-center">
 | 
				
			||||||
    <ToSvelte construct={Svg.loading_svg()} />
 | 
					    <ToSvelte construct={Svg.loading_svg()} />
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,26 +55,26 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{#if filteredLayer.layerDef.name}
 | 
					{#if filteredLayer.layerDef.name}
 | 
				
			||||||
  <div bind:this={mainElem} class="mb-1.5">
 | 
					  <div bind:this={mainElem} class="mb-1.5">
 | 
				
			||||||
      <Checkbox selected={isDisplayed} >
 | 
					    <Checkbox selected={isDisplayed}>
 | 
				
			||||||
        <If condition={filteredLayer.isDisplayed}>
 | 
					      <If condition={filteredLayer.isDisplayed}>
 | 
				
			||||||
          <ToSvelte
 | 
					        <ToSvelte
 | 
				
			||||||
            construct={() => layer.defaultIcon()?.SetClass("block h-6 w-6 no-image-background")}
 | 
					          construct={() => layer.defaultIcon()?.SetClass("block h-6 w-6 no-image-background")}
 | 
				
			||||||
          />
 | 
					        />
 | 
				
			||||||
          <ToSvelte
 | 
					        <ToSvelte
 | 
				
			||||||
            slot="else"
 | 
					          slot="else"
 | 
				
			||||||
            construct={() =>
 | 
					          construct={() =>
 | 
				
			||||||
            layer.defaultIcon()?.SetClass("block h-6 w-6 no-image-background opacity-50")}
 | 
					            layer.defaultIcon()?.SetClass("block h-6 w-6 no-image-background opacity-50")}
 | 
				
			||||||
          />
 | 
					        />
 | 
				
			||||||
        </If>
 | 
					      </If>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {filteredLayer.layerDef.name}
 | 
					      {filteredLayer.layerDef.name}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {#if $zoomlevel < layer.minzoom}
 | 
					      {#if $zoomlevel < layer.minzoom}
 | 
				
			||||||
        <span class="alert">
 | 
					        <span class="alert">
 | 
				
			||||||
          <Tr t={Translations.t.general.layerSelection.zoomInToSeeThisLayer} />
 | 
					          <Tr t={Translations.t.general.layerSelection.zoomInToSeeThisLayer} />
 | 
				
			||||||
        </span>
 | 
					        </span>
 | 
				
			||||||
        {/if}
 | 
					      {/if}
 | 
				
			||||||
      </Checkbox>
 | 
					    </Checkbox>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {#if $isDisplayed && filteredLayer.layerDef.filters?.length > 0}
 | 
					    {#if $isDisplayed && filteredLayer.layerDef.filters?.length > 0}
 | 
				
			||||||
      <div id="subfilters" class="ml-4 flex flex-col gap-y-1">
 | 
					      <div id="subfilters" class="ml-4 flex flex-col gap-y-1">
 | 
				
			||||||
| 
						 | 
					@ -82,9 +82,9 @@
 | 
				
			||||||
          <div>
 | 
					          <div>
 | 
				
			||||||
            <!-- There are three (and a half) modes of filters: a single checkbox, a radio button/dropdown or with searchable fields -->
 | 
					            <!-- There are three (and a half) modes of filters: a single checkbox, a radio button/dropdown or with searchable fields -->
 | 
				
			||||||
            {#if filter.options.length === 1 && filter.options[0].fields.length === 0}
 | 
					            {#if filter.options.length === 1 && filter.options[0].fields.length === 0}
 | 
				
			||||||
                <Checkbox selected={getBooleanStateFor(filter)} >
 | 
					              <Checkbox selected={getBooleanStateFor(filter)}>
 | 
				
			||||||
                  {filter.options[0].question}
 | 
					                {filter.options[0].question}
 | 
				
			||||||
                </Checkbox>
 | 
					              </Checkbox>
 | 
				
			||||||
            {/if}
 | 
					            {/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            {#if filter.options.length === 1 && filter.options[0].fields.length > 0}
 | 
					            {#if filter.options.length === 1 && filter.options[0].fields.length > 0}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,44 +1,45 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import Translations from "../i18n/Translations";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
  import Svg from "../../Svg";
 | 
					  import Svg from "../../Svg"
 | 
				
			||||||
  import Tr from "../Base/Tr.svelte";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
  import NextButton from "../Base/NextButton.svelte";
 | 
					  import NextButton from "../Base/NextButton.svelte"
 | 
				
			||||||
  import Geosearch from "./Geosearch.svelte";
 | 
					  import Geosearch from "./Geosearch.svelte"
 | 
				
			||||||
  import ToSvelte from "../Base/ToSvelte.svelte";
 | 
					  import ToSvelte from "../Base/ToSvelte.svelte"
 | 
				
			||||||
  import ThemeViewState from "../../Models/ThemeViewState";
 | 
					  import ThemeViewState from "../../Models/ThemeViewState"
 | 
				
			||||||
  import { Store, UIEventSource } from "../../Logic/UIEventSource";
 | 
					  import { Store, UIEventSource } from "../../Logic/UIEventSource"
 | 
				
			||||||
  import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid";
 | 
					  import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid"
 | 
				
			||||||
  import { twJoin } from "tailwind-merge";
 | 
					  import { twJoin } from "tailwind-merge"
 | 
				
			||||||
  import { Utils } from "../../Utils";
 | 
					  import { Utils } from "../../Utils"
 | 
				
			||||||
  import type { GeolocationPermissionState } from "../../Logic/State/GeoLocationState";
 | 
					  import type { GeolocationPermissionState } from "../../Logic/State/GeoLocationState"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * The theme introduction panel
 | 
					   * The theme introduction panel
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  export let state: ThemeViewState;
 | 
					  export let state: ThemeViewState
 | 
				
			||||||
  let layout = state.layout;
 | 
					  let layout = state.layout
 | 
				
			||||||
  let selectedElement = state.selectedElement;
 | 
					  let selectedElement = state.selectedElement
 | 
				
			||||||
  let selectedLayer = state.selectedLayer;
 | 
					  let selectedLayer = state.selectedLayer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let triggerSearch: UIEventSource<any> = new UIEventSource<any>(undefined);
 | 
					  let triggerSearch: UIEventSource<any> = new UIEventSource<any>(undefined)
 | 
				
			||||||
  let searchEnabled = false;
 | 
					  let searchEnabled = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let geopermission: Store<GeolocationPermissionState> = state.geolocation.geolocationState.permission;
 | 
					  let geopermission: Store<GeolocationPermissionState> =
 | 
				
			||||||
  let currentGPSLocation = state.geolocation.geolocationState.currentGPSLocation;
 | 
					    state.geolocation.geolocationState.permission
 | 
				
			||||||
 | 
					  let currentGPSLocation = state.geolocation.geolocationState.currentGPSLocation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  geopermission.addCallback(perm => console.log(">>>> Permission", perm));
 | 
					  geopermission.addCallback((perm) => console.log(">>>> Permission", perm))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function jumpToCurrentLocation() {
 | 
					  function jumpToCurrentLocation() {
 | 
				
			||||||
    const glstate = state.geolocation.geolocationState;
 | 
					    const glstate = state.geolocation.geolocationState
 | 
				
			||||||
    if (glstate.currentGPSLocation.data !== undefined) {
 | 
					    if (glstate.currentGPSLocation.data !== undefined) {
 | 
				
			||||||
      const c: GeolocationCoordinates = glstate.currentGPSLocation.data;
 | 
					      const c: GeolocationCoordinates = glstate.currentGPSLocation.data
 | 
				
			||||||
      state.guistate.themeIsOpened.setData(false);
 | 
					      state.guistate.themeIsOpened.setData(false)
 | 
				
			||||||
      const coor = { lon: c.longitude, lat: c.latitude };
 | 
					      const coor = { lon: c.longitude, lat: c.latitude }
 | 
				
			||||||
      state.mapProperties.location.setData(coor);
 | 
					      state.mapProperties.location.setData(coor)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (glstate.permission.data !== "granted") {
 | 
					    if (glstate.permission.data !== "granted") {
 | 
				
			||||||
      glstate.requestPermission();
 | 
					      glstate.requestPermission()
 | 
				
			||||||
      return;
 | 
					      return
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -69,22 +70,29 @@
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
        <!-- No geolocation granted - we don't show the button -->
 | 
					        <!-- No geolocation granted - we don't show the button -->
 | 
				
			||||||
      {:else if $geopermission === "requested"}
 | 
					      {:else if $geopermission === "requested"}
 | 
				
			||||||
        <button class="flex w-full items-center gap-x-2 disabled" on:click={jumpToCurrentLocation}>
 | 
					        <button class="disabled flex w-full items-center gap-x-2" on:click={jumpToCurrentLocation}>
 | 
				
			||||||
          <!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup -->
 | 
					          <!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup -->
 | 
				
			||||||
          <ToSvelte construct={Svg.crosshair_svg().SetClass("w-8 h-8").SetStyle("animation: 3s linear 0s infinite normal none running spin;")} />
 | 
					          <ToSvelte
 | 
				
			||||||
 | 
					            construct={Svg.crosshair_svg()
 | 
				
			||||||
 | 
					              .SetClass("w-8 h-8")
 | 
				
			||||||
 | 
					              .SetStyle("animation: 3s linear 0s infinite normal none running spin;")}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
          <Tr t={Translations.t.general.waitingForGeopermission} />
 | 
					          <Tr t={Translations.t.general.waitingForGeopermission} />
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
      {:else if $geopermission === "denied"}
 | 
					      {:else if $geopermission === "denied"}
 | 
				
			||||||
        <button class="flex w-full items-center gap-x-2 disabled">
 | 
					        <button class="disabled flex w-full items-center gap-x-2">
 | 
				
			||||||
          <ToSvelte construct={Svg.location_refused_svg().SetClass("w-8 h-8")} />
 | 
					          <ToSvelte construct={Svg.location_refused_svg().SetClass("w-8 h-8")} />
 | 
				
			||||||
          <Tr t={Translations.t.general.geopermissionDenied} />
 | 
					          <Tr t={Translations.t.general.geopermissionDenied} />
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
      {:else }
 | 
					      {:else}
 | 
				
			||||||
        <button class="flex w-full items-center gap-x-2 disabled">
 | 
					        <button class="disabled flex w-full items-center gap-x-2">
 | 
				
			||||||
          <ToSvelte construct={Svg.crosshair_svg().SetClass("w-8 h-8").SetStyle("animation: 3s linear 0s infinite normal none running spin;")} />
 | 
					          <ToSvelte
 | 
				
			||||||
 | 
					            construct={Svg.crosshair_svg()
 | 
				
			||||||
 | 
					              .SetClass("w-8 h-8")
 | 
				
			||||||
 | 
					              .SetStyle("animation: 3s linear 0s infinite normal none running spin;")}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
          <Tr t={Translations.t.general.waitingForLocation} />
 | 
					          <Tr t={Translations.t.general.waitingForLocation} />
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
 | 
					 | 
				
			||||||
      {/if}
 | 
					      {/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div class=".button low-interaction m-1 flex w-full items-center gap-x-2 rounded border p-2">
 | 
					      <div class=".button low-interaction m-1 flex w-full items-center gap-x-2 rounded border p-2">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,63 +1,63 @@
 | 
				
			||||||
<script lang="ts">/**
 | 
					<script lang="ts">
 | 
				
			||||||
 * Shows an 'upload'-button which will start the upload for this feature
 | 
					  /**
 | 
				
			||||||
 */
 | 
					   * Shows an 'upload'-button which will start the upload for this feature
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { SpecialVisualizationState } from "../SpecialVisualization";
 | 
					  import type { SpecialVisualizationState } from "../SpecialVisualization"
 | 
				
			||||||
import { Store } from "../../Logic/UIEventSource";
 | 
					  import { Store } from "../../Logic/UIEventSource"
 | 
				
			||||||
import type { OsmTags } from "../../Models/OsmFeature";
 | 
					  import type { OsmTags } from "../../Models/OsmFeature"
 | 
				
			||||||
import LoginToggle from "../Base/LoginToggle.svelte";
 | 
					  import LoginToggle from "../Base/LoginToggle.svelte"
 | 
				
			||||||
import Translations from "../i18n/Translations";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
import Tr from "../Base/Tr.svelte";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
import UploadingImageCounter from "./UploadingImageCounter.svelte";
 | 
					  import UploadingImageCounter from "./UploadingImageCounter.svelte"
 | 
				
			||||||
import FileSelector from "../Base/FileSelector.svelte";
 | 
					  import FileSelector from "../Base/FileSelector.svelte"
 | 
				
			||||||
import ToSvelte from "../Base/ToSvelte.svelte";
 | 
					  import ToSvelte from "../Base/ToSvelte.svelte"
 | 
				
			||||||
import Svg from "../../Svg";
 | 
					  import Svg from "../../Svg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export let state: SpecialVisualizationState;
 | 
					  export let state: SpecialVisualizationState
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export let tags: Store<OsmTags>;
 | 
					  export let tags: Store<OsmTags>
 | 
				
			||||||
/**
 | 
					  /**
 | 
				
			||||||
 * Image to show in the button
 | 
					   * Image to show in the button
 | 
				
			||||||
 * NOT the image to upload!
 | 
					   * NOT the image to upload!
 | 
				
			||||||
 */
 | 
					   */
 | 
				
			||||||
export let image: string = undefined;
 | 
					  export let image: string = undefined
 | 
				
			||||||
if (image === "") {
 | 
					  if (image === "") {
 | 
				
			||||||
  image = undefined;
 | 
					    image = undefined
 | 
				
			||||||
}
 | 
					  }
 | 
				
			||||||
export let labelText: string = undefined;
 | 
					  export let labelText: string = undefined
 | 
				
			||||||
const t = Translations.t.image;
 | 
					  const t = Translations.t.image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let licenseStore = state.userRelatedState.imageLicense;
 | 
					  let licenseStore = state.userRelatedState.imageLicense
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function handleFiles(files: FileList) {
 | 
					  function handleFiles(files: FileList) {
 | 
				
			||||||
  for (let i = 0; i < files.length; i++) {
 | 
					    for (let i = 0; i < files.length; i++) {
 | 
				
			||||||
    const file = files.item(i);
 | 
					      const file = files.item(i)
 | 
				
			||||||
    console.log("Got file", file.name)
 | 
					      console.log("Got file", file.name)
 | 
				
			||||||
    try {
 | 
					      try {
 | 
				
			||||||
      state.imageUploadManager.uploadImageAndApply(file, tags);
 | 
					        state.imageUploadManager.uploadImageAndApply(file, tags)
 | 
				
			||||||
    } catch (e) {
 | 
					      } catch (e) {
 | 
				
			||||||
      alert(e);
 | 
					        alert(e)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
<LoginToggle {state}>
 | 
					<LoginToggle {state}>
 | 
				
			||||||
 | 
					 | 
				
			||||||
  <Tr slot="not-logged-in" t={t.pleaseLogin} />
 | 
					  <Tr slot="not-logged-in" t={t.pleaseLogin} />
 | 
				
			||||||
  <div class="flex flex-col">
 | 
					  <div class="flex flex-col">
 | 
				
			||||||
 | 
					 | 
				
			||||||
    <UploadingImageCounter {state} {tags} />
 | 
					    <UploadingImageCounter {state} {tags} />
 | 
				
			||||||
    <FileSelector accept="image/*" cls="button border-2 text-2xl" multiple={true}
 | 
					    <FileSelector
 | 
				
			||||||
                  on:submit={e => handleFiles(e.detail)}>
 | 
					      accept="image/*"
 | 
				
			||||||
 | 
					      cls="button border-2 text-2xl"
 | 
				
			||||||
 | 
					      multiple={true}
 | 
				
			||||||
 | 
					      on:submit={(e) => handleFiles(e.detail)}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
      <div class="flex items-center">
 | 
					      <div class="flex items-center">
 | 
				
			||||||
 | 
					 | 
				
			||||||
        {#if image !== undefined}
 | 
					        {#if image !== undefined}
 | 
				
			||||||
          <img src={image} />
 | 
					          <img src={image} />
 | 
				
			||||||
        {:else}
 | 
					        {:else}
 | 
				
			||||||
          <ToSvelte construct={ Svg.camera_plus_svg().SetClass("block w-12 h-12 p-1 text-4xl ")} />
 | 
					          <ToSvelte construct={Svg.camera_plus_svg().SetClass("block w-12 h-12 p-1 text-4xl ")} />
 | 
				
			||||||
        {/if}
 | 
					        {/if}
 | 
				
			||||||
        {#if labelText}
 | 
					        {#if labelText}
 | 
				
			||||||
          {labelText}
 | 
					          {labelText}
 | 
				
			||||||
| 
						 | 
					@ -68,10 +68,14 @@ function handleFiles(files: FileList) {
 | 
				
			||||||
    </FileSelector>
 | 
					    </FileSelector>
 | 
				
			||||||
    <div class="text-sm">
 | 
					    <div class="text-sm">
 | 
				
			||||||
      <Tr t={t.respectPrivacy} />
 | 
					      <Tr t={t.respectPrivacy} />
 | 
				
			||||||
      <a class="cursor-pointer" on:click={() => {state.guistate.openUsersettings("picture-license")}}>
 | 
					      <a
 | 
				
			||||||
        <Tr t={t.currentLicense.Subs({license: $licenseStore})} />
 | 
					        class="cursor-pointer"
 | 
				
			||||||
 | 
					        on:click={() => {
 | 
				
			||||||
 | 
					          state.guistate.openUsersettings("picture-license")
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <Tr t={t.currentLicense.Subs({ license: $licenseStore })} />
 | 
				
			||||||
      </a>
 | 
					      </a>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					 | 
				
			||||||
</LoginToggle>
 | 
					</LoginToggle>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,32 +1,28 @@
 | 
				
			||||||
<script lang="ts">/**
 | 
					<script lang="ts">
 | 
				
			||||||
 * Shows information about how much images are uploaded for the given feature
 | 
					  /**
 | 
				
			||||||
 */
 | 
					   * Shows information about how much images are uploaded for the given feature
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { SpecialVisualizationState } from "../SpecialVisualization";
 | 
					  import type { SpecialVisualizationState } from "../SpecialVisualization"
 | 
				
			||||||
import { Store } from "../../Logic/UIEventSource";
 | 
					  import { Store } from "../../Logic/UIEventSource"
 | 
				
			||||||
import type { OsmTags } from "../../Models/OsmFeature";
 | 
					  import type { OsmTags } from "../../Models/OsmFeature"
 | 
				
			||||||
import Translations from "../i18n/Translations";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
import Tr from "../Base/Tr.svelte";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
import Loading from "../Base/Loading.svelte";
 | 
					  import Loading from "../Base/Loading.svelte"
 | 
				
			||||||
 | 
					 | 
				
			||||||
export let state: SpecialVisualizationState;
 | 
					 | 
				
			||||||
export let tags: Store<OsmTags>;
 | 
					 | 
				
			||||||
const featureId = tags.data.id;
 | 
					 | 
				
			||||||
const {
 | 
					 | 
				
			||||||
  uploadStarted,
 | 
					 | 
				
			||||||
  uploadFinished,
 | 
					 | 
				
			||||||
  retried,
 | 
					 | 
				
			||||||
  failed
 | 
					 | 
				
			||||||
} = state.imageUploadManager.getCountsFor(featureId);
 | 
					 | 
				
			||||||
const t = Translations.t.image;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export let state: SpecialVisualizationState
 | 
				
			||||||
 | 
					  export let tags: Store<OsmTags>
 | 
				
			||||||
 | 
					  const featureId = tags.data.id
 | 
				
			||||||
 | 
					  const { uploadStarted, uploadFinished, retried, failed } =
 | 
				
			||||||
 | 
					    state.imageUploadManager.getCountsFor(featureId)
 | 
				
			||||||
 | 
					  const t = Translations.t.image
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{#if $uploadStarted == 1}
 | 
					{#if $uploadStarted == 1}
 | 
				
			||||||
  {#if $uploadFinished == 1 }
 | 
					  {#if $uploadFinished == 1}
 | 
				
			||||||
    <Tr cls="thanks" t={t.upload.one.done} />
 | 
					    <Tr cls="thanks" t={t.upload.one.done} />
 | 
				
			||||||
  {:else if $failed == 1}
 | 
					  {:else if $failed == 1}
 | 
				
			||||||
    <div class="flex flex-col alert">
 | 
					    <div class="alert flex flex-col">
 | 
				
			||||||
      <Tr cls="self-center" t={t.upload.one.failed} />
 | 
					      <Tr cls="self-center" t={t.upload.one.failed} />
 | 
				
			||||||
      <Tr t={t.upload.failReasons} />
 | 
					      <Tr t={t.upload.failReasons} />
 | 
				
			||||||
      <Tr t={t.upload.failReasonsAdvanced} />
 | 
					      <Tr t={t.upload.failReasonsAdvanced} />
 | 
				
			||||||
| 
						 | 
					@ -35,30 +31,34 @@ const t = Translations.t.image;
 | 
				
			||||||
    <Loading cls="alert">
 | 
					    <Loading cls="alert">
 | 
				
			||||||
      <Tr t={t.upload.one.retrying} />
 | 
					      <Tr t={t.upload.one.retrying} />
 | 
				
			||||||
    </Loading>
 | 
					    </Loading>
 | 
				
			||||||
  {:else }
 | 
					  {:else}
 | 
				
			||||||
    <Loading cls="alert">
 | 
					    <Loading cls="alert">
 | 
				
			||||||
      <Tr t={t.upload.one.uploading} />
 | 
					      <Tr t={t.upload.one.uploading} />
 | 
				
			||||||
    </Loading>
 | 
					    </Loading>
 | 
				
			||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
{:else if $uploadStarted > 1}
 | 
					{:else if $uploadStarted > 1}
 | 
				
			||||||
  {#if ($uploadFinished + $failed) == $uploadStarted && $uploadFinished > 0}
 | 
					  {#if $uploadFinished + $failed == $uploadStarted && $uploadFinished > 0}
 | 
				
			||||||
    <Tr cls="thanks" t={t.upload.multiple.done.Subs({count: $uploadFinished})} />
 | 
					    <Tr cls="thanks" t={t.upload.multiple.done.Subs({ count: $uploadFinished })} />
 | 
				
			||||||
  {:else if $uploadFinished == 0}
 | 
					  {:else if $uploadFinished == 0}
 | 
				
			||||||
    <Loading cls="alert">
 | 
					    <Loading cls="alert">
 | 
				
			||||||
      <Tr t={t.upload.multiple.uploading.Subs({count: $uploadStarted})} />
 | 
					      <Tr t={t.upload.multiple.uploading.Subs({ count: $uploadStarted })} />
 | 
				
			||||||
    </Loading>
 | 
					    </Loading>
 | 
				
			||||||
  {:else if $uploadFinished > 0}
 | 
					  {:else if $uploadFinished > 0}
 | 
				
			||||||
    <Loading cls="alert">
 | 
					    <Loading cls="alert">
 | 
				
			||||||
      <Tr t={t.upload.multiple.partiallyDone.Subs({count: $uploadStarted -  $uploadFinished, done: $uploadFinished})} />
 | 
					      <Tr
 | 
				
			||||||
 | 
					        t={t.upload.multiple.partiallyDone.Subs({
 | 
				
			||||||
 | 
					          count: $uploadStarted - $uploadFinished,
 | 
				
			||||||
 | 
					          done: $uploadFinished,
 | 
				
			||||||
 | 
					        })}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
    </Loading>
 | 
					    </Loading>
 | 
				
			||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
  {#if $failed > 0}
 | 
					  {#if $failed > 0}
 | 
				
			||||||
    <div class="flex flex-col alert">
 | 
					    <div class="alert flex flex-col">
 | 
				
			||||||
      {#if failed === 1}
 | 
					      {#if failed === 1}
 | 
				
			||||||
        <Tr cls="self-center" t={t.upload.one.failed} />
 | 
					        <Tr cls="self-center" t={t.upload.one.failed} />
 | 
				
			||||||
      {:else}
 | 
					      {:else}
 | 
				
			||||||
        <Tr cls="self-center" t={t.upload.multiple.someFailed.Subs({count: $failed})} />
 | 
					        <Tr cls="self-center" t={t.upload.multiple.someFailed.Subs({ count: $failed })} />
 | 
				
			||||||
 | 
					 | 
				
			||||||
      {/if}
 | 
					      {/if}
 | 
				
			||||||
      <Tr t={t.upload.failReasons} />
 | 
					      <Tr t={t.upload.failReasons} />
 | 
				
			||||||
      <Tr t={t.upload.failReasonsAdvanced} />
 | 
					      <Tr t={t.upload.failReasonsAdvanced} />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -432,7 +432,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        await this.awaitStyleIsLoaded()
 | 
					        await this.awaitStyleIsLoaded()
 | 
				
			||||||
        if(this._currentRasterLayer !== background?.id){
 | 
					        if (this._currentRasterLayer !== background?.id) {
 | 
				
			||||||
            this.removeCurrentLayer(map)
 | 
					            this.removeCurrentLayer(map)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this._currentRasterLayer = background?.id
 | 
					        this._currentRasterLayer = background?.id
 | 
				
			||||||
| 
						 | 
					@ -459,10 +459,10 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
 | 
				
			||||||
            map.rotateTo(0, { duration: 0 })
 | 
					            map.rotateTo(0, { duration: 0 })
 | 
				
			||||||
            map.setPitch(0)
 | 
					            map.setPitch(0)
 | 
				
			||||||
            map.dragRotate.disable()
 | 
					            map.dragRotate.disable()
 | 
				
			||||||
            map.touchZoomRotate.disableRotation();
 | 
					            map.touchZoomRotate.disableRotation()
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            map.dragRotate.enable()
 | 
					            map.dragRotate.enable()
 | 
				
			||||||
            map.touchZoomRotate.enableRotation();
 | 
					            map.touchZoomRotate.enableRotation()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,76 +1,79 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import Translations from "../i18n/Translations";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
  import Tr from "../Base/Tr.svelte";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
  import PlantNetSpeciesList from "./PlantNetSpeciesList.svelte";
 | 
					  import PlantNetSpeciesList from "./PlantNetSpeciesList.svelte"
 | 
				
			||||||
  import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource";
 | 
					  import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource"
 | 
				
			||||||
  import type { PlantNetSpeciesMatch } from "../../Logic/Web/PlantNet";
 | 
					  import type { PlantNetSpeciesMatch } from "../../Logic/Web/PlantNet"
 | 
				
			||||||
  import PlantNet from "../../Logic/Web/PlantNet";
 | 
					  import PlantNet from "../../Logic/Web/PlantNet"
 | 
				
			||||||
  import { XCircleIcon } from "@babeard/svelte-heroicons/solid";
 | 
					  import { XCircleIcon } from "@babeard/svelte-heroicons/solid"
 | 
				
			||||||
  import BackButton from "../Base/BackButton.svelte";
 | 
					  import BackButton from "../Base/BackButton.svelte"
 | 
				
			||||||
  import NextButton from "../Base/NextButton.svelte";
 | 
					  import NextButton from "../Base/NextButton.svelte"
 | 
				
			||||||
  import WikipediaPanel from "../Wikipedia/WikipediaPanel.svelte";
 | 
					  import WikipediaPanel from "../Wikipedia/WikipediaPanel.svelte"
 | 
				
			||||||
  import { createEventDispatcher } from "svelte";
 | 
					  import { createEventDispatcher } from "svelte"
 | 
				
			||||||
  import ToSvelte from "../Base/ToSvelte.svelte";
 | 
					  import ToSvelte from "../Base/ToSvelte.svelte"
 | 
				
			||||||
  import Svg from "../../Svg";
 | 
					  import Svg from "../../Svg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * The main entry point for the plantnet wizard
 | 
					   * The main entry point for the plantnet wizard
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  const t = Translations.t.plantDetection;
 | 
					  const t = Translations.t.plantDetection
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * All the URLs pointing to images of the selected feature.
 | 
					   * All the URLs pointing to images of the selected feature.
 | 
				
			||||||
   * We need to feed them into Plantnet when applicable
 | 
					   * We need to feed them into Plantnet when applicable
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  export let imageUrls: Store<string[]>;
 | 
					  export let imageUrls: Store<string[]>
 | 
				
			||||||
  export let onConfirm: (wikidataId: string) => void;
 | 
					  export let onConfirm: (wikidataId: string) => void
 | 
				
			||||||
  const dispatch = createEventDispatcher<{ selected: string }>();
 | 
					  const dispatch = createEventDispatcher<{ selected: string }>()
 | 
				
			||||||
  let collapsedMode = true;
 | 
					  let collapsedMode = true
 | 
				
			||||||
  let options: UIEventSource<PlantNetSpeciesMatch[]> = new UIEventSource<PlantNetSpeciesMatch[]>(undefined);
 | 
					  let options: UIEventSource<PlantNetSpeciesMatch[]> = new UIEventSource<PlantNetSpeciesMatch[]>(
 | 
				
			||||||
 | 
					    undefined
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let error: string = undefined;
 | 
					  let error: string = undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * The Wikidata-id of the species to apply
 | 
					   * The Wikidata-id of the species to apply
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  let selectedOption: string;
 | 
					  let selectedOption: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let done = false;
 | 
					  let done = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function speciesSelected(species: PlantNetSpeciesMatch) {
 | 
					  function speciesSelected(species: PlantNetSpeciesMatch) {
 | 
				
			||||||
    console.log("Selected:", species);
 | 
					    console.log("Selected:", species)
 | 
				
			||||||
    selectedOption = species;
 | 
					    selectedOption = species
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function detectSpecies() {
 | 
					  async function detectSpecies() {
 | 
				
			||||||
    collapsedMode = false;
 | 
					    collapsedMode = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
 | 
					      const result = await PlantNet.query(imageUrls.data.slice(0, 5))
 | 
				
			||||||
      const result = await PlantNet.query(imageUrls.data.slice(0, 5));
 | 
					      options.set(result.results.filter((r) => r.score > 0.005).slice(0, 8))
 | 
				
			||||||
      options.set(result.results.filter(r => r.score > 0.005).slice(0, 8));
 | 
					 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
      error = e;
 | 
					      error = e
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="flex flex-col">
 | 
					<div class="flex flex-col">
 | 
				
			||||||
 | 
					 | 
				
			||||||
  {#if collapsedMode}
 | 
					  {#if collapsedMode}
 | 
				
			||||||
    <button class="w-full" on:click={detectSpecies}>
 | 
					    <button class="w-full" on:click={detectSpecies}>
 | 
				
			||||||
      <Tr t={t.button} />
 | 
					      <Tr t={t.button} />
 | 
				
			||||||
    </button>
 | 
					    </button>
 | 
				
			||||||
  {:else if $error !== undefined}
 | 
					  {:else if $error !== undefined}
 | 
				
			||||||
    <Tr cls="alert" t={t.error.Subs({error})} />
 | 
					    <Tr cls="alert" t={t.error.Subs({ error })} />
 | 
				
			||||||
  {:else if $imageUrls.length === 0}
 | 
					  {:else if $imageUrls.length === 0}
 | 
				
			||||||
    <!-- No urls are available, show the explanation instead-->
 | 
					    <!-- No urls are available, show the explanation instead-->
 | 
				
			||||||
    <div class=" border-region p-2 mb-1 relative">
 | 
					    <div class=" border-region relative mb-1 p-2">
 | 
				
			||||||
      <XCircleIcon class="absolute top-0 right-0 w-8 h-8 m-4 cursor-pointer"
 | 
					      <XCircleIcon
 | 
				
			||||||
                   on:click={() => {collapsedMode = true}}></XCircleIcon>
 | 
					        class="absolute top-0 right-0 m-4 h-8 w-8 cursor-pointer"
 | 
				
			||||||
 | 
					        on:click={() => {
 | 
				
			||||||
 | 
					          collapsedMode = true
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
      <Tr t={t.takeImages} />
 | 
					      <Tr t={t.takeImages} />
 | 
				
			||||||
      <Tr t={ t.howTo.intro} />
 | 
					      <Tr t={t.howTo.intro} />
 | 
				
			||||||
      <ul>
 | 
					      <ul>
 | 
				
			||||||
        <li>
 | 
					        <li>
 | 
				
			||||||
          <Tr t={t.howTo.li0} />
 | 
					          <Tr t={t.howTo.li0} />
 | 
				
			||||||
| 
						 | 
					@ -87,23 +90,39 @@
 | 
				
			||||||
      </ul>
 | 
					      </ul>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  {:else if selectedOption === undefined}
 | 
					  {:else if selectedOption === undefined}
 | 
				
			||||||
    <PlantNetSpeciesList {options} numberOfImages={$imageUrls.length}
 | 
					    <PlantNetSpeciesList
 | 
				
			||||||
                         on:selected={(species) => speciesSelected(species.detail)}>
 | 
					      {options}
 | 
				
			||||||
      <XCircleIcon slot="upper-right" class="w-8 h-8 m-4 cursor-pointer"
 | 
					      numberOfImages={$imageUrls.length}
 | 
				
			||||||
                   on:click={() => {collapsedMode = true}}></XCircleIcon>
 | 
					      on:selected={(species) => speciesSelected(species.detail)}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <XCircleIcon
 | 
				
			||||||
 | 
					        slot="upper-right"
 | 
				
			||||||
 | 
					        class="m-4 h-8 w-8 cursor-pointer"
 | 
				
			||||||
 | 
					        on:click={() => {
 | 
				
			||||||
 | 
					          collapsedMode = true
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
    </PlantNetSpeciesList>
 | 
					    </PlantNetSpeciesList>
 | 
				
			||||||
  {:else if !done}
 | 
					  {:else if !done}
 | 
				
			||||||
    <div class="flex flex-col border-interactive">
 | 
					    <div class="border-interactive flex flex-col">
 | 
				
			||||||
      <div class="m-2">
 | 
					      <div class="m-2">
 | 
				
			||||||
 | 
					 | 
				
			||||||
        <WikipediaPanel wikiIds={new ImmutableStore([selectedOption])} />
 | 
					        <WikipediaPanel wikiIds={new ImmutableStore([selectedOption])} />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="flex flex-col items-stretch">
 | 
					      <div class="flex flex-col items-stretch">
 | 
				
			||||||
        <BackButton on:click={() => {selectedOption = undefined}}>
 | 
					        <BackButton
 | 
				
			||||||
 | 
					          on:click={() => {
 | 
				
			||||||
 | 
					            selectedOption = undefined
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
          <Tr t={t.back} />
 | 
					          <Tr t={t.back} />
 | 
				
			||||||
        </BackButton>
 | 
					        </BackButton>
 | 
				
			||||||
        <NextButton clss="primary" on:click={() => { done = true; onConfirm(selectedOption); }} >
 | 
					        <NextButton
 | 
				
			||||||
 | 
					          clss="primary"
 | 
				
			||||||
 | 
					          on:click={() => {
 | 
				
			||||||
 | 
					            done = true
 | 
				
			||||||
 | 
					            onConfirm(selectedOption)
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
          <Tr t={t.confirm} />
 | 
					          <Tr t={t.confirm} />
 | 
				
			||||||
        </NextButton>
 | 
					        </NextButton>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
| 
						 | 
					@ -111,13 +130,21 @@
 | 
				
			||||||
  {:else}
 | 
					  {:else}
 | 
				
			||||||
    <!-- done ! -->
 | 
					    <!-- done ! -->
 | 
				
			||||||
    <Tr t={t.done} cls="thanks w-full" />
 | 
					    <Tr t={t.done} cls="thanks w-full" />
 | 
				
			||||||
    <BackButton imageClass="w-6 h-6 shrink-0" clss="p-1 m-0" on:click={() => {done = false; selectedOption = undefined}}>
 | 
					    <BackButton
 | 
				
			||||||
 | 
					      imageClass="w-6 h-6 shrink-0"
 | 
				
			||||||
 | 
					      clss="p-1 m-0"
 | 
				
			||||||
 | 
					      on:click={() => {
 | 
				
			||||||
 | 
					        done = false
 | 
				
			||||||
 | 
					        selectedOption = undefined
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
      <Tr t={t.tryAgain} />
 | 
					      <Tr t={t.tryAgain} />
 | 
				
			||||||
    </BackButton>
 | 
					    </BackButton>
 | 
				
			||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
  <div class="flex p-2 low-interaction rounded-xl self-end">
 | 
					  <div class="low-interaction flex self-end rounded-xl p-2">
 | 
				
			||||||
    <ToSvelte construct={Svg.plantnet_logo_svg().SetClass("w-8 h-8 p-1 mr-1 bg-white rounded-full")} />
 | 
					    <ToSvelte
 | 
				
			||||||
 | 
					      construct={Svg.plantnet_logo_svg().SetClass("w-8 h-8 p-1 mr-1 bg-white rounded-full")}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
    <Tr t={t.poweredByPlantnet} />
 | 
					    <Tr t={t.poweredByPlantnet} />
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,29 +1,28 @@
 | 
				
			||||||
<script lang="ts">/**
 | 
					<script lang="ts">
 | 
				
			||||||
 * Show the list of options to choose from
 | 
					  /**
 | 
				
			||||||
 */
 | 
					   * Show the list of options to choose from
 | 
				
			||||||
import type { PlantNetSpeciesMatch } from "../../Logic/Web/PlantNet";
 | 
					   */
 | 
				
			||||||
import { Store } from "../../Logic/UIEventSource";
 | 
					  import type { PlantNetSpeciesMatch } from "../../Logic/Web/PlantNet"
 | 
				
			||||||
import Translations from "../i18n/Translations";
 | 
					  import { Store } from "../../Logic/UIEventSource"
 | 
				
			||||||
import Tr from "../Base/Tr.svelte";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
import Loading from "../Base/Loading.svelte";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
import SpeciesButton from "./SpeciesButton.svelte";
 | 
					  import Loading from "../Base/Loading.svelte"
 | 
				
			||||||
 | 
					  import SpeciesButton from "./SpeciesButton.svelte"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const t = Translations.t.plantDetection;
 | 
					  const t = Translations.t.plantDetection
 | 
				
			||||||
 | 
					 | 
				
			||||||
export let options: Store<PlantNetSpeciesMatch[]>;
 | 
					 | 
				
			||||||
export let numberOfImages: number;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export let options: Store<PlantNetSpeciesMatch[]>
 | 
				
			||||||
 | 
					  export let numberOfImages: number
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{#if $options === undefined}
 | 
					{#if $options === undefined}
 | 
				
			||||||
  <Loading>
 | 
					  <Loading>
 | 
				
			||||||
    <Tr t={t.querying.Subs({length: numberOfImages})} />
 | 
					    <Tr t={t.querying.Subs({ length: numberOfImages })} />
 | 
				
			||||||
  </Loading>
 | 
					  </Loading>
 | 
				
			||||||
{:else}
 | 
					{:else}
 | 
				
			||||||
  <div class="low-interaction border-interactive flex p-2 flex-col relative">
 | 
					  <div class="low-interaction border-interactive relative flex flex-col p-2">
 | 
				
			||||||
    <div class="absolute top-0 right-0" >
 | 
					    <div class="absolute top-0 right-0">
 | 
				
			||||||
      
 | 
					      <slot name="upper-right" />
 | 
				
			||||||
    <slot name="upper-right"/>
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <h3>
 | 
					    <h3>
 | 
				
			||||||
      <Tr t={t.overviewTitle} />
 | 
					      <Tr t={t.overviewTitle} />
 | 
				
			||||||
| 
						 | 
					@ -31,7 +30,7 @@ export let numberOfImages: number;
 | 
				
			||||||
    <Tr t={t.overviewIntro} />
 | 
					    <Tr t={t.overviewIntro} />
 | 
				
			||||||
    <Tr cls="font-bold" t={t.overviewVerify} />
 | 
					    <Tr cls="font-bold" t={t.overviewVerify} />
 | 
				
			||||||
    {#each $options as species}
 | 
					    {#each $options as species}
 | 
				
			||||||
      <SpeciesButton {species} on:selected/>
 | 
					      <SpeciesButton {species} on:selected />
 | 
				
			||||||
      {/each}
 | 
					    {/each}
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,54 +1,61 @@
 | 
				
			||||||
<script lang="ts">/**
 | 
					<script lang="ts">
 | 
				
			||||||
 * A button to select a single species
 | 
					  /**
 | 
				
			||||||
 */
 | 
					   * A button to select a single species
 | 
				
			||||||
import { createEventDispatcher } from "svelte";
 | 
					   */
 | 
				
			||||||
import type { PlantNetSpeciesMatch } from "../../Logic/Web/PlantNet";
 | 
					  import { createEventDispatcher } from "svelte"
 | 
				
			||||||
import { UIEventSource } from "../../Logic/UIEventSource";
 | 
					  import type { PlantNetSpeciesMatch } from "../../Logic/Web/PlantNet"
 | 
				
			||||||
import Wikidata from "../../Logic/Web/Wikidata";
 | 
					  import { UIEventSource } from "../../Logic/UIEventSource"
 | 
				
			||||||
import NextButton from "../Base/NextButton.svelte";
 | 
					  import Wikidata from "../../Logic/Web/Wikidata"
 | 
				
			||||||
import Loading from "../Base/Loading.svelte";
 | 
					  import NextButton from "../Base/NextButton.svelte"
 | 
				
			||||||
import WikidataPreviewBox from "../Wikipedia/WikidataPreviewBox";
 | 
					  import Loading from "../Base/Loading.svelte"
 | 
				
			||||||
import Tr from "../Base/Tr.svelte";
 | 
					  import WikidataPreviewBox from "../Wikipedia/WikidataPreviewBox"
 | 
				
			||||||
import Translations from "../i18n/Translations";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
import ToSvelte from "../Base/ToSvelte.svelte";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
 | 
					  import ToSvelte from "../Base/ToSvelte.svelte"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export let species: PlantNetSpeciesMatch;
 | 
					  export let species: PlantNetSpeciesMatch
 | 
				
			||||||
let wikidata = UIEventSource.FromPromise(
 | 
					  let wikidata = UIEventSource.FromPromise(
 | 
				
			||||||
  Wikidata.Sparql<{ species }>(
 | 
					    Wikidata.Sparql<{ species }>(
 | 
				
			||||||
    ["?species", "?speciesLabel"],
 | 
					      ["?species", "?speciesLabel"],
 | 
				
			||||||
    ["?species wdt:P846 \"" + species.gbif.id + "\""]
 | 
					      ['?species wdt:P846 "' + species.gbif.id + '"']
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const dispatch = createEventDispatcher<{ selected: string /* wikidata-id*/ }>();
 | 
					  const dispatch = createEventDispatcher<{ selected: string /* wikidata-id*/ }>()
 | 
				
			||||||
const t = Translations.t.plantDetection;
 | 
					  const t = Translations.t.plantDetection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
/**
 | 
					   * PlantNet give us a GBIF-id, but we want the Wikidata-id instead.
 | 
				
			||||||
 * PlantNet give us a GBIF-id, but we want the Wikidata-id instead.
 | 
					   * We look this up in wikidata
 | 
				
			||||||
 * We look this up in wikidata
 | 
					   */
 | 
				
			||||||
 */
 | 
					  const wikidataId: Store<string> = UIEventSource.FromPromise(
 | 
				
			||||||
const wikidataId: Store<string> = UIEventSource.FromPromise(
 | 
					    Wikidata.Sparql<{ species }>(
 | 
				
			||||||
  Wikidata.Sparql<{ species }>(
 | 
					      ["?species", "?speciesLabel"],
 | 
				
			||||||
    ["?species", "?speciesLabel"],
 | 
					      ['?species wdt:P846 "' + species.gbif.id + '"']
 | 
				
			||||||
    ["?species wdt:P846 \"" + species.gbif.id + "\""]
 | 
					    )
 | 
				
			||||||
  )
 | 
					  ).mapD((wd) => wd[0]?.species?.value)
 | 
				
			||||||
).mapD(wd => wd[0]?.species?.value);
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<NextButton on:click={() => dispatch("selected", $wikidataId)}>
 | 
					<NextButton on:click={() => dispatch("selected", $wikidataId)}>
 | 
				
			||||||
  {#if $wikidata === undefined}
 | 
					  {#if $wikidata === undefined}
 | 
				
			||||||
    <Loading>
 | 
					    <Loading>
 | 
				
			||||||
      <Tr t={ t.loadingWikidata.Subs({
 | 
					      <Tr
 | 
				
			||||||
        species: species.species.scientificNameWithoutAuthor,
 | 
					        t={t.loadingWikidata.Subs({
 | 
				
			||||||
      })} />
 | 
					          species: species.species.scientificNameWithoutAuthor,
 | 
				
			||||||
 | 
					        })}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
    </Loading>
 | 
					    </Loading>
 | 
				
			||||||
  {:else}
 | 
					  {:else}
 | 
				
			||||||
    <ToSvelte construct={() => new WikidataPreviewBox(wikidataId,
 | 
					    <ToSvelte
 | 
				
			||||||
     { imageStyle: "max-width: 8rem; width: unset; height: 8rem",
 | 
					      construct={() =>
 | 
				
			||||||
     extraItems: [t.matchPercentage
 | 
					        new WikidataPreviewBox(wikidataId, {
 | 
				
			||||||
  .Subs({ match: Math.round(species.score * 100) })
 | 
					          imageStyle: "max-width: 8rem; width: unset; height: 8rem",
 | 
				
			||||||
  .SetClass("thanks w-fit self-center")]
 | 
					          extraItems: [
 | 
				
			||||||
     }).SetClass("w-full")}></ToSvelte>
 | 
					            t.matchPercentage
 | 
				
			||||||
 | 
					              .Subs({ match: Math.round(species.score * 100) })
 | 
				
			||||||
 | 
					              .SetClass("thanks w-fit self-center"),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        }).SetClass("w-full")}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
</NextButton>
 | 
					</NextButton>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,109 +3,109 @@
 | 
				
			||||||
   * This component ties together all the steps that are needed to create a new point.
 | 
					   * This component ties together all the steps that are needed to create a new point.
 | 
				
			||||||
   * There are many subcomponents which help with that
 | 
					   * There are many subcomponents which help with that
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  import type { SpecialVisualizationState } from "../../SpecialVisualization";
 | 
					  import type { SpecialVisualizationState } from "../../SpecialVisualization"
 | 
				
			||||||
  import PresetList from "./PresetList.svelte";
 | 
					  import PresetList from "./PresetList.svelte"
 | 
				
			||||||
  import type PresetConfig from "../../../Models/ThemeConfig/PresetConfig";
 | 
					  import type PresetConfig from "../../../Models/ThemeConfig/PresetConfig"
 | 
				
			||||||
  import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
 | 
					  import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
 | 
				
			||||||
  import Tr from "../../Base/Tr.svelte";
 | 
					  import Tr from "../../Base/Tr.svelte"
 | 
				
			||||||
  import SubtleButton from "../../Base/SubtleButton.svelte";
 | 
					  import SubtleButton from "../../Base/SubtleButton.svelte"
 | 
				
			||||||
  import FromHtml from "../../Base/FromHtml.svelte";
 | 
					  import FromHtml from "../../Base/FromHtml.svelte"
 | 
				
			||||||
  import Translations from "../../i18n/Translations.js";
 | 
					  import Translations from "../../i18n/Translations.js"
 | 
				
			||||||
  import TagHint from "../TagHint.svelte";
 | 
					  import TagHint from "../TagHint.svelte"
 | 
				
			||||||
  import { And } from "../../../Logic/Tags/And.js";
 | 
					  import { And } from "../../../Logic/Tags/And.js"
 | 
				
			||||||
  import LoginToggle from "../../Base/LoginToggle.svelte";
 | 
					  import LoginToggle from "../../Base/LoginToggle.svelte"
 | 
				
			||||||
  import Constants from "../../../Models/Constants.js";
 | 
					  import Constants from "../../../Models/Constants.js"
 | 
				
			||||||
  import FilteredLayer from "../../../Models/FilteredLayer";
 | 
					  import FilteredLayer from "../../../Models/FilteredLayer"
 | 
				
			||||||
  import { Store, UIEventSource } from "../../../Logic/UIEventSource";
 | 
					  import { Store, UIEventSource } from "../../../Logic/UIEventSource"
 | 
				
			||||||
  import { EyeIcon, EyeOffIcon } from "@rgossiaux/svelte-heroicons/solid";
 | 
					  import { EyeIcon, EyeOffIcon } from "@rgossiaux/svelte-heroicons/solid"
 | 
				
			||||||
  import LoginButton from "../../Base/LoginButton.svelte";
 | 
					  import LoginButton from "../../Base/LoginButton.svelte"
 | 
				
			||||||
  import NewPointLocationInput from "../../BigComponents/NewPointLocationInput.svelte";
 | 
					  import NewPointLocationInput from "../../BigComponents/NewPointLocationInput.svelte"
 | 
				
			||||||
  import CreateNewNodeAction from "../../../Logic/Osm/Actions/CreateNewNodeAction";
 | 
					  import CreateNewNodeAction from "../../../Logic/Osm/Actions/CreateNewNodeAction"
 | 
				
			||||||
  import { OsmWay } from "../../../Logic/Osm/OsmObject";
 | 
					  import { OsmWay } from "../../../Logic/Osm/OsmObject"
 | 
				
			||||||
  import { Tag } from "../../../Logic/Tags/Tag";
 | 
					  import { Tag } from "../../../Logic/Tags/Tag"
 | 
				
			||||||
  import type { WayId } from "../../../Models/OsmFeature";
 | 
					  import type { WayId } from "../../../Models/OsmFeature"
 | 
				
			||||||
  import Loading from "../../Base/Loading.svelte";
 | 
					  import Loading from "../../Base/Loading.svelte"
 | 
				
			||||||
  import type { GlobalFilter } from "../../../Models/GlobalFilter";
 | 
					  import type { GlobalFilter } from "../../../Models/GlobalFilter"
 | 
				
			||||||
  import { onDestroy } from "svelte";
 | 
					  import { onDestroy } from "svelte"
 | 
				
			||||||
  import NextButton from "../../Base/NextButton.svelte";
 | 
					  import NextButton from "../../Base/NextButton.svelte"
 | 
				
			||||||
  import BackButton from "../../Base/BackButton.svelte";
 | 
					  import BackButton from "../../Base/BackButton.svelte"
 | 
				
			||||||
  import ToSvelte from "../../Base/ToSvelte.svelte";
 | 
					  import ToSvelte from "../../Base/ToSvelte.svelte"
 | 
				
			||||||
  import Svg from "../../../Svg";
 | 
					  import Svg from "../../../Svg"
 | 
				
			||||||
  import OpenBackgroundSelectorButton from "../../BigComponents/OpenBackgroundSelectorButton.svelte";
 | 
					  import OpenBackgroundSelectorButton from "../../BigComponents/OpenBackgroundSelectorButton.svelte"
 | 
				
			||||||
  import { twJoin } from "tailwind-merge";
 | 
					  import { twJoin } from "tailwind-merge"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let coordinate: { lon: number; lat: number };
 | 
					  export let coordinate: { lon: number; lat: number }
 | 
				
			||||||
  export let state: SpecialVisualizationState;
 | 
					  export let state: SpecialVisualizationState
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let selectedPreset: {
 | 
					  let selectedPreset: {
 | 
				
			||||||
    preset: PresetConfig
 | 
					    preset: PresetConfig
 | 
				
			||||||
    layer: LayerConfig
 | 
					    layer: LayerConfig
 | 
				
			||||||
    icon: string
 | 
					    icon: string
 | 
				
			||||||
    tags: Record<string, string>
 | 
					    tags: Record<string, string>
 | 
				
			||||||
  } = undefined;
 | 
					  } = undefined
 | 
				
			||||||
  let checkedOfGlobalFilters: number = 0;
 | 
					  let checkedOfGlobalFilters: number = 0
 | 
				
			||||||
  let confirmedCategory = false;
 | 
					  let confirmedCategory = false
 | 
				
			||||||
  $: if (selectedPreset === undefined) {
 | 
					  $: if (selectedPreset === undefined) {
 | 
				
			||||||
    confirmedCategory = false;
 | 
					    confirmedCategory = false
 | 
				
			||||||
    creating = false;
 | 
					    creating = false
 | 
				
			||||||
    checkedOfGlobalFilters = 0;
 | 
					    checkedOfGlobalFilters = 0
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let flayer: FilteredLayer = undefined;
 | 
					  let flayer: FilteredLayer = undefined
 | 
				
			||||||
  let layerIsDisplayed: UIEventSource<boolean> | undefined = undefined;
 | 
					  let layerIsDisplayed: UIEventSource<boolean> | undefined = undefined
 | 
				
			||||||
  let layerHasFilters: Store<boolean> | undefined = undefined;
 | 
					  let layerHasFilters: Store<boolean> | undefined = undefined
 | 
				
			||||||
  let globalFilter: UIEventSource<GlobalFilter[]> = state.layerState.globalFilters;
 | 
					  let globalFilter: UIEventSource<GlobalFilter[]> = state.layerState.globalFilters
 | 
				
			||||||
  let _globalFilter: GlobalFilter[] = [];
 | 
					  let _globalFilter: GlobalFilter[] = []
 | 
				
			||||||
  onDestroy(
 | 
					  onDestroy(
 | 
				
			||||||
    globalFilter.addCallbackAndRun((globalFilter) => {
 | 
					    globalFilter.addCallbackAndRun((globalFilter) => {
 | 
				
			||||||
      console.log("Global filters are", globalFilter);
 | 
					      console.log("Global filters are", globalFilter)
 | 
				
			||||||
      _globalFilter = globalFilter ?? [];
 | 
					      _globalFilter = globalFilter ?? []
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  );
 | 
					  )
 | 
				
			||||||
  $: {
 | 
					  $: {
 | 
				
			||||||
    flayer = state.layerState.filteredLayers.get(selectedPreset?.layer?.id);
 | 
					    flayer = state.layerState.filteredLayers.get(selectedPreset?.layer?.id)
 | 
				
			||||||
    layerIsDisplayed = flayer?.isDisplayed;
 | 
					    layerIsDisplayed = flayer?.isDisplayed
 | 
				
			||||||
    layerHasFilters = flayer?.hasFilter;
 | 
					    layerHasFilters = flayer?.hasFilter
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  const t = Translations.t.general.add;
 | 
					  const t = Translations.t.general.add
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const zoom = state.mapProperties.zoom;
 | 
					  const zoom = state.mapProperties.zoom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const isLoading = state.dataIsLoading;
 | 
					  const isLoading = state.dataIsLoading
 | 
				
			||||||
  let preciseCoordinate: UIEventSource<{ lon: number; lat: number }> = new UIEventSource(undefined);
 | 
					  let preciseCoordinate: UIEventSource<{ lon: number; lat: number }> = new UIEventSource(undefined)
 | 
				
			||||||
  let snappedToObject: UIEventSource<string> = new UIEventSource<string>(undefined);
 | 
					  let snappedToObject: UIEventSource<string> = new UIEventSource<string>(undefined)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Small helper variable: if the map is tapped, we should let the 'Next'-button grab some attention as users have to click _that_ to continue, not the map
 | 
					  // Small helper variable: if the map is tapped, we should let the 'Next'-button grab some attention as users have to click _that_ to continue, not the map
 | 
				
			||||||
  let preciseInputIsTapped = false;
 | 
					  let preciseInputIsTapped = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let creating = false;
 | 
					  let creating = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Call when the user should restart the flow by clicking on the map, e.g. because they disabled filters.
 | 
					   * Call when the user should restart the flow by clicking on the map, e.g. because they disabled filters.
 | 
				
			||||||
   * Will delete the lastclick-location
 | 
					   * Will delete the lastclick-location
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  function abort() {
 | 
					  function abort() {
 | 
				
			||||||
    state.selectedElement.setData(undefined);
 | 
					    state.selectedElement.setData(undefined)
 | 
				
			||||||
    // When aborted, we force the contributors to place the pin _again_
 | 
					    // When aborted, we force the contributors to place the pin _again_
 | 
				
			||||||
    // This is because there might be a nearby object that was disabled; this forces them to re-evaluate the map
 | 
					    // This is because there might be a nearby object that was disabled; this forces them to re-evaluate the map
 | 
				
			||||||
    state.lastClickObject.features.setData([]);
 | 
					    state.lastClickObject.features.setData([])
 | 
				
			||||||
    preciseInputIsTapped = false;
 | 
					    preciseInputIsTapped = false
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function confirm() {
 | 
					  async function confirm() {
 | 
				
			||||||
    creating = true;
 | 
					    creating = true
 | 
				
			||||||
    const location: { lon: number; lat: number } = preciseCoordinate.data;
 | 
					    const location: { lon: number; lat: number } = preciseCoordinate.data
 | 
				
			||||||
    const snapTo: WayId | undefined = <WayId>snappedToObject.data;
 | 
					    const snapTo: WayId | undefined = <WayId>snappedToObject.data
 | 
				
			||||||
    const tags: Tag[] = selectedPreset.preset.tags.concat(
 | 
					    const tags: Tag[] = selectedPreset.preset.tags.concat(
 | 
				
			||||||
      ..._globalFilter.map((f) => f?.onNewPoint?.tags ?? [])
 | 
					      ..._globalFilter.map((f) => f?.onNewPoint?.tags ?? [])
 | 
				
			||||||
    );
 | 
					    )
 | 
				
			||||||
    console.log("Creating new point at", location, "snapped to", snapTo, "with tags", tags);
 | 
					    console.log("Creating new point at", location, "snapped to", snapTo, "with tags", tags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let snapToWay: undefined | OsmWay = undefined;
 | 
					    let snapToWay: undefined | OsmWay = undefined
 | 
				
			||||||
    if (snapTo !== undefined && snapTo !== null) {
 | 
					    if (snapTo !== undefined && snapTo !== null) {
 | 
				
			||||||
      const downloaded = await state.osmObjectDownloader.DownloadObjectAsync(snapTo, 0);
 | 
					      const downloaded = await state.osmObjectDownloader.DownloadObjectAsync(snapTo, 0)
 | 
				
			||||||
      if (downloaded !== "deleted") {
 | 
					      if (downloaded !== "deleted") {
 | 
				
			||||||
        snapToWay = downloaded;
 | 
					        snapToWay = downloaded
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -113,42 +113,44 @@
 | 
				
			||||||
      theme: state.layout?.id ?? "unkown",
 | 
					      theme: state.layout?.id ?? "unkown",
 | 
				
			||||||
      changeType: "create",
 | 
					      changeType: "create",
 | 
				
			||||||
      snapOnto: snapToWay,
 | 
					      snapOnto: snapToWay,
 | 
				
			||||||
      reusePointWithinMeters: 1
 | 
					      reusePointWithinMeters: 1,
 | 
				
			||||||
    });
 | 
					    })
 | 
				
			||||||
    await state.changes.applyAction(newElementAction);
 | 
					    await state.changes.applyAction(newElementAction)
 | 
				
			||||||
    state.newFeatures.features.ping();
 | 
					    state.newFeatures.features.ping()
 | 
				
			||||||
    // The 'changes' should have created a new point, which added this into the 'featureProperties'
 | 
					    // The 'changes' should have created a new point, which added this into the 'featureProperties'
 | 
				
			||||||
    const newId = newElementAction.newElementId;
 | 
					    const newId = newElementAction.newElementId
 | 
				
			||||||
    console.log("Applied pending changes, fetching store for", newId);
 | 
					    console.log("Applied pending changes, fetching store for", newId)
 | 
				
			||||||
    const tagsStore = state.featureProperties.getStore(newId);
 | 
					    const tagsStore = state.featureProperties.getStore(newId)
 | 
				
			||||||
    if (!tagsStore) {
 | 
					    if (!tagsStore) {
 | 
				
			||||||
      console.error("Bug: no tagsStore found for", newId);
 | 
					      console.error("Bug: no tagsStore found for", newId)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      // Set some metainfo
 | 
					      // Set some metainfo
 | 
				
			||||||
      const properties = tagsStore.data;
 | 
					      const properties = tagsStore.data
 | 
				
			||||||
      if (snapTo) {
 | 
					      if (snapTo) {
 | 
				
			||||||
        // metatags (starting with underscore) are not uploaded, so we can safely mark this
 | 
					        // metatags (starting with underscore) are not uploaded, so we can safely mark this
 | 
				
			||||||
        delete properties["_referencing_ways"];
 | 
					        delete properties["_referencing_ways"]
 | 
				
			||||||
        properties["_referencing_ways"] = `["${snapTo}"]`;
 | 
					        properties["_referencing_ways"] = `["${snapTo}"]`
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      properties["_backend"] = state.osmConnection.Backend();
 | 
					      properties["_backend"] = state.osmConnection.Backend()
 | 
				
			||||||
      properties["_last_edit:timestamp"] = new Date().toISOString();
 | 
					      properties["_last_edit:timestamp"] = new Date().toISOString()
 | 
				
			||||||
      const userdetails = state.osmConnection.userDetails.data;
 | 
					      const userdetails = state.osmConnection.userDetails.data
 | 
				
			||||||
      properties["_last_edit:contributor"] = userdetails.name;
 | 
					      properties["_last_edit:contributor"] = userdetails.name
 | 
				
			||||||
      properties["_last_edit:uid"] = "" + userdetails.uid;
 | 
					      properties["_last_edit:uid"] = "" + userdetails.uid
 | 
				
			||||||
      tagsStore.ping();
 | 
					      tagsStore.ping()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const feature = state.indexedFeatures.featuresById.data.get(newId);
 | 
					    const feature = state.indexedFeatures.featuresById.data.get(newId)
 | 
				
			||||||
    console.log("Selecting feature", feature, "and opening their popup");
 | 
					    console.log("Selecting feature", feature, "and opening their popup")
 | 
				
			||||||
    abort();
 | 
					    abort()
 | 
				
			||||||
    state.selectedLayer.setData(selectedPreset.layer);
 | 
					    state.selectedLayer.setData(selectedPreset.layer)
 | 
				
			||||||
    state.selectedElement.setData(feature);
 | 
					    state.selectedElement.setData(feature)
 | 
				
			||||||
    tagsStore.ping();
 | 
					    tagsStore.ping()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function confirmSync() {
 | 
					  function confirmSync() {
 | 
				
			||||||
    confirm().then(_ => console.debug("New point successfully handled")).catch(e => console.error("Handling the new point went wrong due to", e));
 | 
					    confirm()
 | 
				
			||||||
 | 
					      .then((_) => console.debug("New point successfully handled"))
 | 
				
			||||||
 | 
					      .catch((e) => console.error("Handling the new point went wrong due to", e))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@
 | 
				
			||||||
    state.newFeatures.features.data.push(feature)
 | 
					    state.newFeatures.features.data.push(feature)
 | 
				
			||||||
    state.newFeatures.features.ping()
 | 
					    state.newFeatures.features.ping()
 | 
				
			||||||
    state.selectedElement?.setData(feature)
 | 
					    state.selectedElement?.setData(feature)
 | 
				
			||||||
    if(state.featureProperties.trackFeature){
 | 
					    if (state.featureProperties.trackFeature) {
 | 
				
			||||||
      state.featureProperties.trackFeature(feature)
 | 
					      state.featureProperties.trackFeature(feature)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    comment.setData("")
 | 
					    comment.setData("")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,18 +23,20 @@
 | 
				
			||||||
  export let feature: Feature
 | 
					  export let feature: Feature
 | 
				
			||||||
  export let layer: LayerConfig
 | 
					  export let layer: LayerConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let linkable = true;
 | 
					  export let linkable = true
 | 
				
			||||||
  let isLinked = Object.values(tags.data).some(v => image.pictureUrl === v);
 | 
					  let isLinked = Object.values(tags.data).some((v) => image.pictureUrl === v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const t = Translations.t.image.nearby;
 | 
					  const t = Translations.t.image.nearby
 | 
				
			||||||
  const c = [lon, lat];
 | 
					  const c = [lon, lat]
 | 
				
			||||||
  let attributedImage = new AttributedImage({
 | 
					  let attributedImage = new AttributedImage({
 | 
				
			||||||
    url: image.thumbUrl ?? image.pictureUrl,
 | 
					    url: image.thumbUrl ?? image.pictureUrl,
 | 
				
			||||||
    provider: AllImageProviders.byName(image.provider),
 | 
					    provider: AllImageProviders.byName(image.provider),
 | 
				
			||||||
    date: new Date(image.date)
 | 
					    date: new Date(image.date),
 | 
				
			||||||
  });
 | 
					  })
 | 
				
			||||||
  let distance = Math.round(GeoOperations.distanceBetween([image.coordinates.lng, image.coordinates.lat], c));
 | 
					  let distance = Math.round(
 | 
				
			||||||
  
 | 
					    GeoOperations.distanceBetween([image.coordinates.lng, image.coordinates.lat], c)
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  $: {
 | 
					  $: {
 | 
				
			||||||
    const currentTags = tags.data
 | 
					    const currentTags = tags.data
 | 
				
			||||||
    const key = Object.keys(image.osmTags)[0]
 | 
					    const key = Object.keys(image.osmTags)[0]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,41 +1,40 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import FeatureReviews from "../../Logic/Web/MangroveReviews";
 | 
					  import FeatureReviews from "../../Logic/Web/MangroveReviews"
 | 
				
			||||||
  import SingleReview from "./SingleReview.svelte";
 | 
					  import SingleReview from "./SingleReview.svelte"
 | 
				
			||||||
  import { Utils } from "../../Utils";
 | 
					  import { Utils } from "../../Utils"
 | 
				
			||||||
  import StarsBar from "./StarsBar.svelte";
 | 
					  import StarsBar from "./StarsBar.svelte"
 | 
				
			||||||
  import ReviewForm from "./ReviewForm.svelte";
 | 
					  import ReviewForm from "./ReviewForm.svelte"
 | 
				
			||||||
  import Translations from "../i18n/Translations";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
  import Tr from "../Base/Tr.svelte";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
  import type { SpecialVisualizationState } from "../SpecialVisualization";
 | 
					  import type { SpecialVisualizationState } from "../SpecialVisualization"
 | 
				
			||||||
  import { UIEventSource } from "../../Logic/UIEventSource";
 | 
					  import { UIEventSource } from "../../Logic/UIEventSource"
 | 
				
			||||||
  import type { Feature } from "geojson";
 | 
					  import type { Feature } from "geojson"
 | 
				
			||||||
  import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
 | 
					  import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
 | 
				
			||||||
  import ToSvelte from "../Base/ToSvelte.svelte";
 | 
					  import ToSvelte from "../Base/ToSvelte.svelte"
 | 
				
			||||||
  import Svg from "../../Svg";
 | 
					  import Svg from "../../Svg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * An element showing all reviews
 | 
					   * An element showing all reviews
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  export let reviews: FeatureReviews;
 | 
					  export let reviews: FeatureReviews
 | 
				
			||||||
  export let state: SpecialVisualizationState;
 | 
					  export let state: SpecialVisualizationState
 | 
				
			||||||
  export let tags: UIEventSource<Record<string, string>>;
 | 
					  export let tags: UIEventSource<Record<string, string>>
 | 
				
			||||||
  export let feature: Feature;
 | 
					  export let feature: Feature
 | 
				
			||||||
  export let layer: LayerConfig;
 | 
					  export let layer: LayerConfig
 | 
				
			||||||
  let average = reviews.average;
 | 
					  let average = reviews.average
 | 
				
			||||||
  let _reviews = [];
 | 
					  let _reviews = []
 | 
				
			||||||
  reviews.reviews.addCallbackAndRunD(r => {
 | 
					  reviews.reviews.addCallbackAndRunD((r) => {
 | 
				
			||||||
    _reviews = Utils.NoNull(r);
 | 
					    _reviews = Utils.NoNull(r)
 | 
				
			||||||
  });
 | 
					  })
 | 
				
			||||||
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="border-gray-300 border-dashed border-2">
 | 
					<div class="border-2 border-dashed border-gray-300">
 | 
				
			||||||
  {#if _reviews.length > 1}
 | 
					  {#if _reviews.length > 1}
 | 
				
			||||||
    <StarsBar score={$average}></StarsBar>
 | 
					    <StarsBar score={$average} />
 | 
				
			||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
  {#if _reviews.length > 0}
 | 
					  {#if _reviews.length > 0}
 | 
				
			||||||
    {#each _reviews as review}
 | 
					    {#each _reviews as review}
 | 
				
			||||||
      <SingleReview {review}></SingleReview>
 | 
					      <SingleReview {review} />
 | 
				
			||||||
    {/each}
 | 
					    {/each}
 | 
				
			||||||
  {:else}
 | 
					  {:else}
 | 
				
			||||||
    <Tr t={Translations.t.reviews.no_reviews_yet} />
 | 
					    <Tr t={Translations.t.reviews.no_reviews_yet} />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,60 +1,61 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import FeatureReviews from "../../Logic/Web/MangroveReviews";
 | 
					  import FeatureReviews from "../../Logic/Web/MangroveReviews"
 | 
				
			||||||
  import StarsBar from "./StarsBar.svelte";
 | 
					  import StarsBar from "./StarsBar.svelte"
 | 
				
			||||||
  import SpecialTranslation from "../Popup/TagRendering/SpecialTranslation.svelte";
 | 
					  import SpecialTranslation from "../Popup/TagRendering/SpecialTranslation.svelte"
 | 
				
			||||||
  import type { SpecialVisualizationState } from "../SpecialVisualization";
 | 
					  import type { SpecialVisualizationState } from "../SpecialVisualization"
 | 
				
			||||||
  import { UIEventSource } from "../../Logic/UIEventSource";
 | 
					  import { UIEventSource } from "../../Logic/UIEventSource"
 | 
				
			||||||
  import type { Feature } from "geojson";
 | 
					  import type { Feature } from "geojson"
 | 
				
			||||||
  import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
 | 
					  import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
 | 
				
			||||||
  import Translations from "../i18n/Translations";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
  import Checkbox from "../Base/Checkbox.svelte";
 | 
					  import Checkbox from "../Base/Checkbox.svelte"
 | 
				
			||||||
  import Tr from "../Base/Tr.svelte";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
  import If from "../Base/If.svelte";
 | 
					  import If from "../Base/If.svelte"
 | 
				
			||||||
  import Loading from "../Base/Loading.svelte";
 | 
					  import Loading from "../Base/Loading.svelte"
 | 
				
			||||||
  import { Review } from "mangrove-reviews-typescript";
 | 
					  import { Review } from "mangrove-reviews-typescript"
 | 
				
			||||||
  import { Utils } from "../../Utils";
 | 
					  import { Utils } from "../../Utils"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let state: SpecialVisualizationState;
 | 
					  export let state: SpecialVisualizationState
 | 
				
			||||||
  export let tags: UIEventSource<Record<string, string>>;
 | 
					  export let tags: UIEventSource<Record<string, string>>
 | 
				
			||||||
  export let feature: Feature;
 | 
					  export let feature: Feature
 | 
				
			||||||
  export let layer: LayerConfig;
 | 
					  export let layer: LayerConfig
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * The form to create a new review.
 | 
					   * The form to create a new review.
 | 
				
			||||||
   * This is multi-stepped.
 | 
					   * This is multi-stepped.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  export let reviews: FeatureReviews;
 | 
					  export let reviews: FeatureReviews
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let score = 0;
 | 
					  let score = 0
 | 
				
			||||||
  let confirmedScore = undefined;
 | 
					  let confirmedScore = undefined
 | 
				
			||||||
  let isAffiliated = new UIEventSource(false);
 | 
					  let isAffiliated = new UIEventSource(false)
 | 
				
			||||||
  let opinion = new UIEventSource<string>(undefined);
 | 
					  let opinion = new UIEventSource<string>(undefined)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const t = Translations.t.reviews;
 | 
					  const t = Translations.t.reviews
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let _state: "ask" | "saving" | "done" = "ask";
 | 
					  let _state: "ask" | "saving" | "done" = "ask"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const connection = state.osmConnection;
 | 
					  const connection = state.osmConnection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function save() {
 | 
					  async function save() {
 | 
				
			||||||
    _state = "saving";
 | 
					    _state = "saving"
 | 
				
			||||||
    let nickname = undefined;
 | 
					    let nickname = undefined
 | 
				
			||||||
    if (connection.isLoggedIn.data) {
 | 
					    if (connection.isLoggedIn.data) {
 | 
				
			||||||
      nickname = connection.userDetails.data.name;
 | 
					      nickname = connection.userDetails.data.name
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const review: Omit<Review, "sub"> = {
 | 
					    const review: Omit<Review, "sub"> = {
 | 
				
			||||||
      rating: confirmedScore,
 | 
					      rating: confirmedScore,
 | 
				
			||||||
      opinion: opinion.data,
 | 
					      opinion: opinion.data,
 | 
				
			||||||
      metadata: { nickname, is_affiliated: isAffiliated.data }
 | 
					      metadata: { nickname, is_affiliated: isAffiliated.data },
 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    if (state.featureSwitchIsTesting.data) {
 | 
					 | 
				
			||||||
      console.log("Testing - not actually saving review", review);
 | 
					 | 
				
			||||||
      await Utils.waitFor(1000);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      await reviews.createReview(review);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    _state = "done";
 | 
					    if (state.featureSwitchIsTesting.data) {
 | 
				
			||||||
 | 
					      console.log("Testing - not actually saving review", review)
 | 
				
			||||||
 | 
					      await Utils.waitFor(1000)
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      await reviews.createReview(review)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    _state = "done"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{#if _state === "done"}
 | 
					{#if _state === "done"}
 | 
				
			||||||
  <Tr cls="thanks w-full" t={t.saved} />
 | 
					  <Tr cls="thanks w-full" t={t.saved} />
 | 
				
			||||||
{:else if _state === "saving"}
 | 
					{:else if _state === "saving"}
 | 
				
			||||||
| 
						 | 
					@ -64,24 +65,34 @@
 | 
				
			||||||
{:else}
 | 
					{:else}
 | 
				
			||||||
  <div class="interactive border-interactive p-1">
 | 
					  <div class="interactive border-interactive p-1">
 | 
				
			||||||
    <div class="font-bold">
 | 
					    <div class="font-bold">
 | 
				
			||||||
      <SpecialTranslation {feature} {layer} {state} t={Translations.t.reviews.question} {tags}></SpecialTranslation>
 | 
					      <SpecialTranslation {feature} {layer} {state} t={Translations.t.reviews.question} {tags} />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <StarsBar on:click={e => {confirmedScore = e.detail.score}} on:hover={e => {score = e.detail.score}}
 | 
					    <StarsBar
 | 
				
			||||||
              on:mouseout={e => {score = null}} score={score ?? confirmedScore ?? 0}
 | 
					      on:click={(e) => {
 | 
				
			||||||
              starSize="w-8 h-8"></StarsBar>
 | 
					        confirmedScore = e.detail.score
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      on:hover={(e) => {
 | 
				
			||||||
 | 
					        score = e.detail.score
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      on:mouseout={(e) => {
 | 
				
			||||||
 | 
					        score = null
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      score={score ?? confirmedScore ?? 0}
 | 
				
			||||||
 | 
					      starSize="w-8 h-8"
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {#if confirmedScore !== undefined}
 | 
					    {#if confirmedScore !== undefined}
 | 
				
			||||||
      <Tr cls="font-bold mt-2" t={t.question_opinion} />
 | 
					      <Tr cls="font-bold mt-2" t={t.question_opinion} />
 | 
				
			||||||
      <textarea bind:value={$opinion} inputmode="text" rows="3" class="w-full mb-1" />
 | 
					      <textarea bind:value={$opinion} inputmode="text" rows="3" class="mb-1 w-full" />
 | 
				
			||||||
      <Checkbox selected={isAffiliated}>
 | 
					      <Checkbox selected={isAffiliated}>
 | 
				
			||||||
        <div class="flex flex-col">
 | 
					        <div class="flex flex-col">
 | 
				
			||||||
          <Tr t={t.i_am_affiliated} />
 | 
					          <Tr t={t.i_am_affiliated} />
 | 
				
			||||||
          <Tr cls="subtle" t={t.i_am_affiliated_explanation} />
 | 
					          <Tr cls="subtle" t={t.i_am_affiliated_explanation} />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </Checkbox>
 | 
					      </Checkbox>
 | 
				
			||||||
      <div class="flex w-full justify-between flex-wrap items-center">
 | 
					      <div class="flex w-full flex-wrap items-center justify-between">
 | 
				
			||||||
        <If condition={state.osmConnection.isLoggedIn}>
 | 
					        <If condition={state.osmConnection.isLoggedIn}>
 | 
				
			||||||
          <Tr t={t.reviewing_as.Subs({nickname: state.osmConnection.userDetails.data.name})} />
 | 
					          <Tr t={t.reviewing_as.Subs({ nickname: state.osmConnection.userDetails.data.name })} />
 | 
				
			||||||
          <Tr slot="else" t={t.reviewing_as_anonymous} />
 | 
					          <Tr slot="else" t={t.reviewing_as_anonymous} />
 | 
				
			||||||
        </If>
 | 
					        </If>
 | 
				
			||||||
        <button class="primary" on:click={save}>
 | 
					        <button class="primary" on:click={save}>
 | 
				
			||||||
| 
						 | 
					@ -90,8 +101,6 @@
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <Tr cls="subtle mt-4" t={t.tos} />
 | 
					      <Tr cls="subtle mt-4" t={t.tos} />
 | 
				
			||||||
 | 
					 | 
				
			||||||
    {/if}
 | 
					    {/if}
 | 
				
			||||||
 | 
					 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,32 +1,32 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import { Review } from "mangrove-reviews-typescript";
 | 
					  import { Review } from "mangrove-reviews-typescript"
 | 
				
			||||||
  import { Store } from "../../Logic/UIEventSource";
 | 
					  import { Store } from "../../Logic/UIEventSource"
 | 
				
			||||||
  import StarsBar from "./StarsBar.svelte";
 | 
					  import StarsBar from "./StarsBar.svelte"
 | 
				
			||||||
  import Translations from "../i18n/Translations";
 | 
					  import Translations from "../i18n/Translations"
 | 
				
			||||||
  import Tr from "../Base/Tr.svelte";
 | 
					  import Tr from "../Base/Tr.svelte"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let review: Review & { madeByLoggedInUser: Store<boolean> };
 | 
					  export let review: Review & { madeByLoggedInUser: Store<boolean> }
 | 
				
			||||||
  let name = review.metadata.nickname;
 | 
					  let name = review.metadata.nickname
 | 
				
			||||||
  name ??= (review.metadata.given_name ?? "") + " " + (review.metadata.family_name ?? "").trim();
 | 
					  name ??= (review.metadata.given_name ?? "") + " " + (review.metadata.family_name ?? "").trim()
 | 
				
			||||||
  if (name.length === 0) {
 | 
					  if (name.length === 0) {
 | 
				
			||||||
    name = "Anonymous";
 | 
					    name = "Anonymous"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  let d = new Date();
 | 
					  let d = new Date()
 | 
				
			||||||
  d.setTime(review.iat * 1000);
 | 
					  d.setTime(review.iat * 1000)
 | 
				
			||||||
  let date = d.toDateString();
 | 
					  let date = d.toDateString()
 | 
				
			||||||
  let byLoggedInUser = review.madeByLoggedInUser;
 | 
					  let byLoggedInUser = review.madeByLoggedInUser
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class={"low-interaction p-1 px-2 rounded-lg "+ ($byLoggedInUser ? "border-interactive" : "")}>
 | 
					<div class={"low-interaction rounded-lg p-1 px-2 " + ($byLoggedInUser ? "border-interactive" : "")}>
 | 
				
			||||||
  <div class="flex justify-between items-center">
 | 
					  <div class="flex items-center justify-between">
 | 
				
			||||||
    <StarsBar score={review.rating}></StarsBar>
 | 
					    <StarsBar score={review.rating} />
 | 
				
			||||||
    <div class="flex flex-wrap space-x-2">
 | 
					    <div class="flex flex-wrap space-x-2">
 | 
				
			||||||
      <div class="font-bold">
 | 
					      <div class="font-bold">
 | 
				
			||||||
        {name}
 | 
					        {name}
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    <span class="subtle">
 | 
					      <span class="subtle">
 | 
				
			||||||
      {date}
 | 
					        {date}
 | 
				
			||||||
    </span>
 | 
					      </span>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  {#if review.opinion}
 | 
					  {#if review.opinion}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,27 +1,27 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					  import ToSvelte from "../Base/ToSvelte.svelte"
 | 
				
			||||||
 | 
					  import Svg from "../../Svg"
 | 
				
			||||||
 | 
					  import { createEventDispatcher } from "svelte"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  import ToSvelte from "../Base/ToSvelte.svelte";
 | 
					  export let score: number
 | 
				
			||||||
  import Svg from "../../Svg";
 | 
					  export let cutoff: number
 | 
				
			||||||
  import { createEventDispatcher } from "svelte";
 | 
					  export let starSize = "w-h h-4"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let score: number;
 | 
					  let dispatch = createEventDispatcher<{ hover: { score: number } }>()
 | 
				
			||||||
  export let cutoff: number;
 | 
					  let container: HTMLElement
 | 
				
			||||||
  export let starSize = "w-h h-4";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let dispatch = createEventDispatcher<{ hover: { score: number } }>();
 | 
					 | 
				
			||||||
  let container: HTMLElement;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function getScore(e: MouseEvent): number {
 | 
					  function getScore(e: MouseEvent): number {
 | 
				
			||||||
    const x = e.clientX - e.target.getBoundingClientRect().x;
 | 
					    const x = e.clientX - e.target.getBoundingClientRect().x
 | 
				
			||||||
    const w = container.getClientRects()[0]?.width;
 | 
					    const w = container.getClientRects()[0]?.width
 | 
				
			||||||
    return (x / w) < 0.5 ? cutoff - 10 : cutoff;
 | 
					    return x / w < 0.5 ? cutoff - 10 : cutoff
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div bind:this={container} on:click={(e) => dispatch("click", {score: getScore(e)})}
 | 
					<div
 | 
				
			||||||
     on:mousemove={(e) => dispatch("hover", { score: getScore(e) })}>
 | 
					  bind:this={container}
 | 
				
			||||||
 | 
					  on:click={(e) => dispatch("click", { score: getScore(e) })}
 | 
				
			||||||
 | 
					  on:mousemove={(e) => dispatch("hover", { score: getScore(e) })}
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
  {#if score >= cutoff}
 | 
					  {#if score >= cutoff}
 | 
				
			||||||
    <ToSvelte construct={Svg.star_svg().SetClass(starSize)} />
 | 
					    <ToSvelte construct={Svg.star_svg().SetClass(starSize)} />
 | 
				
			||||||
  {:else if score + 10 >= cutoff}
 | 
					  {:else if score + 10 >= cutoff}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,21 +1,21 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import { createEventDispatcher } from "svelte";
 | 
					  import { createEventDispatcher } from "svelte"
 | 
				
			||||||
  import StarElement from "./StarElement.svelte";
 | 
					  import StarElement from "./StarElement.svelte"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Number between 0 and 100. Every 10 points, another half star is added
 | 
					   * Number between 0 and 100. Every 10 points, another half star is added
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  export let score: number;
 | 
					  export let score: number
 | 
				
			||||||
  let dispatch = createEventDispatcher<{ hover: number, click: number }>();
 | 
					  let dispatch = createEventDispatcher<{ hover: number; click: number }>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let cutoffs = [20,40,60,80,100]
 | 
					  let cutoffs = [20, 40, 60, 80, 100]
 | 
				
			||||||
  export let starSize = "w-h h-4"
 | 
					  export let starSize = "w-h h-4"
 | 
				
			||||||
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{#if score !== undefined}
 | 
					{#if score !== undefined}
 | 
				
			||||||
<div class="flex" on:mouseout>
 | 
					  <div class="flex" on:mouseout>
 | 
				
			||||||
  {#each cutoffs as cutoff}
 | 
					    {#each cutoffs as cutoff}
 | 
				
			||||||
    <StarElement {score} {cutoff} {starSize} on:hover on:click/>
 | 
					      <StarElement {score} {cutoff} {starSize} on:hover on:click />
 | 
				
			||||||
    {/each}
 | 
					    {/each}
 | 
				
			||||||
</div>
 | 
					  </div>
 | 
				
			||||||
  {/if}
 | 
					{/if}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,8 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					  import { Store } from "../../Logic/UIEventSource"
 | 
				
			||||||
 | 
					  import StarsBar from "./StarsBar.svelte"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  import { Store } from "../../Logic/UIEventSource";
 | 
					  export let score: Store<number>
 | 
				
			||||||
  import StarsBar from "./StarsBar.svelte";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  export let score: Store<number>;
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{#if $score !== undefined && $score !== null}
 | 
					{#if $score !== undefined && $score !== null}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,118 +1,121 @@
 | 
				
			||||||
import { Store, UIEventSource } from "../Logic/UIEventSource";
 | 
					import { Store, UIEventSource } from "../Logic/UIEventSource"
 | 
				
			||||||
import BaseUIElement from "./BaseUIElement";
 | 
					import BaseUIElement from "./BaseUIElement"
 | 
				
			||||||
import LayoutConfig from "../Models/ThemeConfig/LayoutConfig";
 | 
					import LayoutConfig from "../Models/ThemeConfig/LayoutConfig"
 | 
				
			||||||
import { IndexedFeatureSource, WritableFeatureSource } from "../Logic/FeatureSource/FeatureSource";
 | 
					import { IndexedFeatureSource, WritableFeatureSource } from "../Logic/FeatureSource/FeatureSource"
 | 
				
			||||||
import { OsmConnection } from "../Logic/Osm/OsmConnection";
 | 
					import { OsmConnection } from "../Logic/Osm/OsmConnection"
 | 
				
			||||||
import { Changes } from "../Logic/Osm/Changes";
 | 
					import { Changes } from "../Logic/Osm/Changes"
 | 
				
			||||||
import { ExportableMap, MapProperties } from "../Models/MapProperties";
 | 
					import { ExportableMap, MapProperties } from "../Models/MapProperties"
 | 
				
			||||||
import LayerState from "../Logic/State/LayerState";
 | 
					import LayerState from "../Logic/State/LayerState"
 | 
				
			||||||
import { Feature, Geometry, Point } from "geojson";
 | 
					import { Feature, Geometry, Point } from "geojson"
 | 
				
			||||||
import FullNodeDatabaseSource from "../Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource";
 | 
					import FullNodeDatabaseSource from "../Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource"
 | 
				
			||||||
import { MangroveIdentity } from "../Logic/Web/MangroveReviews";
 | 
					import { MangroveIdentity } from "../Logic/Web/MangroveReviews"
 | 
				
			||||||
import { GeoIndexedStoreForLayer } from "../Logic/FeatureSource/Actors/GeoIndexedStore";
 | 
					import { GeoIndexedStoreForLayer } from "../Logic/FeatureSource/Actors/GeoIndexedStore"
 | 
				
			||||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
 | 
					import LayerConfig from "../Models/ThemeConfig/LayerConfig"
 | 
				
			||||||
import FeatureSwitchState from "../Logic/State/FeatureSwitchState";
 | 
					import FeatureSwitchState from "../Logic/State/FeatureSwitchState"
 | 
				
			||||||
import { MenuState } from "../Models/MenuState";
 | 
					import { MenuState } from "../Models/MenuState"
 | 
				
			||||||
import OsmObjectDownloader from "../Logic/Osm/OsmObjectDownloader";
 | 
					import OsmObjectDownloader from "../Logic/Osm/OsmObjectDownloader"
 | 
				
			||||||
import { RasterLayerPolygon } from "../Models/RasterLayers";
 | 
					import { RasterLayerPolygon } from "../Models/RasterLayers"
 | 
				
			||||||
import { ImageUploadManager } from "../Logic/ImageProviders/ImageUploadManager";
 | 
					import { ImageUploadManager } from "../Logic/ImageProviders/ImageUploadManager"
 | 
				
			||||||
import { OsmTags } from "../Models/OsmFeature";
 | 
					import { OsmTags } from "../Models/OsmFeature"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The state needed to render a special Visualisation.
 | 
					 * The state needed to render a special Visualisation.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export interface SpecialVisualizationState {
 | 
					export interface SpecialVisualizationState {
 | 
				
			||||||
  readonly guistate: MenuState;
 | 
					    readonly guistate: MenuState
 | 
				
			||||||
  readonly layout: LayoutConfig;
 | 
					    readonly layout: LayoutConfig
 | 
				
			||||||
  readonly featureSwitches: FeatureSwitchState;
 | 
					    readonly featureSwitches: FeatureSwitchState
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly layerState: LayerState;
 | 
					    readonly layerState: LayerState
 | 
				
			||||||
  readonly featureProperties: { getStore(id: string): UIEventSource<Record<string, string>>, trackFeature?(feature: { properties: OsmTags }) };
 | 
					    readonly featureProperties: {
 | 
				
			||||||
 | 
					        getStore(id: string): UIEventSource<Record<string, string>>
 | 
				
			||||||
 | 
					        trackFeature?(feature: { properties: OsmTags })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly indexedFeatures: IndexedFeatureSource;
 | 
					    readonly indexedFeatures: IndexedFeatureSource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					    /**
 | 
				
			||||||
   * Some features will create a new element that should be displayed.
 | 
					     * Some features will create a new element that should be displayed.
 | 
				
			||||||
   * These can be injected by appending them to this featuresource (and pinging it)
 | 
					     * These can be injected by appending them to this featuresource (and pinging it)
 | 
				
			||||||
   */
 | 
					     */
 | 
				
			||||||
  readonly newFeatures: WritableFeatureSource;
 | 
					    readonly newFeatures: WritableFeatureSource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly historicalUserLocations: WritableFeatureSource<Feature<Point>>;
 | 
					    readonly historicalUserLocations: WritableFeatureSource<Feature<Point>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly osmConnection: OsmConnection;
 | 
					    readonly osmConnection: OsmConnection
 | 
				
			||||||
  readonly featureSwitchUserbadge: Store<boolean>;
 | 
					    readonly featureSwitchUserbadge: Store<boolean>
 | 
				
			||||||
  readonly featureSwitchIsTesting: Store<boolean>;
 | 
					    readonly featureSwitchIsTesting: Store<boolean>
 | 
				
			||||||
  readonly changes: Changes;
 | 
					    readonly changes: Changes
 | 
				
			||||||
  readonly osmObjectDownloader: OsmObjectDownloader;
 | 
					    readonly osmObjectDownloader: OsmObjectDownloader
 | 
				
			||||||
  /**
 | 
					    /**
 | 
				
			||||||
   * State of the main map
 | 
					     * State of the main map
 | 
				
			||||||
   */
 | 
					     */
 | 
				
			||||||
  readonly mapProperties: MapProperties & ExportableMap;
 | 
					    readonly mapProperties: MapProperties & ExportableMap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly selectedElement: UIEventSource<Feature>;
 | 
					    readonly selectedElement: UIEventSource<Feature>
 | 
				
			||||||
  /**
 | 
					    /**
 | 
				
			||||||
   * Works together with 'selectedElement' to indicate what properties should be displayed
 | 
					     * Works together with 'selectedElement' to indicate what properties should be displayed
 | 
				
			||||||
   */
 | 
					     */
 | 
				
			||||||
  readonly selectedLayer: UIEventSource<LayerConfig>;
 | 
					    readonly selectedLayer: UIEventSource<LayerConfig>
 | 
				
			||||||
  readonly selectedElementAndLayer: Store<{ feature: Feature; layer: LayerConfig }>;
 | 
					    readonly selectedElementAndLayer: Store<{ feature: Feature; layer: LayerConfig }>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					    /**
 | 
				
			||||||
   * If data is currently being fetched from external sources
 | 
					     * If data is currently being fetched from external sources
 | 
				
			||||||
   */
 | 
					     */
 | 
				
			||||||
  readonly dataIsLoading: Store<boolean>;
 | 
					    readonly dataIsLoading: Store<boolean>
 | 
				
			||||||
  /**
 | 
					    /**
 | 
				
			||||||
   * Only needed for 'ReplaceGeometryAction'
 | 
					     * Only needed for 'ReplaceGeometryAction'
 | 
				
			||||||
   */
 | 
					     */
 | 
				
			||||||
  readonly fullNodeDatabase?: FullNodeDatabaseSource;
 | 
					    readonly fullNodeDatabase?: FullNodeDatabaseSource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer>;
 | 
					    readonly perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer>
 | 
				
			||||||
  readonly userRelatedState: {
 | 
					    readonly userRelatedState: {
 | 
				
			||||||
    readonly imageLicense: UIEventSource<string>;
 | 
					        readonly imageLicense: UIEventSource<string>
 | 
				
			||||||
    readonly showTags: UIEventSource<"no" | undefined | "always" | "yes" | "full">
 | 
					        readonly showTags: UIEventSource<"no" | undefined | "always" | "yes" | "full">
 | 
				
			||||||
    readonly mangroveIdentity: MangroveIdentity
 | 
					        readonly mangroveIdentity: MangroveIdentity
 | 
				
			||||||
    readonly showAllQuestionsAtOnce: UIEventSource<boolean>
 | 
					        readonly showAllQuestionsAtOnce: UIEventSource<boolean>
 | 
				
			||||||
    readonly preferencesAsTags: Store<Record<string, string>>
 | 
					        readonly preferencesAsTags: Store<Record<string, string>>
 | 
				
			||||||
    readonly language: UIEventSource<string>
 | 
					        readonly language: UIEventSource<string>
 | 
				
			||||||
  };
 | 
					    }
 | 
				
			||||||
  readonly lastClickObject: WritableFeatureSource;
 | 
					    readonly lastClickObject: WritableFeatureSource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly availableLayers: Store<RasterLayerPolygon[]>;
 | 
					    readonly availableLayers: Store<RasterLayerPolygon[]>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  readonly imageUploadManager: ImageUploadManager;
 | 
					    readonly imageUploadManager: ImageUploadManager
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface SpecialVisualization {
 | 
					export interface SpecialVisualization {
 | 
				
			||||||
  readonly funcName: string;
 | 
					    readonly funcName: string
 | 
				
			||||||
  readonly docs: string | BaseUIElement;
 | 
					    readonly docs: string | BaseUIElement
 | 
				
			||||||
  readonly example?: string;
 | 
					    readonly example?: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					    /**
 | 
				
			||||||
   * Indicates that this special visualisation will make requests to the 'alLNodesDatabase' and that it thus should be included
 | 
					     * Indicates that this special visualisation will make requests to the 'alLNodesDatabase' and that it thus should be included
 | 
				
			||||||
   */
 | 
					     */
 | 
				
			||||||
  readonly needsNodeDatabase?: boolean;
 | 
					    readonly needsNodeDatabase?: boolean
 | 
				
			||||||
  readonly args: {
 | 
					    readonly args: {
 | 
				
			||||||
    name: string
 | 
					        name: string
 | 
				
			||||||
    defaultValue?: string
 | 
					        defaultValue?: string
 | 
				
			||||||
    doc: string
 | 
					        doc: string
 | 
				
			||||||
    required?: false | boolean
 | 
					        required?: false | boolean
 | 
				
			||||||
  }[];
 | 
					    }[]
 | 
				
			||||||
  readonly getLayerDependencies?: (argument: string[]) => string[];
 | 
					    readonly getLayerDependencies?: (argument: string[]) => string[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  structuredExamples?(): { feature: Feature<Geometry, Record<string, string>>; args: string[] }[];
 | 
					    structuredExamples?(): { feature: Feature<Geometry, Record<string, string>>; args: string[] }[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constr(
 | 
					    constr(
 | 
				
			||||||
    state: SpecialVisualizationState,
 | 
					        state: SpecialVisualizationState,
 | 
				
			||||||
    tagSource: UIEventSource<Record<string, string>>,
 | 
					        tagSource: UIEventSource<Record<string, string>>,
 | 
				
			||||||
    argument: string[],
 | 
					        argument: string[],
 | 
				
			||||||
    feature: Feature,
 | 
					        feature: Feature,
 | 
				
			||||||
    layer: LayerConfig
 | 
					        layer: LayerConfig
 | 
				
			||||||
  ): BaseUIElement;
 | 
					    ): BaseUIElement
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type RenderingSpecification =
 | 
					export type RenderingSpecification =
 | 
				
			||||||
  | string
 | 
					    | string
 | 
				
			||||||
  | {
 | 
					    | {
 | 
				
			||||||
  func: SpecialVisualization
 | 
					          func: SpecialVisualization
 | 
				
			||||||
  args: string[]
 | 
					          args: string[]
 | 
				
			||||||
  style: string
 | 
					          style: string
 | 
				
			||||||
}
 | 
					      }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,72 +1,76 @@
 | 
				
			||||||
import Combine from "./Base/Combine";
 | 
					import Combine from "./Base/Combine"
 | 
				
			||||||
import { FixedUiElement } from "./Base/FixedUiElement";
 | 
					import { FixedUiElement } from "./Base/FixedUiElement"
 | 
				
			||||||
import BaseUIElement from "./BaseUIElement";
 | 
					import BaseUIElement from "./BaseUIElement"
 | 
				
			||||||
import Title from "./Base/Title";
 | 
					import Title from "./Base/Title"
 | 
				
			||||||
import Table from "./Base/Table";
 | 
					import Table from "./Base/Table"
 | 
				
			||||||
import { RenderingSpecification, SpecialVisualization, SpecialVisualizationState } from "./SpecialVisualization";
 | 
					import {
 | 
				
			||||||
import { HistogramViz } from "./Popup/HistogramViz";
 | 
					    RenderingSpecification,
 | 
				
			||||||
import { MinimapViz } from "./Popup/MinimapViz";
 | 
					    SpecialVisualization,
 | 
				
			||||||
import { ShareLinkViz } from "./Popup/ShareLinkViz";
 | 
					    SpecialVisualizationState,
 | 
				
			||||||
import { UploadToOsmViz } from "./Popup/UploadToOsmViz";
 | 
					} from "./SpecialVisualization"
 | 
				
			||||||
import { MultiApplyViz } from "./Popup/MultiApplyViz";
 | 
					import { HistogramViz } from "./Popup/HistogramViz"
 | 
				
			||||||
import { AddNoteCommentViz } from "./Popup/AddNoteCommentViz";
 | 
					import { MinimapViz } from "./Popup/MinimapViz"
 | 
				
			||||||
import { PlantNetDetectionViz } from "./Popup/PlantNetDetectionViz";
 | 
					import { ShareLinkViz } from "./Popup/ShareLinkViz"
 | 
				
			||||||
import TagApplyButton from "./Popup/TagApplyButton";
 | 
					import { UploadToOsmViz } from "./Popup/UploadToOsmViz"
 | 
				
			||||||
import { CloseNoteButton } from "./Popup/CloseNoteButton";
 | 
					import { MultiApplyViz } from "./Popup/MultiApplyViz"
 | 
				
			||||||
import { MapillaryLinkVis } from "./Popup/MapillaryLinkVis";
 | 
					import { AddNoteCommentViz } from "./Popup/AddNoteCommentViz"
 | 
				
			||||||
import { Store, Stores, UIEventSource } from "../Logic/UIEventSource";
 | 
					import { PlantNetDetectionViz } from "./Popup/PlantNetDetectionViz"
 | 
				
			||||||
import AllTagsPanel from "./Popup/AllTagsPanel.svelte";
 | 
					import TagApplyButton from "./Popup/TagApplyButton"
 | 
				
			||||||
import AllImageProviders from "../Logic/ImageProviders/AllImageProviders";
 | 
					import { CloseNoteButton } from "./Popup/CloseNoteButton"
 | 
				
			||||||
import { ImageCarousel } from "./Image/ImageCarousel";
 | 
					import { MapillaryLinkVis } from "./Popup/MapillaryLinkVis"
 | 
				
			||||||
import { VariableUiElement } from "./Base/VariableUIElement";
 | 
					import { Store, Stores, UIEventSource } from "../Logic/UIEventSource"
 | 
				
			||||||
import { Utils } from "../Utils";
 | 
					import AllTagsPanel from "./Popup/AllTagsPanel.svelte"
 | 
				
			||||||
import Wikidata, { WikidataResponse } from "../Logic/Web/Wikidata";
 | 
					import AllImageProviders from "../Logic/ImageProviders/AllImageProviders"
 | 
				
			||||||
import { Translation } from "./i18n/Translation";
 | 
					import { ImageCarousel } from "./Image/ImageCarousel"
 | 
				
			||||||
import Translations from "./i18n/Translations";
 | 
					import { VariableUiElement } from "./Base/VariableUIElement"
 | 
				
			||||||
import OpeningHoursVisualization from "./OpeningHours/OpeningHoursVisualization";
 | 
					import { Utils } from "../Utils"
 | 
				
			||||||
import LiveQueryHandler from "../Logic/Web/LiveQueryHandler";
 | 
					import Wikidata, { WikidataResponse } from "../Logic/Web/Wikidata"
 | 
				
			||||||
import { SubtleButton } from "./Base/SubtleButton";
 | 
					import { Translation } from "./i18n/Translation"
 | 
				
			||||||
import Svg from "../Svg";
 | 
					import Translations from "./i18n/Translations"
 | 
				
			||||||
import NoteCommentElement from "./Popup/NoteCommentElement";
 | 
					import OpeningHoursVisualization from "./OpeningHours/OpeningHoursVisualization"
 | 
				
			||||||
import { SubstitutedTranslation } from "./SubstitutedTranslation";
 | 
					import LiveQueryHandler from "../Logic/Web/LiveQueryHandler"
 | 
				
			||||||
import List from "./Base/List";
 | 
					import { SubtleButton } from "./Base/SubtleButton"
 | 
				
			||||||
import StatisticsPanel from "./BigComponents/StatisticsPanel";
 | 
					import Svg from "../Svg"
 | 
				
			||||||
import AutoApplyButton from "./Popup/AutoApplyButton";
 | 
					import NoteCommentElement from "./Popup/NoteCommentElement"
 | 
				
			||||||
import { LanguageElement } from "./Popup/LanguageElement";
 | 
					import { SubstitutedTranslation } from "./SubstitutedTranslation"
 | 
				
			||||||
import FeatureReviews from "../Logic/Web/MangroveReviews";
 | 
					import List from "./Base/List"
 | 
				
			||||||
import Maproulette from "../Logic/Maproulette";
 | 
					import StatisticsPanel from "./BigComponents/StatisticsPanel"
 | 
				
			||||||
import SvelteUIElement from "./Base/SvelteUIElement";
 | 
					import AutoApplyButton from "./Popup/AutoApplyButton"
 | 
				
			||||||
import { BBoxFeatureSourceForLayer } from "../Logic/FeatureSource/Sources/TouchesBboxFeatureSource";
 | 
					import { LanguageElement } from "./Popup/LanguageElement"
 | 
				
			||||||
import QuestionViz from "./Popup/QuestionViz";
 | 
					import FeatureReviews from "../Logic/Web/MangroveReviews"
 | 
				
			||||||
import { Feature, Point } from "geojson";
 | 
					import Maproulette from "../Logic/Maproulette"
 | 
				
			||||||
import { GeoOperations } from "../Logic/GeoOperations";
 | 
					import SvelteUIElement from "./Base/SvelteUIElement"
 | 
				
			||||||
import CreateNewNote from "./Popup/CreateNewNote.svelte";
 | 
					import { BBoxFeatureSourceForLayer } from "../Logic/FeatureSource/Sources/TouchesBboxFeatureSource"
 | 
				
			||||||
import AddNewPoint from "./Popup/AddNewPoint/AddNewPoint.svelte";
 | 
					import QuestionViz from "./Popup/QuestionViz"
 | 
				
			||||||
import UserProfile from "./BigComponents/UserProfile.svelte";
 | 
					import { Feature, Point } from "geojson"
 | 
				
			||||||
import LanguagePicker from "./LanguagePicker";
 | 
					import { GeoOperations } from "../Logic/GeoOperations"
 | 
				
			||||||
import Link from "./Base/Link";
 | 
					import CreateNewNote from "./Popup/CreateNewNote.svelte"
 | 
				
			||||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
 | 
					import AddNewPoint from "./Popup/AddNewPoint/AddNewPoint.svelte"
 | 
				
			||||||
import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig";
 | 
					import UserProfile from "./BigComponents/UserProfile.svelte"
 | 
				
			||||||
import { OsmTags, WayId } from "../Models/OsmFeature";
 | 
					import LanguagePicker from "./LanguagePicker"
 | 
				
			||||||
import MoveWizard from "./Popup/MoveWizard";
 | 
					import Link from "./Base/Link"
 | 
				
			||||||
import SplitRoadWizard from "./Popup/SplitRoadWizard";
 | 
					import LayerConfig from "../Models/ThemeConfig/LayerConfig"
 | 
				
			||||||
import { ExportAsGpxViz } from "./Popup/ExportAsGpxViz";
 | 
					import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig"
 | 
				
			||||||
import WikipediaPanel from "./Wikipedia/WikipediaPanel.svelte";
 | 
					import { OsmTags, WayId } from "../Models/OsmFeature"
 | 
				
			||||||
import TagRenderingEditable from "./Popup/TagRendering/TagRenderingEditable.svelte";
 | 
					import MoveWizard from "./Popup/MoveWizard"
 | 
				
			||||||
import { PointImportButtonViz } from "./Popup/ImportButtons/PointImportButtonViz";
 | 
					import SplitRoadWizard from "./Popup/SplitRoadWizard"
 | 
				
			||||||
import WayImportButtonViz from "./Popup/ImportButtons/WayImportButtonViz";
 | 
					import { ExportAsGpxViz } from "./Popup/ExportAsGpxViz"
 | 
				
			||||||
import ConflateImportButtonViz from "./Popup/ImportButtons/ConflateImportButtonViz";
 | 
					import WikipediaPanel from "./Wikipedia/WikipediaPanel.svelte"
 | 
				
			||||||
import DeleteWizard from "./Popup/DeleteFlow/DeleteWizard.svelte";
 | 
					import TagRenderingEditable from "./Popup/TagRendering/TagRenderingEditable.svelte"
 | 
				
			||||||
import { OpenJosm } from "./BigComponents/OpenJosm";
 | 
					import { PointImportButtonViz } from "./Popup/ImportButtons/PointImportButtonViz"
 | 
				
			||||||
import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte";
 | 
					import WayImportButtonViz from "./Popup/ImportButtons/WayImportButtonViz"
 | 
				
			||||||
import FediverseValidator from "./InputElement/Validators/FediverseValidator";
 | 
					import ConflateImportButtonViz from "./Popup/ImportButtons/ConflateImportButtonViz"
 | 
				
			||||||
import SendEmail from "./Popup/SendEmail.svelte";
 | 
					import DeleteWizard from "./Popup/DeleteFlow/DeleteWizard.svelte"
 | 
				
			||||||
import NearbyImages from "./Popup/NearbyImages.svelte";
 | 
					import { OpenJosm } from "./BigComponents/OpenJosm"
 | 
				
			||||||
import NearbyImagesCollapsed from "./Popup/NearbyImagesCollapsed.svelte";
 | 
					import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte"
 | 
				
			||||||
import UploadImage from "./Image/UploadImage.svelte";
 | 
					import FediverseValidator from "./InputElement/Validators/FediverseValidator"
 | 
				
			||||||
import AllReviews from "./Reviews/AllReviews.svelte";
 | 
					import SendEmail from "./Popup/SendEmail.svelte"
 | 
				
			||||||
import StarsBarIcon from "./Reviews/StarsBarIcon.svelte";
 | 
					import NearbyImages from "./Popup/NearbyImages.svelte"
 | 
				
			||||||
import ReviewForm from "./Reviews/ReviewForm.svelte";
 | 
					import NearbyImagesCollapsed from "./Popup/NearbyImagesCollapsed.svelte"
 | 
				
			||||||
 | 
					import UploadImage from "./Image/UploadImage.svelte"
 | 
				
			||||||
 | 
					import AllReviews from "./Reviews/AllReviews.svelte"
 | 
				
			||||||
 | 
					import StarsBarIcon from "./Reviews/StarsBarIcon.svelte"
 | 
				
			||||||
 | 
					import ReviewForm from "./Reviews/ReviewForm.svelte"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NearbyImageVis implements SpecialVisualization {
 | 
					class NearbyImageVis implements SpecialVisualization {
 | 
				
			||||||
    // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
 | 
					    // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
 | 
				
			||||||
| 
						 | 
					@ -265,7 +269,6 @@ export default class SpecialVisualizations {
 | 
				
			||||||
                    SpecialVisualizations.specialVisualizations
 | 
					                    SpecialVisualizations.specialVisualizations
 | 
				
			||||||
                        .map((sp) => sp.funcName + "()")
 | 
					                        .map((sp) => sp.funcName + "()")
 | 
				
			||||||
                        .join(", ")
 | 
					                        .join(", ")
 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -610,17 +613,20 @@ export default class SpecialVisualizations {
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        name: "image-key",
 | 
					                        name: "image-key",
 | 
				
			||||||
                        doc: "Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)",
 | 
					                        doc: "Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)",
 | 
				
			||||||
                        required: false
 | 
					                        required: false,
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        name: "label",
 | 
					                        name: "label",
 | 
				
			||||||
                        doc: "The text to show on the button",
 | 
					                        doc: "The text to show on the button",
 | 
				
			||||||
                        required: false
 | 
					                        required: false,
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
                constr: (state, tags, args) => {
 | 
					                constr: (state, tags, args) => {
 | 
				
			||||||
                    return new SvelteUIElement(UploadImage, {
 | 
					                    return new SvelteUIElement(UploadImage, {
 | 
				
			||||||
                        state,tags, labelText: args[1], image: args[0]
 | 
					                        state,
 | 
				
			||||||
 | 
					                        tags,
 | 
				
			||||||
 | 
					                        labelText: args[1],
 | 
				
			||||||
 | 
					                        image: args[0],
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					@ -642,15 +648,22 @@ export default class SpecialVisualizations {
 | 
				
			||||||
                    const nameKey = args[0] ?? "name"
 | 
					                    const nameKey = args[0] ?? "name"
 | 
				
			||||||
                    let fallbackName = args[1]
 | 
					                    let fallbackName = args[1]
 | 
				
			||||||
                    const reviews = FeatureReviews.construct(
 | 
					                    const reviews = FeatureReviews.construct(
 | 
				
			||||||
                      feature,
 | 
					                        feature,
 | 
				
			||||||
                      tags,
 | 
					                        tags,
 | 
				
			||||||
                      state.userRelatedState.mangroveIdentity,
 | 
					                        state.userRelatedState.mangroveIdentity,
 | 
				
			||||||
                      {
 | 
					                        {
 | 
				
			||||||
                          nameKey: nameKey,
 | 
					                            nameKey: nameKey,
 | 
				
			||||||
                          fallbackName,
 | 
					                            fallbackName,
 | 
				
			||||||
                      }
 | 
					                        }
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    return new SvelteUIElement(StarsBarIcon, {score:reviews.average, reviews, state, tags, feature, layer})
 | 
					                    return new SvelteUIElement(StarsBarIcon, {
 | 
				
			||||||
 | 
					                        score: reviews.average,
 | 
				
			||||||
 | 
					                        reviews,
 | 
				
			||||||
 | 
					                        state,
 | 
				
			||||||
 | 
					                        tags,
 | 
				
			||||||
 | 
					                        feature,
 | 
				
			||||||
 | 
					                        layer,
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -672,15 +685,15 @@ export default class SpecialVisualizations {
 | 
				
			||||||
                    const nameKey = args[0] ?? "name"
 | 
					                    const nameKey = args[0] ?? "name"
 | 
				
			||||||
                    let fallbackName = args[1]
 | 
					                    let fallbackName = args[1]
 | 
				
			||||||
                    const reviews = FeatureReviews.construct(
 | 
					                    const reviews = FeatureReviews.construct(
 | 
				
			||||||
                      feature,
 | 
					                        feature,
 | 
				
			||||||
                      tags,
 | 
					                        tags,
 | 
				
			||||||
                      state.userRelatedState.mangroveIdentity,
 | 
					                        state.userRelatedState.mangroveIdentity,
 | 
				
			||||||
                      {
 | 
					                        {
 | 
				
			||||||
                          nameKey: nameKey,
 | 
					                            nameKey: nameKey,
 | 
				
			||||||
                          fallbackName,
 | 
					                            fallbackName,
 | 
				
			||||||
                      }
 | 
					                        }
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    return new SvelteUIElement(ReviewForm, {reviews, state, tags, feature, layer})
 | 
					                    return new SvelteUIElement(ReviewForm, { reviews, state, tags, feature, layer })
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -711,7 +724,7 @@ export default class SpecialVisualizations {
 | 
				
			||||||
                            fallbackName,
 | 
					                            fallbackName,
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    return new SvelteUIElement(AllReviews, {reviews, state, tags, feature, layer})
 | 
					                    return new SvelteUIElement(AllReviews, { reviews, state, tags, feature, layer })
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -920,8 +933,8 @@ export default class SpecialVisualizations {
 | 
				
			||||||
                    const id = tags.data[args[0] ?? "id"]
 | 
					                    const id = tags.data[args[0] ?? "id"]
 | 
				
			||||||
                    tags = state.featureProperties.getStore(id)
 | 
					                    tags = state.featureProperties.getStore(id)
 | 
				
			||||||
                    console.log("Id is", id)
 | 
					                    console.log("Id is", id)
 | 
				
			||||||
                    return new SvelteUIElement(UploadImage, {state, tags})
 | 
					                    return new SvelteUIElement(UploadImage, { state, tags })
 | 
				
			||||||
                    }
 | 
					                },
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                funcName: "title",
 | 
					                funcName: "title",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@
 | 
				
			||||||
    <div class="border-interactive interactive">
 | 
					    <div class="border-interactive interactive">
 | 
				
			||||||
      Highly interactive area (mostly: active question)
 | 
					      Highly interactive area (mostly: active question)
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    <div class="flex">
 | 
					    <div class="flex">
 | 
				
			||||||
      <button class="primary">
 | 
					      <button class="primary">
 | 
				
			||||||
        <ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
 | 
					        <ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,22 +33,22 @@
 | 
				
			||||||
      <Tr t={Translations.t.general.wikipedia.loading} />
 | 
					      <Tr t={Translations.t.general.wikipedia.loading} />
 | 
				
			||||||
    </Loading>
 | 
					    </Loading>
 | 
				
			||||||
  {:else}
 | 
					  {:else}
 | 
				
			||||||
  <span class="wikipedia-article">
 | 
					    <span class="wikipedia-article">
 | 
				
			||||||
    <FromHtml src={$wikipediaDetails.firstParagraph} />
 | 
					      <FromHtml src={$wikipediaDetails.firstParagraph} />
 | 
				
			||||||
    <Disclosure let:open>
 | 
					      <Disclosure let:open>
 | 
				
			||||||
      <DisclosureButton>
 | 
					        <DisclosureButton>
 | 
				
			||||||
        <span class="flex">
 | 
					          <span class="flex">
 | 
				
			||||||
          <ChevronRightIcon
 | 
					            <ChevronRightIcon
 | 
				
			||||||
            style={(open ? "transform: rotate(90deg); " : "") +
 | 
					              style={(open ? "transform: rotate(90deg); " : "") +
 | 
				
			||||||
              "  transition: all .25s linear; width: 1.5rem; height: 1.5rem"}
 | 
					                "  transition: all .25s linear; width: 1.5rem; height: 1.5rem"}
 | 
				
			||||||
          />
 | 
					            />
 | 
				
			||||||
          <Tr t={Translations.t.general.wikipedia.readMore}/>
 | 
					            <Tr t={Translations.t.general.wikipedia.readMore} />
 | 
				
			||||||
        </span>
 | 
					          </span>
 | 
				
			||||||
      </DisclosureButton>
 | 
					        </DisclosureButton>
 | 
				
			||||||
      <DisclosurePanel>
 | 
					        <DisclosurePanel>
 | 
				
			||||||
        <FromHtml src={$wikipediaDetails.restOfArticle} />
 | 
					          <FromHtml src={$wikipediaDetails.restOfArticle} />
 | 
				
			||||||
      </DisclosurePanel>
 | 
					        </DisclosurePanel>
 | 
				
			||||||
    </Disclosure>
 | 
					      </Disclosure>
 | 
				
			||||||
  </span>
 | 
					    </span>
 | 
				
			||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@
 | 
				
			||||||
  export let wikiIds: Store<string[]>
 | 
					  export let wikiIds: Store<string[]>
 | 
				
			||||||
  let wikipediaStores: Store<Store<FullWikipediaDetails>[]> = Locale.language.bind((language) =>
 | 
					  let wikipediaStores: Store<Store<FullWikipediaDetails>[]> = Locale.language.bind((language) =>
 | 
				
			||||||
    wikiIds?.map((wikiIds) => wikiIds?.map((id) => Wikipedia.fetchArticleAndWikidata(id, language)))
 | 
					    wikiIds?.map((wikiIds) => wikiIds?.map((id) => Wikipedia.fetchArticleAndWikidata(id, language)))
 | 
				
			||||||
  );
 | 
					  )
 | 
				
			||||||
  let _wikipediaStores
 | 
					  let _wikipediaStores
 | 
				
			||||||
  onDestroy(
 | 
					  onDestroy(
 | 
				
			||||||
    wikipediaStores.addCallbackAndRunD((wikipediaStores) => {
 | 
					    wikipediaStores.addCallbackAndRunD((wikipediaStores) => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  "contributors": [
 | 
					  "contributors": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "commits": 5965,
 | 
					      "commits": 6039,
 | 
				
			||||||
      "contributor": "Pieter Vander Vennet"
 | 
					      "contributor": "Pieter Vander Vennet"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@
 | 
				
			||||||
      "contributor": "paunofu"
 | 
					      "contributor": "paunofu"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "commits": 28,
 | 
					      "commits": 29,
 | 
				
			||||||
      "contributor": "Hosted Weblate"
 | 
					      "contributor": "Hosted Weblate"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@
 | 
				
			||||||
  "gl": "lingua galega",
 | 
					  "gl": "lingua galega",
 | 
				
			||||||
  "he": "עברית",
 | 
					  "he": "עברית",
 | 
				
			||||||
  "hu": "magyar",
 | 
					  "hu": "magyar",
 | 
				
			||||||
  "id": "Indonesia",
 | 
					  "id": "bahasa Indonesia",
 | 
				
			||||||
  "it": "italiano",
 | 
					  "it": "italiano",
 | 
				
			||||||
  "ja": "日本語",
 | 
					  "ja": "日本語",
 | 
				
			||||||
  "nb_NO": "bokmål",
 | 
					  "nb_NO": "bokmål",
 | 
				
			||||||
| 
						 | 
					@ -23,5 +23,6 @@
 | 
				
			||||||
  "ru": "русский язык",
 | 
					  "ru": "русский язык",
 | 
				
			||||||
  "sl": "slovenščina",
 | 
					  "sl": "slovenščina",
 | 
				
			||||||
  "sv": "svenska",
 | 
					  "sv": "svenska",
 | 
				
			||||||
  "zh_Hant": "簡體中文"
 | 
					  "zh_Hans": "简体中文",
 | 
				
			||||||
 | 
					  "zh_Hant": "繁體中文"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -146,7 +146,7 @@
 | 
				
			||||||
    "gl": "Lingua adigue",
 | 
					    "gl": "Lingua adigue",
 | 
				
			||||||
    "he": "אדיגית",
 | 
					    "he": "אדיגית",
 | 
				
			||||||
    "hu": "adigei",
 | 
					    "hu": "adigei",
 | 
				
			||||||
    "id": "Adyghe",
 | 
					    "id": "bahasa Adyghe",
 | 
				
			||||||
    "it": "adighè",
 | 
					    "it": "adighè",
 | 
				
			||||||
    "ja": "アディゲ語",
 | 
					    "ja": "アディゲ語",
 | 
				
			||||||
    "nb_NO": "adygeisk",
 | 
					    "nb_NO": "adygeisk",
 | 
				
			||||||
| 
						 | 
					@ -603,7 +603,7 @@
 | 
				
			||||||
    "gl": "árabe",
 | 
					    "gl": "árabe",
 | 
				
			||||||
    "he": "ערבית",
 | 
					    "he": "ערבית",
 | 
				
			||||||
    "hu": "arab",
 | 
					    "hu": "arab",
 | 
				
			||||||
    "id": "Arab",
 | 
					    "id": "bahasa Arab",
 | 
				
			||||||
    "it": "arabo",
 | 
					    "it": "arabo",
 | 
				
			||||||
    "ja": "アラビア語",
 | 
					    "ja": "アラビア語",
 | 
				
			||||||
    "nb_NO": "arabisk",
 | 
					    "nb_NO": "arabisk",
 | 
				
			||||||
| 
						 | 
					@ -929,7 +929,7 @@
 | 
				
			||||||
    "fi": "Awadhin kieli",
 | 
					    "fi": "Awadhin kieli",
 | 
				
			||||||
    "fr": "awadhi",
 | 
					    "fr": "awadhi",
 | 
				
			||||||
    "gl": "Lingua awadhi",
 | 
					    "gl": "Lingua awadhi",
 | 
				
			||||||
    "he": "אוודית",
 | 
					    "he": "אוודהית",
 | 
				
			||||||
    "id": "Bahasa Awadhi",
 | 
					    "id": "Bahasa Awadhi",
 | 
				
			||||||
    "it": "awadhi",
 | 
					    "it": "awadhi",
 | 
				
			||||||
    "ja": "アワディー語",
 | 
					    "ja": "アワディー語",
 | 
				
			||||||
| 
						 | 
					@ -1603,7 +1603,7 @@
 | 
				
			||||||
    "gl": "lingua bretoa",
 | 
					    "gl": "lingua bretoa",
 | 
				
			||||||
    "he": "ברטונית",
 | 
					    "he": "ברטונית",
 | 
				
			||||||
    "hu": "breton",
 | 
					    "hu": "breton",
 | 
				
			||||||
    "id": "Breton",
 | 
					    "id": "Bahasa Breton",
 | 
				
			||||||
    "it": "bretone",
 | 
					    "it": "bretone",
 | 
				
			||||||
    "ja": "ブルトン語",
 | 
					    "ja": "ブルトン語",
 | 
				
			||||||
    "nb_NO": "bretonsk",
 | 
					    "nb_NO": "bretonsk",
 | 
				
			||||||
| 
						 | 
					@ -1772,7 +1772,7 @@
 | 
				
			||||||
    "gl": "Lingua buriata",
 | 
					    "gl": "Lingua buriata",
 | 
				
			||||||
    "he": "בוריאטית",
 | 
					    "he": "בוריאטית",
 | 
				
			||||||
    "hu": "burját",
 | 
					    "hu": "burját",
 | 
				
			||||||
    "id": "Buryat",
 | 
					    "id": "bahasa Buryat",
 | 
				
			||||||
    "it": "buriato",
 | 
					    "it": "buriato",
 | 
				
			||||||
    "ja": "ブリヤート語",
 | 
					    "ja": "ブリヤート語",
 | 
				
			||||||
    "nb_NO": "burjatisk",
 | 
					    "nb_NO": "burjatisk",
 | 
				
			||||||
| 
						 | 
					@ -2316,7 +2316,7 @@
 | 
				
			||||||
    "gl": "Lingua tártara de Crimea",
 | 
					    "gl": "Lingua tártara de Crimea",
 | 
				
			||||||
    "he": "טטרית של קרים",
 | 
					    "he": "טטרית של קרים",
 | 
				
			||||||
    "hu": "krími tatár",
 | 
					    "hu": "krími tatár",
 | 
				
			||||||
    "id": "Tatar Krimea",
 | 
					    "id": "Bahasa Tatar Krimea",
 | 
				
			||||||
    "it": "tataro di Crimea",
 | 
					    "it": "tataro di Crimea",
 | 
				
			||||||
    "ja": "クリミア・タタール語",
 | 
					    "ja": "クリミア・タタール語",
 | 
				
			||||||
    "nb_NO": "krimtatarisk",
 | 
					    "nb_NO": "krimtatarisk",
 | 
				
			||||||
| 
						 | 
					@ -2442,7 +2442,6 @@
 | 
				
			||||||
    "id": "Bahasa Chittagonia",
 | 
					    "id": "Bahasa Chittagonia",
 | 
				
			||||||
    "it": "lingua chittagonian",
 | 
					    "it": "lingua chittagonian",
 | 
				
			||||||
    "ja": "チッタゴン語",
 | 
					    "ja": "チッタゴン語",
 | 
				
			||||||
    "nb_NO": "Chittagong",
 | 
					 | 
				
			||||||
    "pl": "Język chatgaya",
 | 
					    "pl": "Język chatgaya",
 | 
				
			||||||
    "pt": "Língua chittagong",
 | 
					    "pt": "Língua chittagong",
 | 
				
			||||||
    "pt_BR": "Língua chittagong",
 | 
					    "pt_BR": "Língua chittagong",
 | 
				
			||||||
| 
						 | 
					@ -2533,7 +2532,7 @@
 | 
				
			||||||
    "gl": "lingua dinamarquesa",
 | 
					    "gl": "lingua dinamarquesa",
 | 
				
			||||||
    "he": "דנית",
 | 
					    "he": "דנית",
 | 
				
			||||||
    "hu": "dán",
 | 
					    "hu": "dán",
 | 
				
			||||||
    "id": "Denmark",
 | 
					    "id": "bahasa Denmark",
 | 
				
			||||||
    "it": "danese",
 | 
					    "it": "danese",
 | 
				
			||||||
    "ja": "デンマーク語",
 | 
					    "ja": "デンマーク語",
 | 
				
			||||||
    "nb_NO": "dansk",
 | 
					    "nb_NO": "dansk",
 | 
				
			||||||
| 
						 | 
					@ -2596,7 +2595,7 @@
 | 
				
			||||||
    "gl": "lingua alemá",
 | 
					    "gl": "lingua alemá",
 | 
				
			||||||
    "he": "גרמנית",
 | 
					    "he": "גרמנית",
 | 
				
			||||||
    "hu": "német",
 | 
					    "hu": "német",
 | 
				
			||||||
    "id": "Jerman",
 | 
					    "id": "bahasa Jerman",
 | 
				
			||||||
    "it": "tedesco",
 | 
					    "it": "tedesco",
 | 
				
			||||||
    "ja": "ドイツ語",
 | 
					    "ja": "ドイツ語",
 | 
				
			||||||
    "nb_NO": "tysk",
 | 
					    "nb_NO": "tysk",
 | 
				
			||||||
| 
						 | 
					@ -2967,8 +2966,8 @@
 | 
				
			||||||
    "ru": "новогреческий язык",
 | 
					    "ru": "новогреческий язык",
 | 
				
			||||||
    "sl": "novogrščina",
 | 
					    "sl": "novogrščina",
 | 
				
			||||||
    "sv": "nygrekiska",
 | 
					    "sv": "nygrekiska",
 | 
				
			||||||
    "zh_Hans": "现代希腊语",
 | 
					    "zh_Hans": "希腊语",
 | 
				
			||||||
    "zh_Hant": "現代希臘語",
 | 
					    "zh_Hant": "希臘語",
 | 
				
			||||||
    "_meta": {
 | 
					    "_meta": {
 | 
				
			||||||
      "countries": [
 | 
					      "countries": [
 | 
				
			||||||
        "CY",
 | 
					        "CY",
 | 
				
			||||||
| 
						 | 
					@ -3585,7 +3584,7 @@
 | 
				
			||||||
    "gl": "lingua feroesa",
 | 
					    "gl": "lingua feroesa",
 | 
				
			||||||
    "he": "פארואזית",
 | 
					    "he": "פארואזית",
 | 
				
			||||||
    "hu": "feröeri",
 | 
					    "hu": "feröeri",
 | 
				
			||||||
    "id": "Faroe",
 | 
					    "id": "bahasa Faroe",
 | 
				
			||||||
    "it": "faroese",
 | 
					    "it": "faroese",
 | 
				
			||||||
    "ja": "フェロー語",
 | 
					    "ja": "フェロー語",
 | 
				
			||||||
    "nb_NO": "færøysk",
 | 
					    "nb_NO": "færøysk",
 | 
				
			||||||
| 
						 | 
					@ -4873,7 +4872,7 @@
 | 
				
			||||||
    "gl": "lingua indonesia",
 | 
					    "gl": "lingua indonesia",
 | 
				
			||||||
    "he": "אינדונזית",
 | 
					    "he": "אינדונזית",
 | 
				
			||||||
    "hu": "indonéz",
 | 
					    "hu": "indonéz",
 | 
				
			||||||
    "id": "Indonesia",
 | 
					    "id": "bahasa Indonesia",
 | 
				
			||||||
    "it": "indonesiano",
 | 
					    "it": "indonesiano",
 | 
				
			||||||
    "ja": "インドネシア語",
 | 
					    "ja": "インドネシア語",
 | 
				
			||||||
    "nb_NO": "indonesisk",
 | 
					    "nb_NO": "indonesisk",
 | 
				
			||||||
| 
						 | 
					@ -5020,7 +5019,7 @@
 | 
				
			||||||
    "gl": "lingua islandesa",
 | 
					    "gl": "lingua islandesa",
 | 
				
			||||||
    "he": "איסלנדית",
 | 
					    "he": "איסלנדית",
 | 
				
			||||||
    "hu": "izlandi",
 | 
					    "hu": "izlandi",
 | 
				
			||||||
    "id": "Islandia",
 | 
					    "id": "bahasa Islandia",
 | 
				
			||||||
    "it": "islandese",
 | 
					    "it": "islandese",
 | 
				
			||||||
    "ja": "アイスランド語",
 | 
					    "ja": "アイスランド語",
 | 
				
			||||||
    "nb_NO": "islandsk",
 | 
					    "nb_NO": "islandsk",
 | 
				
			||||||
| 
						 | 
					@ -5056,7 +5055,7 @@
 | 
				
			||||||
    "gl": "lingua italiana",
 | 
					    "gl": "lingua italiana",
 | 
				
			||||||
    "he": "איטלקית",
 | 
					    "he": "איטלקית",
 | 
				
			||||||
    "hu": "olasz",
 | 
					    "hu": "olasz",
 | 
				
			||||||
    "id": "Italia",
 | 
					    "id": "bahasa Italia",
 | 
				
			||||||
    "it": "italiano",
 | 
					    "it": "italiano",
 | 
				
			||||||
    "ja": "イタリア語",
 | 
					    "ja": "イタリア語",
 | 
				
			||||||
    "nb_NO": "italiensk",
 | 
					    "nb_NO": "italiensk",
 | 
				
			||||||
| 
						 | 
					@ -5128,7 +5127,7 @@
 | 
				
			||||||
    "gl": "lingua xaponesa",
 | 
					    "gl": "lingua xaponesa",
 | 
				
			||||||
    "he": "יפנית",
 | 
					    "he": "יפנית",
 | 
				
			||||||
    "hu": "japán",
 | 
					    "hu": "japán",
 | 
				
			||||||
    "id": "Jepang",
 | 
					    "id": "bahasa Jepang",
 | 
				
			||||||
    "it": "giapponese",
 | 
					    "it": "giapponese",
 | 
				
			||||||
    "ja": "日本語",
 | 
					    "ja": "日本語",
 | 
				
			||||||
    "nb_NO": "japansk",
 | 
					    "nb_NO": "japansk",
 | 
				
			||||||
| 
						 | 
					@ -5211,7 +5210,7 @@
 | 
				
			||||||
    "gl": "Lingua xavanesa",
 | 
					    "gl": "Lingua xavanesa",
 | 
				
			||||||
    "he": "ג'אווה",
 | 
					    "he": "ג'אווה",
 | 
				
			||||||
    "hu": "jávai",
 | 
					    "hu": "jávai",
 | 
				
			||||||
    "id": "Jawa",
 | 
					    "id": "bahasa Jawa",
 | 
				
			||||||
    "it": "giavanese",
 | 
					    "it": "giavanese",
 | 
				
			||||||
    "ja": "ジャワ語",
 | 
					    "ja": "ジャワ語",
 | 
				
			||||||
    "nb_NO": "javanesisk",
 | 
					    "nb_NO": "javanesisk",
 | 
				
			||||||
| 
						 | 
					@ -5248,7 +5247,7 @@
 | 
				
			||||||
    "gl": "lingua xeorxiana",
 | 
					    "gl": "lingua xeorxiana",
 | 
				
			||||||
    "he": "גאורגית",
 | 
					    "he": "גאורגית",
 | 
				
			||||||
    "hu": "grúz",
 | 
					    "hu": "grúz",
 | 
				
			||||||
    "id": "Georgia",
 | 
					    "id": "Bahasa Georgia",
 | 
				
			||||||
    "it": "georgiano",
 | 
					    "it": "georgiano",
 | 
				
			||||||
    "ja": "ジョージア語",
 | 
					    "ja": "ジョージア語",
 | 
				
			||||||
    "nb_NO": "georgisk",
 | 
					    "nb_NO": "georgisk",
 | 
				
			||||||
| 
						 | 
					@ -5283,7 +5282,7 @@
 | 
				
			||||||
    "gl": "Lingua karakalpak",
 | 
					    "gl": "Lingua karakalpak",
 | 
				
			||||||
    "he": "קראקלפקית",
 | 
					    "he": "קראקלפקית",
 | 
				
			||||||
    "hu": "karakalpak",
 | 
					    "hu": "karakalpak",
 | 
				
			||||||
    "id": "Karakalpak",
 | 
					    "id": "Bahasa Karakalpak",
 | 
				
			||||||
    "it": "karakalpako",
 | 
					    "it": "karakalpako",
 | 
				
			||||||
    "ja": "カラカルパク語",
 | 
					    "ja": "カラカルパク語",
 | 
				
			||||||
    "nl": "Karakalpaks",
 | 
					    "nl": "Karakalpaks",
 | 
				
			||||||
| 
						 | 
					@ -5467,7 +5466,6 @@
 | 
				
			||||||
    "ja": "カインガング語",
 | 
					    "ja": "カインガング語",
 | 
				
			||||||
    "nb_NO": "Kaingang",
 | 
					    "nb_NO": "Kaingang",
 | 
				
			||||||
    "nl": "Kaingang",
 | 
					    "nl": "Kaingang",
 | 
				
			||||||
    "pl": "Języki caingang",
 | 
					 | 
				
			||||||
    "pt": "Língua caingangue",
 | 
					    "pt": "Língua caingangue",
 | 
				
			||||||
    "pt_BR": "Língua kaingáng",
 | 
					    "pt_BR": "Língua kaingáng",
 | 
				
			||||||
    "ru": "Каинганг",
 | 
					    "ru": "Каинганг",
 | 
				
			||||||
| 
						 | 
					@ -5638,7 +5636,7 @@
 | 
				
			||||||
    "gl": "Lingua casaca",
 | 
					    "gl": "Lingua casaca",
 | 
				
			||||||
    "he": "קזחית",
 | 
					    "he": "קזחית",
 | 
				
			||||||
    "hu": "kazak",
 | 
					    "hu": "kazak",
 | 
				
			||||||
    "id": "Kazakh",
 | 
					    "id": "bahasa Kazakh",
 | 
				
			||||||
    "it": "kazako",
 | 
					    "it": "kazako",
 | 
				
			||||||
    "ja": "カザフ語",
 | 
					    "ja": "カザフ語",
 | 
				
			||||||
    "nb_NO": "kasakhisk",
 | 
					    "nb_NO": "kasakhisk",
 | 
				
			||||||
| 
						 | 
					@ -5675,7 +5673,7 @@
 | 
				
			||||||
    "gl": "Lingua grenlandesa",
 | 
					    "gl": "Lingua grenlandesa",
 | 
				
			||||||
    "he": "גרינלנדית",
 | 
					    "he": "גרינלנדית",
 | 
				
			||||||
    "hu": "grönlandi",
 | 
					    "hu": "grönlandi",
 | 
				
			||||||
    "id": "Greenland",
 | 
					    "id": "bahasa Greenland",
 | 
				
			||||||
    "it": "groenlandese",
 | 
					    "it": "groenlandese",
 | 
				
			||||||
    "ja": "グリーンランド語",
 | 
					    "ja": "グリーンランド語",
 | 
				
			||||||
    "nb_NO": "grønlandsk",
 | 
					    "nb_NO": "grønlandsk",
 | 
				
			||||||
| 
						 | 
					@ -5707,7 +5705,7 @@
 | 
				
			||||||
    "gl": "Lingua khmer",
 | 
					    "gl": "Lingua khmer",
 | 
				
			||||||
    "he": "קמרית",
 | 
					    "he": "קמרית",
 | 
				
			||||||
    "hu": "khmer",
 | 
					    "hu": "khmer",
 | 
				
			||||||
    "id": "Khmer",
 | 
					    "id": "bahasa Khmer",
 | 
				
			||||||
    "it": "khmer",
 | 
					    "it": "khmer",
 | 
				
			||||||
    "ja": "クメール語",
 | 
					    "ja": "クメール語",
 | 
				
			||||||
    "nb_NO": "khmer",
 | 
					    "nb_NO": "khmer",
 | 
				
			||||||
| 
						 | 
					@ -5818,7 +5816,6 @@
 | 
				
			||||||
    "pl": "język komi-permiacki",
 | 
					    "pl": "język komi-permiacki",
 | 
				
			||||||
    "pt": "Língua komi-permyak",
 | 
					    "pt": "Língua komi-permyak",
 | 
				
			||||||
    "ru": "коми-пермяцкий язык",
 | 
					    "ru": "коми-пермяцкий язык",
 | 
				
			||||||
    "sl": "permjaščina",
 | 
					 | 
				
			||||||
    "sv": "komi-permjakiska",
 | 
					    "sv": "komi-permjakiska",
 | 
				
			||||||
    "zh_Hans": "彼尔姆科米语",
 | 
					    "zh_Hans": "彼尔姆科米语",
 | 
				
			||||||
    "zh_Hant": "彼爾姆科米語",
 | 
					    "zh_Hant": "彼爾姆科米語",
 | 
				
			||||||
| 
						 | 
					@ -6028,32 +6025,32 @@
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "ku": {
 | 
					  "ku": {
 | 
				
			||||||
    "ca": "kurd",
 | 
					    "ca": "kurd del nord",
 | 
				
			||||||
    "cs": "kurdština",
 | 
					    "cs": "kurmándží",
 | 
				
			||||||
    "da": "kurdisk",
 | 
					    "da": "Kurmanji",
 | 
				
			||||||
    "de": "Kurdisch",
 | 
					    "de": "Kurmandschi",
 | 
				
			||||||
    "en": "Kurdish",
 | 
					    "en": "Kurmanji",
 | 
				
			||||||
    "eo": "kurda lingvo",
 | 
					    "eo": "kurmanĝa lingvo",
 | 
				
			||||||
    "es": "kurdo",
 | 
					    "es": "kurmanji",
 | 
				
			||||||
    "eu": "kurduera",
 | 
					    "eu": "Kurmanji",
 | 
				
			||||||
    "fi": "kurdi",
 | 
					    "fi": "Kurmandži",
 | 
				
			||||||
    "fr": "kurde",
 | 
					    "fr": "kurmandji",
 | 
				
			||||||
    "gl": "lingua kurda",
 | 
					    "gl": "lingua kurda",
 | 
				
			||||||
    "he": "כורדית",
 | 
					    "he": "כורמנג'ית",
 | 
				
			||||||
    "hu": "kurd",
 | 
					    "hu": "kurmandzsi",
 | 
				
			||||||
    "id": "Bahasa Kurdi",
 | 
					    "id": "Kurmanji",
 | 
				
			||||||
    "it": "curdo",
 | 
					    "it": "kurmanji",
 | 
				
			||||||
    "ja": "クルド語",
 | 
					    "ja": "クルマンジー",
 | 
				
			||||||
    "nb_NO": "kurdisk",
 | 
					    "nb_NO": "kurdisk",
 | 
				
			||||||
    "nl": "Koerdisch",
 | 
					    "nl": "Kurmançi",
 | 
				
			||||||
    "pl": "język kurdyjski",
 | 
					    "pl": "język kurmandżi",
 | 
				
			||||||
    "pt": "língua curda",
 | 
					    "pt": "curmânji",
 | 
				
			||||||
    "pt_BR": "língua curda",
 | 
					    "pt_BR": "Curmânji",
 | 
				
			||||||
    "ru": "курдские языки",
 | 
					    "ru": "курманджи",
 | 
				
			||||||
    "sl": "kurdščina",
 | 
					    "sl": "kurmandži",
 | 
				
			||||||
    "sv": "kurdiska",
 | 
					    "sv": "nordkurdiska",
 | 
				
			||||||
    "zh_Hans": "库尔德语",
 | 
					    "zh_Hans": "库尔德语",
 | 
				
			||||||
    "zh_Hant": "庫德語",
 | 
					    "zh_Hant": "北庫德語",
 | 
				
			||||||
    "_meta": {
 | 
					    "_meta": {
 | 
				
			||||||
      "countries": [
 | 
					      "countries": [
 | 
				
			||||||
        "IQ"
 | 
					        "IQ"
 | 
				
			||||||
| 
						 | 
					@ -6130,7 +6127,7 @@
 | 
				
			||||||
    "gl": "lingua komi",
 | 
					    "gl": "lingua komi",
 | 
				
			||||||
    "he": "קומי",
 | 
					    "he": "קומי",
 | 
				
			||||||
    "hu": "komi",
 | 
					    "hu": "komi",
 | 
				
			||||||
    "id": "Komi",
 | 
					    "id": "Bahasa Komi",
 | 
				
			||||||
    "it": "comi",
 | 
					    "it": "comi",
 | 
				
			||||||
    "ja": "コミ語",
 | 
					    "ja": "コミ語",
 | 
				
			||||||
    "nb_NO": "syrjensk",
 | 
					    "nb_NO": "syrjensk",
 | 
				
			||||||
| 
						 | 
					@ -6138,7 +6135,6 @@
 | 
				
			||||||
    "pl": "język komi",
 | 
					    "pl": "język komi",
 | 
				
			||||||
    "pt": "língua komi",
 | 
					    "pt": "língua komi",
 | 
				
			||||||
    "ru": "коми язык",
 | 
					    "ru": "коми язык",
 | 
				
			||||||
    "sl": "komijščina",
 | 
					 | 
				
			||||||
    "sv": "komi",
 | 
					    "sv": "komi",
 | 
				
			||||||
    "_meta": {
 | 
					    "_meta": {
 | 
				
			||||||
      "dir": [
 | 
					      "dir": [
 | 
				
			||||||
| 
						 | 
					@ -6221,7 +6217,7 @@
 | 
				
			||||||
    "gl": "kirguiz",
 | 
					    "gl": "kirguiz",
 | 
				
			||||||
    "he": "קירגיזית",
 | 
					    "he": "קירגיזית",
 | 
				
			||||||
    "hu": "kirgiz",
 | 
					    "hu": "kirgiz",
 | 
				
			||||||
    "id": "Kirgiz",
 | 
					    "id": "bahasa Kirgiz",
 | 
				
			||||||
    "it": "kirghiso",
 | 
					    "it": "kirghiso",
 | 
				
			||||||
    "ja": "キルギス語",
 | 
					    "ja": "キルギス語",
 | 
				
			||||||
    "nb_NO": "kirgisisk",
 | 
					    "nb_NO": "kirgisisk",
 | 
				
			||||||
| 
						 | 
					@ -6307,7 +6303,7 @@
 | 
				
			||||||
    "gl": "Lingua luxemburguesa",
 | 
					    "gl": "Lingua luxemburguesa",
 | 
				
			||||||
    "he": "לוקסמבורגית",
 | 
					    "he": "לוקסמבורגית",
 | 
				
			||||||
    "hu": "luxemburgi",
 | 
					    "hu": "luxemburgi",
 | 
				
			||||||
    "id": "Luksemburg",
 | 
					    "id": "bahasa Luksemburg",
 | 
				
			||||||
    "it": "lussemburghese",
 | 
					    "it": "lussemburghese",
 | 
				
			||||||
    "ja": "ルクセンブルク語",
 | 
					    "ja": "ルクセンブルク語",
 | 
				
			||||||
    "nb_NO": "luxembourgsk",
 | 
					    "nb_NO": "luxembourgsk",
 | 
				
			||||||
| 
						 | 
					@ -6547,7 +6543,7 @@
 | 
				
			||||||
    "gl": "Lingua lombarda",
 | 
					    "gl": "Lingua lombarda",
 | 
				
			||||||
    "he": "לומברד (שפה)",
 | 
					    "he": "לומברד (שפה)",
 | 
				
			||||||
    "hu": "lombard",
 | 
					    "hu": "lombard",
 | 
				
			||||||
    "id": "Lombard",
 | 
					    "id": "bahasa Lombard",
 | 
				
			||||||
    "it": "lingua lombarda",
 | 
					    "it": "lingua lombarda",
 | 
				
			||||||
    "ja": "ロンバルド語",
 | 
					    "ja": "ロンバルド語",
 | 
				
			||||||
    "nb_NO": "lombardisk",
 | 
					    "nb_NO": "lombardisk",
 | 
				
			||||||
| 
						 | 
					@ -6607,7 +6603,7 @@
 | 
				
			||||||
    "gl": "Lingua laosiana",
 | 
					    "gl": "Lingua laosiana",
 | 
				
			||||||
    "he": "לאית",
 | 
					    "he": "לאית",
 | 
				
			||||||
    "hu": "lao",
 | 
					    "hu": "lao",
 | 
				
			||||||
    "id": "Lao",
 | 
					    "id": "bahasa Lao",
 | 
				
			||||||
    "it": "lao",
 | 
					    "it": "lao",
 | 
				
			||||||
    "ja": "ラーオ語",
 | 
					    "ja": "ラーオ語",
 | 
				
			||||||
    "nb_NO": "laotisk",
 | 
					    "nb_NO": "laotisk",
 | 
				
			||||||
| 
						 | 
					@ -6977,7 +6973,7 @@
 | 
				
			||||||
    "gl": "Lingua malgaxe",
 | 
					    "gl": "Lingua malgaxe",
 | 
				
			||||||
    "he": "מלגשית",
 | 
					    "he": "מלגשית",
 | 
				
			||||||
    "hu": "malgas",
 | 
					    "hu": "malgas",
 | 
				
			||||||
    "id": "Malagasi",
 | 
					    "id": "Bahasa Malagasi",
 | 
				
			||||||
    "it": "malgascio",
 | 
					    "it": "malgascio",
 | 
				
			||||||
    "ja": "マダガスカル語",
 | 
					    "ja": "マダガスカル語",
 | 
				
			||||||
    "nb_NO": "gassisk",
 | 
					    "nb_NO": "gassisk",
 | 
				
			||||||
| 
						 | 
					@ -7163,7 +7159,7 @@
 | 
				
			||||||
    "gl": "Lingua macedonia",
 | 
					    "gl": "Lingua macedonia",
 | 
				
			||||||
    "he": "מקדונית",
 | 
					    "he": "מקדונית",
 | 
				
			||||||
    "hu": "macedón",
 | 
					    "hu": "macedón",
 | 
				
			||||||
    "id": "Makedonia",
 | 
					    "id": "bahasa Makedonia",
 | 
				
			||||||
    "it": "macedone",
 | 
					    "it": "macedone",
 | 
				
			||||||
    "ja": "マケドニア語",
 | 
					    "ja": "マケドニア語",
 | 
				
			||||||
    "nb_NO": "makedonsk",
 | 
					    "nb_NO": "makedonsk",
 | 
				
			||||||
| 
						 | 
					@ -7231,7 +7227,7 @@
 | 
				
			||||||
    "gl": "Lingua mongol",
 | 
					    "gl": "Lingua mongol",
 | 
				
			||||||
    "he": "מונגולית",
 | 
					    "he": "מונגולית",
 | 
				
			||||||
    "hu": "mongol",
 | 
					    "hu": "mongol",
 | 
				
			||||||
    "id": "Mongol",
 | 
					    "id": "bahasa Mongol",
 | 
				
			||||||
    "it": "mongolo",
 | 
					    "it": "mongolo",
 | 
				
			||||||
    "ja": "モンゴル語",
 | 
					    "ja": "モンゴル語",
 | 
				
			||||||
    "nb_NO": "mongolsk",
 | 
					    "nb_NO": "mongolsk",
 | 
				
			||||||
| 
						 | 
					@ -7472,7 +7468,7 @@
 | 
				
			||||||
    "gl": "lingua malaia",
 | 
					    "gl": "lingua malaia",
 | 
				
			||||||
    "he": "מלאית",
 | 
					    "he": "מלאית",
 | 
				
			||||||
    "hu": "maláj",
 | 
					    "hu": "maláj",
 | 
				
			||||||
    "id": "Melayu",
 | 
					    "id": "bahasa Melayu",
 | 
				
			||||||
    "it": "malese",
 | 
					    "it": "malese",
 | 
				
			||||||
    "ja": "マレー語",
 | 
					    "ja": "マレー語",
 | 
				
			||||||
    "nb_NO": "malayisk",
 | 
					    "nb_NO": "malayisk",
 | 
				
			||||||
| 
						 | 
					@ -7650,7 +7646,7 @@
 | 
				
			||||||
    "gl": "birmano",
 | 
					    "gl": "birmano",
 | 
				
			||||||
    "he": "בורמזית",
 | 
					    "he": "בורמזית",
 | 
				
			||||||
    "hu": "burmai",
 | 
					    "hu": "burmai",
 | 
				
			||||||
    "id": "Burma",
 | 
					    "id": "bahasa Burma",
 | 
				
			||||||
    "it": "birmano",
 | 
					    "it": "birmano",
 | 
				
			||||||
    "ja": "ビルマ語",
 | 
					    "ja": "ビルマ語",
 | 
				
			||||||
    "nb_NO": "burmesisk",
 | 
					    "nb_NO": "burmesisk",
 | 
				
			||||||
| 
						 | 
					@ -8112,7 +8108,7 @@
 | 
				
			||||||
    "gl": "lingua norueguesa",
 | 
					    "gl": "lingua norueguesa",
 | 
				
			||||||
    "he": "נורווגית",
 | 
					    "he": "נורווגית",
 | 
				
			||||||
    "hu": "norvég",
 | 
					    "hu": "norvég",
 | 
				
			||||||
    "id": "Norwegia",
 | 
					    "id": "bahasa Norwegia",
 | 
				
			||||||
    "it": "norvegese",
 | 
					    "it": "norvegese",
 | 
				
			||||||
    "ja": "ノルウェー語",
 | 
					    "ja": "ノルウェー語",
 | 
				
			||||||
    "nb_NO": "norsk",
 | 
					    "nb_NO": "norsk",
 | 
				
			||||||
| 
						 | 
					@ -8439,12 +8435,12 @@
 | 
				
			||||||
    "eo": "olonec-karela lingvo",
 | 
					    "eo": "olonec-karela lingvo",
 | 
				
			||||||
    "fi": "livvinkarjala",
 | 
					    "fi": "livvinkarjala",
 | 
				
			||||||
    "fr": "olonetsien",
 | 
					    "fr": "olonetsien",
 | 
				
			||||||
    "gl": "lingua livvi",
 | 
					    "gl": "Lingua livvi",
 | 
				
			||||||
    "it": "lingua livvi",
 | 
					    "it": "lingua livvi",
 | 
				
			||||||
    "ja": "リッヴィ語",
 | 
					    "ja": "リッヴィ語",
 | 
				
			||||||
    "nb_NO": "livvisk",
 | 
					    "nb_NO": "livvisk",
 | 
				
			||||||
    "nl": "Olonetsisch",
 | 
					    "nl": "Olonetsisch",
 | 
				
			||||||
    "pl": "dialekt ołoniecki",
 | 
					    "pl": "Dialekt ołoniecki",
 | 
				
			||||||
    "ru": "ливвиковское наречие",
 | 
					    "ru": "ливвиковское наречие",
 | 
				
			||||||
    "sv": "livvi",
 | 
					    "sv": "livvi",
 | 
				
			||||||
    "zh_Hant": "利維卡累利阿語",
 | 
					    "zh_Hant": "利維卡累利阿語",
 | 
				
			||||||
| 
						 | 
					@ -8549,7 +8545,7 @@
 | 
				
			||||||
    "gl": "Lingua oseta",
 | 
					    "gl": "Lingua oseta",
 | 
				
			||||||
    "he": "אוסטית",
 | 
					    "he": "אוסטית",
 | 
				
			||||||
    "hu": "oszét",
 | 
					    "hu": "oszét",
 | 
				
			||||||
    "id": "Ossetia",
 | 
					    "id": "bahasa Ossetia",
 | 
				
			||||||
    "it": "osseto",
 | 
					    "it": "osseto",
 | 
				
			||||||
    "ja": "オセット語",
 | 
					    "ja": "オセット語",
 | 
				
			||||||
    "nb_NO": "ossetisk",
 | 
					    "nb_NO": "ossetisk",
 | 
				
			||||||
| 
						 | 
					@ -8625,7 +8621,7 @@
 | 
				
			||||||
    "gl": "lingua punjabi (Shahmukhi)",
 | 
					    "gl": "lingua punjabi (Shahmukhi)",
 | 
				
			||||||
    "he": "פנג'אבי (אלפבית שאהמוקי)",
 | 
					    "he": "פנג'אבי (אלפבית שאהמוקי)",
 | 
				
			||||||
    "hu": "pandzsábi (Shahmukhi)",
 | 
					    "hu": "pandzsábi (Shahmukhi)",
 | 
				
			||||||
    "id": "Punjab (Abjad Shahmukhi)",
 | 
					    "id": "Bahasa Punjab (Abjad Shahmukhi)",
 | 
				
			||||||
    "it": "punjabi (Shahmukhī)",
 | 
					    "it": "punjabi (Shahmukhī)",
 | 
				
			||||||
    "ja": "パンジャーブ語 (シャームキー文字)",
 | 
					    "ja": "パンジャーブ語 (シャームキー文字)",
 | 
				
			||||||
    "nb_NO": "panjabi (Shahmukhi)",
 | 
					    "nb_NO": "panjabi (Shahmukhi)",
 | 
				
			||||||
| 
						 | 
					@ -8850,7 +8846,6 @@
 | 
				
			||||||
    "pl": "Język neosalomoński",
 | 
					    "pl": "Język neosalomoński",
 | 
				
			||||||
    "pt": "Língua pijin",
 | 
					    "pt": "Língua pijin",
 | 
				
			||||||
    "ru": "Пиджин Соломоновых Островов",
 | 
					    "ru": "Пиджин Соломоновых Островов",
 | 
				
			||||||
    "sl": "salomonski pidžin",
 | 
					 | 
				
			||||||
    "sv": "pijin",
 | 
					    "sv": "pijin",
 | 
				
			||||||
    "_meta": {
 | 
					    "_meta": {
 | 
				
			||||||
      "dir": [
 | 
					      "dir": [
 | 
				
			||||||
| 
						 | 
					@ -9048,7 +9043,7 @@
 | 
				
			||||||
    "gl": "lingua portuguesa",
 | 
					    "gl": "lingua portuguesa",
 | 
				
			||||||
    "he": "פורטוגזית",
 | 
					    "he": "פורטוגזית",
 | 
				
			||||||
    "hu": "portugál",
 | 
					    "hu": "portugál",
 | 
				
			||||||
    "id": "Portugis",
 | 
					    "id": "bahasa Portugis",
 | 
				
			||||||
    "it": "portoghese",
 | 
					    "it": "portoghese",
 | 
				
			||||||
    "ja": "ポルトガル語",
 | 
					    "ja": "ポルトガル語",
 | 
				
			||||||
    "nb_NO": "portugisisk",
 | 
					    "nb_NO": "portugisisk",
 | 
				
			||||||
| 
						 | 
					@ -9258,7 +9253,7 @@
 | 
				
			||||||
    "en": "Rakhine",
 | 
					    "en": "Rakhine",
 | 
				
			||||||
    "fr": "arakanais",
 | 
					    "fr": "arakanais",
 | 
				
			||||||
    "gl": "Lingua arakanesa",
 | 
					    "gl": "Lingua arakanesa",
 | 
				
			||||||
    "id": "Rakhine",
 | 
					    "id": "bahasa Rakhine",
 | 
				
			||||||
    "ja": "ラカイン語",
 | 
					    "ja": "ラカイン語",
 | 
				
			||||||
    "nl": "Arakanees",
 | 
					    "nl": "Arakanees",
 | 
				
			||||||
    "pl": "Język arakański",
 | 
					    "pl": "Język arakański",
 | 
				
			||||||
| 
						 | 
					@ -9506,7 +9501,7 @@
 | 
				
			||||||
    "gl": "Lingua arromanesa",
 | 
					    "gl": "Lingua arromanesa",
 | 
				
			||||||
    "he": "ארומנית",
 | 
					    "he": "ארומנית",
 | 
				
			||||||
    "hu": "aromán",
 | 
					    "hu": "aromán",
 | 
				
			||||||
    "id": "Arumania",
 | 
					    "id": "Bahasa Arumania",
 | 
				
			||||||
    "it": "arumeno",
 | 
					    "it": "arumeno",
 | 
				
			||||||
    "ja": "アルーマニア語",
 | 
					    "ja": "アルーマニア語",
 | 
				
			||||||
    "nb_NO": "arumensk",
 | 
					    "nb_NO": "arumensk",
 | 
				
			||||||
| 
						 | 
					@ -9901,7 +9896,7 @@
 | 
				
			||||||
    "ca": "taixelhit",
 | 
					    "ca": "taixelhit",
 | 
				
			||||||
    "cs": "tašelhit",
 | 
					    "cs": "tašelhit",
 | 
				
			||||||
    "de": "Taschelhit",
 | 
					    "de": "Taschelhit",
 | 
				
			||||||
    "en": "Tachelhit",
 | 
					    "en": "Shilha",
 | 
				
			||||||
    "eo": "ŝelha lingvo",
 | 
					    "eo": "ŝelha lingvo",
 | 
				
			||||||
    "es": "chilha",
 | 
					    "es": "chilha",
 | 
				
			||||||
    "fi": "Tašelhit",
 | 
					    "fi": "Tašelhit",
 | 
				
			||||||
| 
						 | 
					@ -10001,7 +9996,7 @@
 | 
				
			||||||
    "pt": "Língua cingalesa",
 | 
					    "pt": "Língua cingalesa",
 | 
				
			||||||
    "pt_BR": "Língua cingalesa",
 | 
					    "pt_BR": "Língua cingalesa",
 | 
				
			||||||
    "ru": "сингальский язык",
 | 
					    "ru": "сингальский язык",
 | 
				
			||||||
    "sl": "singalščina",
 | 
					    "sl": "sinhalščina",
 | 
				
			||||||
    "sv": "singalesiska",
 | 
					    "sv": "singalesiska",
 | 
				
			||||||
    "zh_Hant": "僧伽羅語",
 | 
					    "zh_Hant": "僧伽羅語",
 | 
				
			||||||
    "_meta": {
 | 
					    "_meta": {
 | 
				
			||||||
| 
						 | 
					@ -10461,7 +10456,7 @@
 | 
				
			||||||
    "gl": "Lingua albanesa",
 | 
					    "gl": "Lingua albanesa",
 | 
				
			||||||
    "he": "אלבנית",
 | 
					    "he": "אלבנית",
 | 
				
			||||||
    "hu": "albán",
 | 
					    "hu": "albán",
 | 
				
			||||||
    "id": "Albania",
 | 
					    "id": "Bahasa Albania",
 | 
				
			||||||
    "it": "albanese",
 | 
					    "it": "albanese",
 | 
				
			||||||
    "ja": "アルバニア語",
 | 
					    "ja": "アルバニア語",
 | 
				
			||||||
    "nb_NO": "albansk",
 | 
					    "nb_NO": "albansk",
 | 
				
			||||||
| 
						 | 
					@ -10704,7 +10699,7 @@
 | 
				
			||||||
    "gl": "lingua sueca",
 | 
					    "gl": "lingua sueca",
 | 
				
			||||||
    "he": "שוודית",
 | 
					    "he": "שוודית",
 | 
				
			||||||
    "hu": "svéd",
 | 
					    "hu": "svéd",
 | 
				
			||||||
    "id": "Swedia",
 | 
					    "id": "bahasa Swedia",
 | 
				
			||||||
    "it": "svedese",
 | 
					    "it": "svedese",
 | 
				
			||||||
    "ja": "スウェーデン語",
 | 
					    "ja": "スウェーデン語",
 | 
				
			||||||
    "nb_NO": "svensk",
 | 
					    "nb_NO": "svensk",
 | 
				
			||||||
| 
						 | 
					@ -10803,7 +10798,7 @@
 | 
				
			||||||
    "gl": "Lingua silesiana",
 | 
					    "gl": "Lingua silesiana",
 | 
				
			||||||
    "he": "שלזית",
 | 
					    "he": "שלזית",
 | 
				
			||||||
    "hu": "sziléziai",
 | 
					    "hu": "sziléziai",
 | 
				
			||||||
    "id": "Silesia",
 | 
					    "id": "bahasa Silesia",
 | 
				
			||||||
    "it": "slesiano",
 | 
					    "it": "slesiano",
 | 
				
			||||||
    "ja": "シレジア語",
 | 
					    "ja": "シレジア語",
 | 
				
			||||||
    "nb_NO": "schlesisk",
 | 
					    "nb_NO": "schlesisk",
 | 
				
			||||||
| 
						 | 
					@ -10852,7 +10847,7 @@
 | 
				
			||||||
    "gl": "Lingua támil",
 | 
					    "gl": "Lingua támil",
 | 
				
			||||||
    "he": "טמילית",
 | 
					    "he": "טמילית",
 | 
				
			||||||
    "hu": "tamil",
 | 
					    "hu": "tamil",
 | 
				
			||||||
    "id": "Tamil",
 | 
					    "id": "Bahasa Tamil",
 | 
				
			||||||
    "it": "tamil",
 | 
					    "it": "tamil",
 | 
				
			||||||
    "ja": "タミル語",
 | 
					    "ja": "タミル語",
 | 
				
			||||||
    "nb_NO": "tamilsk",
 | 
					    "nb_NO": "tamilsk",
 | 
				
			||||||
| 
						 | 
					@ -11039,7 +11034,7 @@
 | 
				
			||||||
    "gl": "lingua tailandesa",
 | 
					    "gl": "lingua tailandesa",
 | 
				
			||||||
    "he": "תאית",
 | 
					    "he": "תאית",
 | 
				
			||||||
    "hu": "thai",
 | 
					    "hu": "thai",
 | 
				
			||||||
    "id": "Thai",
 | 
					    "id": "bahasa Thai",
 | 
				
			||||||
    "it": "thailandese",
 | 
					    "it": "thailandese",
 | 
				
			||||||
    "ja": "タイ語",
 | 
					    "ja": "タイ語",
 | 
				
			||||||
    "nb_NO": "thai",
 | 
					    "nb_NO": "thai",
 | 
				
			||||||
| 
						 | 
					@ -11109,7 +11104,7 @@
 | 
				
			||||||
    "gl": "Lingua turcomá",
 | 
					    "gl": "Lingua turcomá",
 | 
				
			||||||
    "he": "טורקמנית",
 | 
					    "he": "טורקמנית",
 | 
				
			||||||
    "hu": "türkmén",
 | 
					    "hu": "türkmén",
 | 
				
			||||||
    "id": "Turkmen",
 | 
					    "id": "bahasa Turkmen",
 | 
				
			||||||
    "it": "Turkmeno",
 | 
					    "it": "Turkmeno",
 | 
				
			||||||
    "ja": "トルクメン語",
 | 
					    "ja": "トルクメン語",
 | 
				
			||||||
    "nb_NO": "turkmensk",
 | 
					    "nb_NO": "turkmensk",
 | 
				
			||||||
| 
						 | 
					@ -11637,7 +11632,7 @@
 | 
				
			||||||
    "gl": "Lingua uigur",
 | 
					    "gl": "Lingua uigur",
 | 
				
			||||||
    "he": "אויגורית",
 | 
					    "he": "אויגורית",
 | 
				
			||||||
    "hu": "ujgur",
 | 
					    "hu": "ujgur",
 | 
				
			||||||
    "id": "Uighur",
 | 
					    "id": "bahasa Uyghur",
 | 
				
			||||||
    "it": "uiguro",
 | 
					    "it": "uiguro",
 | 
				
			||||||
    "ja": "ウイグル語",
 | 
					    "ja": "ウイグル語",
 | 
				
			||||||
    "nb_NO": "uigurisk",
 | 
					    "nb_NO": "uigurisk",
 | 
				
			||||||
| 
						 | 
					@ -11707,7 +11702,7 @@
 | 
				
			||||||
    "gl": "Lingua usbeka",
 | 
					    "gl": "Lingua usbeka",
 | 
				
			||||||
    "he": "אוזבקית",
 | 
					    "he": "אוזבקית",
 | 
				
			||||||
    "hu": "üzbég",
 | 
					    "hu": "üzbég",
 | 
				
			||||||
    "id": "Uzbek",
 | 
					    "id": "bahasa Uzbek",
 | 
				
			||||||
    "it": "uzbeco",
 | 
					    "it": "uzbeco",
 | 
				
			||||||
    "ja": "ウズベク語",
 | 
					    "ja": "ウズベク語",
 | 
				
			||||||
    "nb_NO": "usbekisk",
 | 
					    "nb_NO": "usbekisk",
 | 
				
			||||||
| 
						 | 
					@ -12596,7 +12591,7 @@
 | 
				
			||||||
    "gl": "lingua chinesa",
 | 
					    "gl": "lingua chinesa",
 | 
				
			||||||
    "he": "סינית",
 | 
					    "he": "סינית",
 | 
				
			||||||
    "hu": "kínai",
 | 
					    "hu": "kínai",
 | 
				
			||||||
    "id": "Tionghoa",
 | 
					    "id": "bahasa Tionghoa",
 | 
				
			||||||
    "it": "cinese",
 | 
					    "it": "cinese",
 | 
				
			||||||
    "ja": "中国語",
 | 
					    "ja": "中国語",
 | 
				
			||||||
    "nb_NO": "kinesisk",
 | 
					    "nb_NO": "kinesisk",
 | 
				
			||||||
| 
						 | 
					@ -12652,7 +12647,7 @@
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "zh_Hant": {
 | 
					  "zh_Hans": {
 | 
				
			||||||
    "ca": "xinès simplificat",
 | 
					    "ca": "xinès simplificat",
 | 
				
			||||||
    "cs": "zjednodušená čínština",
 | 
					    "cs": "zjednodušená čínština",
 | 
				
			||||||
    "da": "forenklet kinesisk",
 | 
					    "da": "forenklet kinesisk",
 | 
				
			||||||
| 
						 | 
					@ -12661,7 +12656,6 @@
 | 
				
			||||||
    "eo": "simpligita ĉina skribsistemo",
 | 
					    "eo": "simpligita ĉina skribsistemo",
 | 
				
			||||||
    "es": "chino simplificado",
 | 
					    "es": "chino simplificado",
 | 
				
			||||||
    "eu": "Txinera sinplifikatua",
 | 
					    "eu": "Txinera sinplifikatua",
 | 
				
			||||||
    "fi": "perinteinen kiina",
 | 
					 | 
				
			||||||
    "fr": "chinois simplifié",
 | 
					    "fr": "chinois simplifié",
 | 
				
			||||||
    "gl": "chinés simplificado",
 | 
					    "gl": "chinés simplificado",
 | 
				
			||||||
    "he": "סינית מפושטת",
 | 
					    "he": "סינית מפושטת",
 | 
				
			||||||
| 
						 | 
					@ -12684,6 +12678,36 @@
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  "zh_Hant": {
 | 
				
			||||||
 | 
					    "ca": "xinès tradicional",
 | 
				
			||||||
 | 
					    "cs": "čínština (tradiční)",
 | 
				
			||||||
 | 
					    "da": "traditionel kinesisk",
 | 
				
			||||||
 | 
					    "de": "traditionelles Chinesisch",
 | 
				
			||||||
 | 
					    "en": "Traditional Chinese",
 | 
				
			||||||
 | 
					    "eo": "ĉina lingvo de tradicia ortografio",
 | 
				
			||||||
 | 
					    "es": "chino tradicional",
 | 
				
			||||||
 | 
					    "eu": "Txinera tradizional",
 | 
				
			||||||
 | 
					    "fi": "perinteinen kiina",
 | 
				
			||||||
 | 
					    "fr": "chinois traditionnel",
 | 
				
			||||||
 | 
					    "gl": "chinés tradicional",
 | 
				
			||||||
 | 
					    "he": "סינית מסורתית",
 | 
				
			||||||
 | 
					    "it": "cinese tradizionale",
 | 
				
			||||||
 | 
					    "ja": "繁体字中国語",
 | 
				
			||||||
 | 
					    "nb_NO": "tradisjonell kinesisk",
 | 
				
			||||||
 | 
					    "nl": "traditioneel Chinees",
 | 
				
			||||||
 | 
					    "pl": "język chiński tradycyjny",
 | 
				
			||||||
 | 
					    "pt": "chinês tradicional",
 | 
				
			||||||
 | 
					    "ru": "традиционный китайский",
 | 
				
			||||||
 | 
					    "sl": "tradicionalna kitajščina",
 | 
				
			||||||
 | 
					    "sv": "traditionell kinesiska",
 | 
				
			||||||
 | 
					    "zh_Hans": "繁体中文",
 | 
				
			||||||
 | 
					    "zh_Hant": "繁體中文",
 | 
				
			||||||
 | 
					    "_meta": {
 | 
				
			||||||
 | 
					      "dir": [
 | 
				
			||||||
 | 
					        "left-to-right"
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  "zu": {
 | 
					  "zu": {
 | 
				
			||||||
    "ca": "zulu",
 | 
					    "ca": "zulu",
 | 
				
			||||||
    "cs": "zuluština",
 | 
					    "cs": "zuluština",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,15 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  "contributors": [
 | 
					  "contributors": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "commits": 303,
 | 
					      "commits": 306,
 | 
				
			||||||
      "contributor": "kjon"
 | 
					      "contributor": "kjon"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "commits": 285,
 | 
					      "commits": 287,
 | 
				
			||||||
      "contributor": "Pieter Vander Vennet"
 | 
					      "contributor": "Pieter Vander Vennet"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "commits": 163,
 | 
					      "commits": 171,
 | 
				
			||||||
      "contributor": "paunofu"
 | 
					      "contributor": "paunofu"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue