diff --git a/.github/actions/setup-and-validate/action.yml b/.github/actions/setup-and-validate/action.yml index cc9ded1b7..8f19afd34 100644 --- a/.github/actions/setup-and-validate/action.yml +++ b/.github/actions/setup-and-validate/action.yml @@ -17,6 +17,22 @@ runs: - name: create generated dir run: mkdir ./assets/generated shell: bash + + - name: create dependencies + run: npm run generate:licenses; npm run generate:images; npm run generate:charging-stations; npm run generate:service-worker + shell: bash + + - name: sync translations + run: npm run generate:translations + shell: bash + + - name: generate layeroverview + run: npm run reset:layeroverview + shell: bash + + - name: run tests + run: npm run test + shell: bash - name: Prepare deploy run: npm run prepare-deploy diff --git a/.github/workflows/deploy_pietervdvn.yml b/.github/workflows/deploy_pietervdvn.yml index 36d4ebc26..9c566a61e 100644 --- a/.github/workflows/deploy_pietervdvn.yml +++ b/.github/workflows/deploy_pietervdvn.yml @@ -11,9 +11,41 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup and validate themes - uses: ./.github/actions/setup-and-validate - + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: "16" + cache: "npm" + cache-dependency-path: package-lock.json + + - name: install deps + run: npm ci + shell: bash + + - name: create generated dir + run: mkdir ./assets/generated + shell: bash + + - name: create dependencies + run: npm run generate:licenses; npm run generate:images; npm run generate:charging-stations; npm run generate:service-worker; npm run generate:editor-layer-index + shell: bash + + - name: sync translations + run: npm run generate:translations + shell: bash + + - name: generate layeroverview + run: npm run reset:layeroverview + shell: bash + + - name: run tests + run: npm run test + shell: bash + + - name: Prepare deploy + run: npm run prepare-deploy + shell: bash + - name: Clone deployment repo env: DEPLOY_KEY_PIETERVDVN: ${{ secrets.DEPLOY_KEY_PIETERVDVN }} diff --git a/.github/workflows/validate-pr.yml b/.github/workflows/validate-pr.yml index 4e64746f8..2e897022b 100644 --- a/.github/workflows/validate-pr.yml +++ b/.github/workflows/validate-pr.yml @@ -8,5 +8,83 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Setup and validate themes - uses: ./.github/actions/setup-and-validate + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: "16" + cache: "npm" + cache-dependency-path: package-lock.json + + - name: install deps + run: npm ci + shell: bash + + - name: create generated dir + run: mkdir ./assets/generated + shell: bash + + - name: create dependencies + run: npm run generate:licenses; npm run generate:images; npm run generate:charging-stations; npm run generate:service-worker; npm run generate:editor-layer-index + shell: bash + + - name: sync translations + run: npm run generate:translations + shell: bash + + - name: generate layeroverview + run: npm run reset:layeroverview + shell: bash + + - name: run tests + run: npm run test + shell: bash + + - name: Prepare deploy + run: npm run prepare-deploy + shell: bash + - name: Clone deployment repo + env: + DEPLOY_KEY_PIETERVDVN: ${{ secrets.DEPLOY_KEY_PIETERVDVN }} + run: | + echo "Cloning destination repo" + git config --global user.email "pietervdvn@posteo.net" + git config --global user.name "pietervdvn" + git clone --depth 1 --single-branch --branch master "https://x-access-token:$DEPLOY_KEY_PIETERVDVN@github.com/pietervdvn/pietervdvn.github.io.git" + echo "Destination repo is cloned" + + - name: Sync repo + env: + DEPLOY_KEY_PIETERVDVN: ${{ secrets.DEPLOY_KEY_PIETERVDVN }} + run: | + cd pietervdvn.github.io + git pull + + - name: get branch name + run: echo TARGET_BRANCH=${GITHUB_REF:11} >> $GITHUB_ENV + + - name: "Copying files" + run: | + echo "Deploying" + rm -rf pietervdvn.github.io/mc/${{ env.TARGET_BRANCH }}/* + mkdir -p pietervdvn.github.io/mc/${{ env.TARGET_BRANCH }}/ + cp -r dist/* pietervdvn.github.io/mc/${{ env.TARGET_BRANCH }}/ + cd pietervdvn.github.io/ + git add * + if git status | grep -q "Changes to be committed" + then + git commit -am "Deploying a new version of mapcomplete" + git push + else + echo "No changes to commit" + fi + env: + TARGET_BRANCH: ${{ env.TARGET_BRANCH }} + + - uses: mshick/add-pr-comment@v1 + name: Comment the PR with the review URL + if: ${{ success() && github.ref != 'refs/heads/develop' && github.ref != 'refs/heads/master' }} + with: + message: | + [🚀 Preview Branch](https://pietervdvn.github.io/mc/${{ env.TARGET_BRANCH }}) + repo-token: ${{ secrets.GITHUB_TOKEN }} + diff --git a/Customizations/AllKnownLayouts.ts b/Customizations/AllKnownLayouts.ts index 12c27223c..f01bfe24d 100644 --- a/Customizations/AllKnownLayouts.ts +++ b/Customizations/AllKnownLayouts.ts @@ -49,4 +49,14 @@ export class AllKnownLayoutsLazy { export class AllKnownLayouts { public static allKnownLayouts: AllKnownLayoutsLazy = new AllKnownLayoutsLazy() + + static AllPublicLayers() { + const layers = [].concat( + ...this.allKnownLayouts + .values() + .filter((layout) => !layout.hideFromOverview) + .map((layout) => layout.layers) + ) + return layers + } } diff --git a/Customizations/AllSharedLayers.ts b/Customizations/AllSharedLayers.ts index 7e4cf71a1..43c18e981 100644 --- a/Customizations/AllSharedLayers.ts +++ b/Customizations/AllSharedLayers.ts @@ -2,7 +2,6 @@ import LayerConfig from "../Models/ThemeConfig/LayerConfig" import { Utils } from "../Utils" import known_themes from "../assets/generated/known_layers.json" import { LayerConfigJson } from "../Models/ThemeConfig/Json/LayerConfigJson" -import { ALL } from "dns" import { AllKnownLayouts } from "./AllKnownLayouts" export class AllSharedLayers { public static sharedLayers: Map = AllSharedLayers.getSharedLayers() diff --git a/Docs/BuiltinIndex.md b/Docs/BuiltinIndex.md index 43fa12ab3..c4de09acb 100644 --- a/Docs/BuiltinIndex.md +++ b/Docs/BuiltinIndex.md @@ -42,11 +42,11 @@ + [climbing.max_difficulty](#climbingmax_difficulty) + [climbing.sportclimbing](#climbingsportclimbing) + [climbing.max_bolts](#climbingmax_bolts) - + [all_tags](#all_tags) + [opening_hours_by_appointment](#opening_hours_by_appointment) + [multilevels](#multilevels) + [induction-loop](#induction-loop) + [questions](#questions) + + [all_tags](#all_tags) + [export_as_gpx](#export_as_gpx) + [export_as_geojson](#export_as_geojson) + [minimap](#minimap) @@ -120,7 +120,6 @@ - food - ghost_bike - governments - - grass_in_parks - hackerspace - hotel - hydrant @@ -375,6 +374,7 @@ - bicycle_rental - cafe_pub + - climbing_gym - food - observation_tower - shops @@ -522,6 +522,7 @@ - cafe_pub + - climbing_gym - food - hotel - shops @@ -536,6 +537,7 @@ - cafe_pub + - climbing_gym - food - hotel - shops @@ -550,6 +552,7 @@ - cafe_pub + - climbing_gym - food - hotel - shops @@ -676,18 +679,6 @@ -### all_tags - - - - - - - cluster_style - - fixme - - - - ### opening_hours_by_appointment @@ -740,6 +731,17 @@ +### all_tags + + + + + + - fixme + + + + ### export_as_gpx diff --git a/Docs/BuiltinLayers.md b/Docs/BuiltinLayers.md index df5aa5b94..b5a646cb7 100644 --- a/Docs/BuiltinLayers.md +++ b/Docs/BuiltinLayers.md @@ -24,47 +24,76 @@ 1. [gps_track](#gps_track) - [Basic tags for this layer](#basic-tags-for-this-layer) - [Supported attributes](#supported-attributes) + + [just_created](#just_created) + [Privacy notice](#privacy-notice) + [export_as_gpx](#export_as_gpx) + [export_as_geojson](#export_as_geojson) + [upload_to_osm](#upload_to_osm) + [minimap](#minimap) + [delete](#delete) -1. [type_node](#type_node) + + [leftover-questions](#leftover-questions) + + [all-tags](#all-tags) +1. [range](#range) - [Basic tags for this layer](#basic-tags-for-this-layer) - [Supported attributes](#supported-attributes) -1. [note](#note) +1. [last_click](#last_click) - [Basic tags for this layer](#basic-tags-for-this-layer) - [Supported attributes](#supported-attributes) - + [conversation](#conversation) - + [add_image](#add_image) - + [comment](#comment) - + [nearby-images](#nearby-images) - + [report-contributor](#report-contributor) - + [report-note](#report-note) + + [just_created](#just_created) + + [add_new](#add_new) + + [add_note](#add_note) + + [leftover-questions](#leftover-questions) + + [all-tags](#all-tags) * [Filters](#filters) -1. [import_candidate](#import_candidate) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) - + [all_tags](#all_tags) -1. [direction](#direction) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) 1. [conflation](#conflation) - [Basic tags for this layer](#basic-tags-for-this-layer) - [Supported attributes](#supported-attributes) -1. [left_right_style](#left_right_style) - - [Basic tags for this layer](#basic-tags-for-this-layer) - - [Supported attributes](#supported-attributes) 1. [split_point](#split_point) - [Basic tags for this layer](#basic-tags-for-this-layer) - [Supported attributes](#supported-attributes) -1. [current_view](#current_view) +1. [split_road](#split_road) - [Basic tags for this layer](#basic-tags-for-this-layer) - [Supported attributes](#supported-attributes) +1. [current_view](#current_view) + * [Themes using this layer](#themes-using-this-layer) + - [Basic tags for this layer](#basic-tags-for-this-layer) + - [Supported attributes](#supported-attributes) + + [just_created](#just_created) + + [leftover-questions](#leftover-questions) + + [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) + - [Basic tags for this layer](#basic-tags-for-this-layer) + - [Supported attributes](#supported-attributes) + + [just_created](#just_created) + + [all_tags](#all_tags) + + [leftover-questions](#leftover-questions) +1. [usersettings](#usersettings) + - [Basic tags for this layer](#basic-tags-for-this-layer) + - [Supported attributes](#supported-attributes) + + [just_created](#just_created) + + [profile](#profile) + + [language_picker](#language_picker) + + [inbox](#inbox) + + [settings-link](#settings-link) + + [logout](#logout) + + [picture-license](#picture-license) + + [show_tags](#show_tags) + + [all-questions-at-once](#all-questions-at-once) + + [translations-title](#translations-title) + + [translation-mode](#translation-mode) + + [translation-help](#translation-help) + + [translation-completeness](#translation-completeness) + + [translation-links](#translation-links) + + [verified-mastodon](#verified-mastodon) + + [cscount-thanks](#cscount-thanks) + + [translation-thanks](#translation-thanks) + + [contributor-thanks](#contributor-thanks) + + [show_debug](#show_debug) + + [debug](#debug) + + [leftover-questions](#leftover-questions) 1. [Normal layers](#normal-layers) @@ -85,15 +114,15 @@ MapComplete has a few data layers available in the theme which have special prop - [gps_location_history](#gps_location_history) - [home_location](#home_location) - [gps_track](#gps_track) - - [type_node](#type_node) - - [note](#note) - - [import_candidate](#import_candidate) - - [direction](#direction) + - [range](#range) + - [last_click](#last_click) - [conflation](#conflation) - - [left_right_style](#left_right_style) - [split_point](#split_point) + - [split_road](#split_road) - [current_view](#current_view) - [matchpoint](#matchpoint) + - [import_candidate](#import_candidate) + - [usersettings](#usersettings) @@ -129,7 +158,7 @@ Elements must have the all of following tags to be shown on this layer: - - selected=yes + @@ -172,7 +201,7 @@ Elements must have the all of following tags to be shown on this layer: - - id=gps + @@ -217,7 +246,7 @@ Elements must have the all of following tags to be shown on this layer: - - user:location=yes + @@ -260,7 +289,7 @@ Elements must have the all of following tags to be shown on this layer: - - user:home=yes + @@ -303,7 +332,7 @@ Elements must have the all of following tags to be shown on this layer: - - id=location_track + @@ -313,6 +342,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### Privacy notice @@ -381,21 +440,44 @@ This tagrendering has no question and is thus read-only - type_node -=========== +### leftover-questions + + + +This tagrendering has no question and is thus read-only -This is a priviliged meta_layer which exports _every_ point in OSM. This only works if zoomed below the point that the full tile is loaded (and not loaded via Overpass). Note that this point will also contain a property `parent_ways` which contains all the ways this node is part of as a list. This is mainly used for extremely specialized themes, which do advanced conflations. Expert use only. +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + + range +======= + + + + + +Meta-layer, simply showing a bbox in red - - This layer is shown at zoomlevel **18** 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** + - 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. + - 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` @@ -410,7 +492,7 @@ Elements must have the all of following tags to be shown on this layer: - - id~^(node\/.*)$ + @@ -422,202 +504,14 @@ Elements must have the all of following tags to be shown on this layer: - note -====== + last_click +============ - +
{renderings}{first_preset}
' height="100px"> -This layer shows notes on OpenStreetMap. Having this layer in your theme will trigger the 'add new note' functionality in the 'addNewPoint'-popup (or if your theme has no presets, it'll enable adding notes) - - - - - - - - This layer is shown at zoomlevel **10** and higher - - This layer is loaded from an external source, namely `https://api.openstreetmap.org/api/0.6/notes.json?limit=10000&closed=7&bbox={x_min},{y_min},{x_max},{y_max}` - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - date_created~.+ - - - - - Supported attributes ----------------------- - - - - - -### conversation - - - -This tagrendering has no question and is thus read-only - - - - - -### add_image - - - -This tagrendering has no question and is thus read-only - - - - - -### comment - - - -This tagrendering has no question and is thus read-only - - - - - -### nearby-images - - - -This tagrendering has no question and is thus read-only - - - - - -### report-contributor - - - -This tagrendering has no question and is thus read-only - - - -This tagrendering is only visible in the popup if the following condition is met: `_opened_by_anonymous_user=false` - - - -### report-note - - - -This tagrendering has no question and is thus read-only - - - - - -#### Filters - - - - - -id | question | osmTags | fields ----- | ---------- | --------- | -------- -search.0 | Should mention {search} in the first comment | | search (string) - - - - -id | question | osmTags | fields ----- | ---------- | --------- | -------- -not.0 | Should not mention {search} in the first comment | | search (string) - - - - -id | question | osmTags | fields ----- | ---------- | --------- | -------- -opened_by.0 | Opened by contributor {search} | | search (string) - - - - -id | question | osmTags | fields ----- | ---------- | --------- | -------- -not_opened_by.0 | Not opened by contributor {search} | | search (string) - - - - -id | question | osmTags | fields ----- | ---------- | --------- | -------- -edited_by.0 | Last edited by contributor {search} | | search (string) - - - - -id | question | osmTags | fields ----- | ---------- | --------- | -------- -not_edited_by.0 | Opened after {search} | | search (string) - - - - -id | question | osmTags | fields ----- | ---------- | --------- | -------- -opened_before.0 | Created before {search} | | search (date) - - - - -id | question | osmTags | fields ----- | ---------- | --------- | -------- -opened_after.0 | Created after {search} | | search (date) - - - - -id | question | osmTags ----- | ---------- | --------- -anonymous.0 | Only show notes opened by an anonymous contributor | _opened_by_anonymous_user=true - - - - -id | question | osmTags ----- | ---------- | --------- -is_open.0 | Only show open notes | - - - - -id | question | osmTags ----- | ---------- | --------- -no_imports.0 | All Notes (default) | -no_imports.1 | Hide import notes | -no_imports.2 | Show only import Notes | _is_import_note~.+ - - - - - import_candidate -================== - - - - - -Layer used in the importHelper +This layer defines how to render the 'last click'-location. By default, it will show a marker with the possibility to add a new point (if there are some presets) and/or to add a new note (if the 'note' layer attribute is set). If none are possible, this layer won't show up @@ -625,6 +519,7 @@ Layer used in the importHelper - This layer is shown at zoomlevel **0** and higher + - **This layer is included automatically in every theme. This layer might contain no points** - Not visible in the layer selection by default. If you want to make this layer toggable, override `name` @@ -649,9 +544,63 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete -### all_tags + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### add_new + + + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `has_presets=yes` + + + +### add_note + + + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `has_note_layer=yes` + + + +### leftover-questions @@ -661,43 +610,25 @@ This tagrendering has no question and is thus read-only - direction -=========== +### all-tags - - -This layer visualizes directions +This tagrendering has no question and is thus read-only - - - This layer is shown at zoomlevel **16** and higher - - 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. +#### Filters - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - camera:direction~.+|direction~.+ - - - - - Supported attributes ----------------------- +id | question | osmTags +---- | ---------- | --------- +action.0 | only_if_action_is_possible | has_note_layer=yes\|has_presets=yes @@ -731,51 +662,10 @@ Elements must have the all of following tags to be shown on this layer: - - move=yes|newpoint=yes - Supported attributes ----------------------- - - - - - - left_right_style -================== - - - - - -Special meta-style which will show one single line, either on the left or on the right depending on the id. This is used in the small popups with left_right roads. Cannot be included in a theme - - - - - - - - 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: - - - - - id=left|id=right - - - Supported attributes ---------------------- @@ -813,7 +703,48 @@ Elements must have the all of following tags to be shown on this layer: - - _split_point=yes + + + + + + Supported attributes +---------------------- + + + + + + split_road +============ + + + + + +Layer rendering the way to split in the 'splitRoadWizard'. This one is used instead of the variable rendering by the themes themselves, as they might not always be very visible + + + + + + + - This layer is shown at zoomlevel **1** 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: + + + + @@ -832,7 +763,7 @@ Elements must have the all of following tags to be shown on this layer: -A meta-layer which contains one single feature, namely the BBOX of the current map view. This can be used to trigger special actions. If a popup is defined for this layer, this popup will be accessible via an extra button on screen. +A meta-layer which contains one single feature, namely the bounding box of the current map view. This can be used to trigger special actions. If a popup is defined for this layer, this popup will be accessible via an extra button on screen. The icon on the button is the default icon of the layer, but can be customized by detecting 'button=yes'. @@ -847,6 +778,20 @@ The icon on the button is the default icon of the layer, but can be customized b +#### Themes using this layer + + + + + + - [grb](https://mapcomplete.osm.be/grb) + - [mapcomplete-changes](https://mapcomplete.osm.be/mapcomplete-changes) + - [onwheels](https://mapcomplete.osm.be/onwheels) + - [personal](https://mapcomplete.osm.be/personal) + + + + Basic tags for this layer --------------------------- @@ -856,7 +801,7 @@ Elements must have the all of following tags to be shown on this layer: - - current_view=yes + @@ -866,6 +811,56 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + matchpoint @@ -909,6 +904,459 @@ Elements must have the all of following tags to be shown on this layer: + import_candidate +================== + + + + + +Layer used as template in the importHelper + + + + + + + - 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 +---------------------- + + + +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### all_tags + + + +This tagrendering has no question and is thus read-only + + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + + usersettings +============== + + + + + +A special layer which is not meant to be shown on a map, but which is used to set user settings + + + + + + + - 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 +---------------------- + + + +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | +[](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) +[](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) +[](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) +[](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) +[](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) +[](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) +[](https://taginfo.openstreetmap.org/keys/mapcomplete-show_debug#values) [mapcomplete-show_debug](https://wiki.openstreetmap.org/wiki/Key:mapcomplete-show_debug) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_debug%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:mapcomplete-show_debug%3Dno) + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### profile + + + +This tagrendering has no question and is thus read-only + + + + + +### language_picker + + + +This tagrendering has no question and is thus read-only + + + + + +### inbox + + + +This tagrendering has no question and is thus read-only + + + + + + - *{link(Open your inbox,&LBRACE_backend&RBRACE/messages/inbox,)}* corresponds with `_unreadMessages=0` + - *{link(You have &LBRACE_unreadMessages&RBRACE
Open your inbox,&LBRACE_backend&RBRACE/messages/inbox,)}* corresponds with `_unreadMessages>0` + + + + +### settings-link + + + +This tagrendering has no question and is thus read-only + + + + + +### logout + + + +This tagrendering has no question and is thus read-only + + + + + +### picture-license + + + +This question is not meant to be placed on an OpenStreetMap-element; however it is used in the user information panel to ask which license the user wants + +The question is *Under what license do you want to publish your pictures?* + + + + + + - *Pictures you take will be licensed with CC0 and added to the public domain. This means that everyone can use your pictures for any purpose. This is the default choice.* corresponds with `` + - This option cannot be chosen as answer + - *Pictures you take will be licensed with CC0 and added to the public domain. This means that everyone can use your pictures for any purpose.* corresponds with `mapcomplete-pictures-license=CC0` + - *Pictures you take will be licensed with CC-BY 4.0 which requires everyone using your picture that they have to attribute you* corresponds with `mapcomplete-pictures-license=CC-BY 4.0` + - *Pictures you take will be licensed with CC-BY-SA 4.0 which means that everyone using your picture must attribute you and that derivatives of your picture must be reshared with the same license.* corresponds with `mapcomplete-pictures-license=CC-BY-SA 4.0` + + + + +### show_tags + + + +The question is *Show the raw OpenStreetMap-tags?* + + + + + + - *Never show the tags.* corresponds with `mapcomplete-show_tags=no` + - *Show the tags that will be applied once I have made {__userjourney_tagsVisibleAt} changesets* corresponds with `` + - *Show the tags that will be applied when making a change* corresponds with `mapcomplete-show_tags=yes` + - *Show the tags that will be applied when making a change and show the tags table on every feature* corresponds with `mapcomplete-show_tags=full` + + + + +### all-questions-at-once + + + +The question is *Should questions for unknown data fields appear one-by-one or together?* + + + + + + - *Show all questions in the infobox together* corresponds with `mapcomplete-show-all-questions=true` + - *Show questions one-by-one* corresponds with `mapcomplete-show-all-questions=false` + + + + +### translations-title + + + +This tagrendering has no question and is thus read-only + + + + + +### translation-mode + + + +The question is *Do you want to help translating MapComplete?* + + + + + + - *Don't show a button to quickly change translations* corresponds with `mapcomplete-translation-mode=false` + - *Show a button to quickly open translations when using MapComplete on a big screen* corresponds with `mapcomplete-translation-mode=true` + - *Always show the translation buttons, including on mobile* corresponds with `mapcomplete-translation-mode=mobile` + + + + +### translation-help + + + +This tagrendering has no question and is thus read-only + + + + + + - *Click the 'translate'-icon next to a string to enter or update a piece of text. You need a Weblate-account for this. Create one with your OSM-username to automatically unlock translation mode.* corresponds with `mapcomplete-translation-mode=yes|mapcomplete-translation-mode=true|mapcomplete-translation-mode=mobile` + + + + +### translation-completeness + + + +This tagrendering has no question and is thus read-only + + + + + + - *Completely translated* corresponds with `_translation_percentage=100` + + +This tagrendering is only visible in the popup if the following condition is met: `mapcomplete-translation-mode=yes|mapcomplete-translation-mode=true|mapcomplete-translation-mode=mobile` + + + +### translation-links + + + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_translation_links~.+&mapcomplete-translation-mode=true|mapcomplete-translation-mode=mobile` + + + +### verified-mastodon + + + +This tagrendering has no question and is thus read-only + + + + + + - *A link to your Mastodon-profile has been been found: {_mastodon_link}* corresponds with `_mastodon_link~.+` + - *We found a link to what looks to be a mastodon account, but it is unverified. Edit your profile description and place the following there: <a href="{_mastodon_candidate}" rel="me">Mastodon</a>* corresponds with `_mastodon_candidate~.+` + + + + +### cscount-thanks + + + +This tagrendering has no question and is thus read-only + + + + + + - *You have made changes on {_csCount} different occasions! That is awesome!* corresponds with `_csCount>0` + + + + +### translation-thanks + + + +This tagrendering has no question and is thus read-only + + + + + + - *You have contributed to translating MapComplete! That's awesome!* corresponds with `_translation_contributions>0` + + + + +### contributor-thanks + + + +This tagrendering has no question and is thus read-only + + + + + + - *You have contributed code to MapComplete with {_code_contributions} commits! That's awesome!* corresponds with `_code_contributions>0` + - This option cannot be chosen as answer + + + + +### show_debug + + + +The question is *Show user settings debug info?* + + + + + + - *Show debug info* corresponds with `mapcomplete-show_debug=yes` + - *Don't show debug info* corresponds with `mapcomplete-show_debug=no` + - *Don't show debug info* corresponds with `` + - This option cannot be chosen as answer + + + + +### debug + + + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `mapcomplete-show_debug=yes` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + Normal layers =============== @@ -948,7 +1396,6 @@ The following layers are included in MapComplete: - [climbing_opportunity](./Layers/climbing_opportunity.md) - [climbing_route](./Layers/climbing_route.md) - [clock](./Layers/clock.md) - - [cluster_style](./Layers/cluster_style.md) - [conflation](./Layers/conflation.md) - [crab_address](./Layers/crab_address.md) - [crossings](./Layers/crossings.md) @@ -975,7 +1422,6 @@ The following layers are included in MapComplete: - [gps_location](./Layers/gps_location.md) - [gps_location_history](./Layers/gps_location_history.md) - [gps_track](./Layers/gps_track.md) - - [grass_in_parks](./Layers/grass_in_parks.md) - [hackerspace](./Layers/hackerspace.md) - [home_location](./Layers/home_location.md) - [hospital](./Layers/hospital.md) @@ -988,7 +1434,7 @@ The following layers are included in MapComplete: - [information_board](./Layers/information_board.md) - [kerbs](./Layers/kerbs.md) - [kindergarten_childcare](./Layers/kindergarten_childcare.md) - - [left_right_style](./Layers/left_right_style.md) + - [last_click](./Layers/last_click.md) - [map](./Layers/map.md) - [maproulette](./Layers/maproulette.md) - [maproulette_challenge](./Layers/maproulette_challenge.md) @@ -1014,6 +1460,7 @@ The following layers are included in MapComplete: - [public_bookcase](./Layers/public_bookcase.md) - [railway_platforms](./Layers/railway_platforms.md) - [rainbow_crossings](./Layers/rainbow_crossings.md) + - [range](./Layers/range.md) - [reception_desk](./Layers/reception_desk.md) - [recycling](./Layers/recycling.md) - [school](./Layers/school.md) @@ -1024,6 +1471,7 @@ The following layers are included in MapComplete: - [speed_camera](./Layers/speed_camera.md) - [speed_display](./Layers/speed_display.md) - [split_point](./Layers/split_point.md) + - [split_road](./Layers/split_road.md) - [sport_pitch](./Layers/sport_pitch.md) - [sports_centre](./Layers/sports_centre.md) - [stairs](./Layers/stairs.md) @@ -1038,7 +1486,6 @@ The following layers are included in MapComplete: - [transit_routes](./Layers/transit_routes.md) - [transit_stops](./Layers/transit_stops.md) - [tree_node](./Layers/tree_node.md) - - [type_node](./Layers/type_node.md) - [usersettings](./Layers/usersettings.md) - [veterinary](./Layers/veterinary.md) - [viewpoint](./Layers/viewpoint.md) diff --git a/Docs/BuiltinQuestions.md b/Docs/BuiltinQuestions.md index 8e69de421..aa7daa342 100644 --- a/Docs/BuiltinQuestions.md +++ b/Docs/BuiltinQuestions.md @@ -34,8 +34,8 @@ The following items can be easily reused in your layers + [payment-options-advanced](#payment-options-advanced) + [denominations-coins](#denominations-coins) + [denominations-notes](#denominations-notes) - + [last_edit](#last_edit) + [all_tags](#all_tags) + + [just_created](#just_created) + [multilevels](#multilevels) + [level](#level) + [smoking](#smoking) @@ -53,6 +53,8 @@ The following items can be easily reused in your layers +{questions()} + *Read-only tagrendering* @@ -61,7 +63,7 @@ The following items can be easily reused in your layers -{image_carousel()}{image_upload()}{nearby_images(expandable)} +{image_carousel()}{image_upload()} *Read-only tagrendering* @@ -382,16 +384,6 @@ what notes can you use to pay here? -### last_edit - - - - - -*Read-only tagrendering* - - - ### all_tags @@ -402,6 +394,19 @@ what notes can you use to pay here? +### just_created + + + +*Read-only tagrendering* + + + + - You just created this element! Thanks for sharing this info with the world and helping people worldwide. + + + + ### multilevels diff --git a/Docs/CalculatedTags.md b/Docs/CalculatedTags.md index 697cda570..65cc1d4b1 100644 --- a/Docs/CalculatedTags.md +++ b/Docs/CalculatedTags.md @@ -11,26 +11,27 @@ - [Metatags calculated by MapComplete](#metatags-calculated-by-mapcomplete) + [_lat, _lon](#_lat,-_lon) + [_layer](#_layer) - + [_surface, _surface:ha](#_surface,-_surfaceha) + + [_surface](#_surface) + + [_surface:ha](#_surfaceha) + [_length, _length:km](#_length,-_lengthkm) + [Theme-defined keys](#theme-defined-keys) + [_country](#_country) + [_isOpen](#_isopen) + [_direction:numerical, _direction:leftright](#_directionnumerical,-_direction:leftright) + [_direction:centerpoint](#_directioncenterpoint) - + [_now:date, _now:datetime, _loaded:date, _loaded:_datetime](#_nowdate,-_now:datetime,-_loaded:date,-_loaded:_datetime) + + [_now:date, _now:datetime](#_nowdate,-_now:datetime) + [_last_edit:contributor, _last_edit:contributor:uid, _last_edit:changeset, _last_edit:timestamp, _version_number, _backend](#_last_editcontributor,-_last_edit:contributor:uid,-_last_edit:changeset,-_last_edit:timestamp,-_version_number,-_backend) + [sidewalk:left, sidewalk:right, generic_key:left:property, generic_key:right:property](#sidewalkleft,-sidewalk:right,-generic_key:left:property,-generic_key:right:property) + [_geometry:type](#_geometrytype) + [_level](#_level) + [_referencing_ways](#_referencing_ways) + + [_last_edit:passed_time](#_last_editpassed_time) + [distanceTo](#distanceto) + [overlapWith](#overlapwith) + [enclosingFeatures](#enclosingfeatures) + [intersectionsWith](#intersectionswith) + [closest](#closest) + [closestn](#closestn) - + [memberships](#memberships) + [get](#get) @@ -72,11 +73,21 @@ The layer-id to which this feature belongs. Note that this might be return any a -### _surface, _surface:ha +### _surface -The surface area of the feature, in square meters and in hectare. Not set on points and ways +The surface area of the feature in square meters. Not set on points and ways + +This is a lazy metatag and is only calculated when needed + + + +### _surface:ha + + + +The surface area of the feature in hectare. Not set on points and ways This is a lazy metatag and is only calculated when needed @@ -142,7 +153,7 @@ This is a lazy metatag and is only calculated when needed -### _now:date, _now:datetime, _loaded:date, _loaded:_datetime +### _now:date, _now:datetime @@ -156,7 +167,7 @@ Adds the time that the data got loaded - pretty much the time of downloading fro -Information about the last edit of this object. +Information about the last edit of this object. This object will actually _rewrite_ some tags for features coming from overpass @@ -196,7 +207,17 @@ Extract the 'level'-tag into a normalized, ';'-separated value -_referencing_ways contains - for a node - which ways use this this node as point in their geometry. If the preset has 'snapToLayer' defined, the icon will be calculated based on the preset tags with `_referencing_ways=["way/-1"]` added. +_referencing_ways contains - for a node - which ways use this this node as point in their geometry. + +This is a lazy metatag and is only calculated when needed + + + +### _last_edit:passed_time + + + +Gives the number of seconds since the last edit. Note that this will _not_ update, but rather be the number of seconds elapsed at the moment this tag is read first This is a lazy metatag and is only calculated when needed @@ -232,7 +253,7 @@ To enable this feature, add a field `calculatedTags` in the layer object, e.g.: "name=feat.properties.name ?? feat.properties.ref ?? feat.properties.operator", - "_distanceCloserThen3Km=feat.distanceTo( some_lon, some_lat) < 3 ? 'yes' : 'no'" + "_distanceCloserThen3Km=distanceTo(feat)( some_lon, some_lat) < 3 ? 'yes' : 'no'" ] @@ -248,7 +269,7 @@ The above code will be executed for every feature in the layer. The feature is a - `lat` and `lon` contain the latitude and longitude -Some advanced functions are available on **feat** as well: +Some advanced functions are available as well. Due to technical reasons, they should be used as `funcname(feat)(arguments)`. - [distanceTo](#distanceTo) - [overlapWith](#overlapWith) @@ -256,7 +277,6 @@ Some advanced functions are available on **feat** as well: - [intersectionsWith](#intersectionsWith) - [closest](#closest) - [closestn](#closestn) - - [memberships](#memberships) - [get](#get) @@ -276,7 +296,7 @@ If the current feature is a point, all features that this point is embeded in ar The returned value is `{ feat: GeoJSONFeature, overlap: number}[]` where `overlap` is the overlapping surface are (in m²) for areas, the overlapping length (in meter) if the current feature is a line or `undefined` if the current feature is a point. The resulting list is sorted in descending order by overlap. The feature with the most overlap will thus be the first in the list. -For example to get all objects which overlap or embed from a layer, use `_contained_climbing_routes_properties=feat.overlapWith('climbing_route')` +For example to get all objects which overlap or embed from a layer, use `_contained_climbing_routes_properties=overlapWith(feat)('climbing_route')` Also see [enclosingFeatures](#enclosingFeatures) which can be used to get all objects which fully contain this feature @@ -324,15 +344,6 @@ If a 'unique tag key' is given, the tag with this key will only appear once (e.g 3. maxDistanceInMeters (optional) -### memberships - - Gives a list of `{role: string, relation: Relation}`-objects, containing all the relations that this feature is part of. - -For example: `_part_of_walking_routes=feat.memberships().map(r => r.relation.tags.name).join(';')` - - - - ### get Gets the property of the feature, parses it (as JSON) and returns it. Might return 'undefined' if not defined, null, ... diff --git a/Docs/Hotkeys.md b/Docs/Hotkeys.md index 1ac7bbd61..89c5250a3 100644 --- a/Docs/Hotkeys.md +++ b/Docs/Hotkeys.md @@ -17,14 +17,12 @@ MapComplete supports the following keys: Key combination | Action ----------------- | -------- -`B` | Opens the Background, layers and filters panel -`Escape` | Close the sidebar -`L` | Pan the map to the current location or zoom the map to the current location. Requests geopermission -`M` | Select a background layer of category map -`O` | Select a background layer of category osmbasedmap -`P` | Select a background layer of category photo -`ctrl+F` | Select the search bar to search locations -`shift+O` | Sets the background layer to OpenStreetMap-carto +B | Opens the Background, layers and filters panel +Escape | Close the sidebar +M | Set the background to a map from external sources. Toggles between the two best, available layers +O | Set the background layer to on OpenStreetMap-based map (or disable the background raster layer) +P | Set the background to aerial or satellite imagery. Toggles between the two best, available layers +shift+O | Set the background layer to OpenStreetMap-carto This document is autogenerated from diff --git a/Docs/Layers/address.md b/Docs/Layers/address.md index 59ea54e7b..e6d10eaf4 100644 --- a/Docs/Layers/address.md +++ b/Docs/Layers/address.md @@ -18,21 +18,7 @@ Addresses - This layer will automatically load [named_streets](./named_streets.md) into the layout as it depends on it: a calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _closest_3_street_names) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - addr:housenumber~.+|addr:street~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22addr%3Ahousenumber%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22addr%3Astreet%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -49,6 +35,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/addr:housenumber#values) [addr:housenumber](https://wiki.openstreetmap.org/wiki/Key:addr:housenumber) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/addr:street#values) [addr:street](https://wiki.openstreetmap.org/wiki/Key:addr:street) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:addr:street%3D) [](https://wiki.openstreetmap.org/wiki/Tag:addr:street%3D) [](https://wiki.openstreetmap.org/wiki/Tag:addr:street%3D) [](https://taginfo.openstreetmap.org/keys/fixme#values) [fixme](https://wiki.openstreetmap.org/wiki/Key:fixme) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:fixme%3D) @@ -56,6 +43,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### housenumber @@ -111,6 +117,52 @@ This is rendered with `Fixme description{fixme}` - *No fixme - write something here to explain complicated cases* corresponds with `` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/address/address.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/address/address.json) diff --git a/Docs/Layers/advertising.md b/Docs/Layers/advertising.md index a1a527525..9e716e0df 100644 --- a/Docs/Layers/advertising.md +++ b/Docs/Layers/advertising.md @@ -34,21 +34,7 @@ We will complete data from advertising features with reference, operator and lit - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - advertising~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22advertising%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -65,6 +51,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/advertising#values) [advertising](https://wiki.openstreetmap.org/wiki/Key:advertising) | [string](../SpecialInputElements.md#string) | [billboard](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dbillboard) [board](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dboard) [column](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dcolumn) [flag](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dflag) [poster_box](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dposter_box) [screen](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dscreen) [sculpture](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dsculpture) [sign](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dsign) [tarp](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dtarp) [totem](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dtotem) [wall_painting](https://wiki.openstreetmap.org/wiki/Tag:advertising%3Dwall_painting) [](https://taginfo.openstreetmap.org/keys/animated#values) [animated](https://wiki.openstreetmap.org/wiki/Key:animated) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:animated%3Dno) [digital_display](https://wiki.openstreetmap.org/wiki/Tag:animated%3Ddigital_display) [trivision_blades](https://wiki.openstreetmap.org/wiki/Tag:animated%3Dtrivision_blades) [winding_posters](https://wiki.openstreetmap.org/wiki/Tag:animated%3Dwinding_posters) [revolving](https://wiki.openstreetmap.org/wiki/Tag:animated%3Drevolving) [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | @@ -74,6 +61,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -229,6 +235,72 @@ This rendering asks information about the property [ref](https://wiki.openstree This is rendered with `Reference number is {ref}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/advertising/advertising.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/advertising/advertising.json) diff --git a/Docs/Layers/all_streets.md b/Docs/Layers/all_streets.md index 6b872c4e2..a9815681d 100644 --- a/Docs/Layers/all_streets.md +++ b/Docs/Layers/all_streets.md @@ -29,21 +29,7 @@ Layer to mark any street as cyclestreet - [street_lighting](https://mapcomplete.osm.be/street_lighting) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=residential|highway=tertiary|highway=unclassified - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22residential%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22tertiary%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22unclassified%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,18 +48,7 @@ attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ [](https://taginfo.openstreetmap.org/keys/traffic_sign#values) [traffic_sign](https://wiki.openstreetmap.org/wiki/Key:traffic_sign) | Multiple choice | [DE:244.1,1020-30](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1020-30) [DE:244.1,1022-12,1024-10](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1022-12,1024-10) [DE:244.1,1022-12](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1022-12) [DE:244.1,1024-10](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1024-10) [DE:244.1](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1) [](https://taginfo.openstreetmap.org/keys/cyclestreet:start_date#values) [cyclestreet:start_date](https://wiki.openstreetmap.org/wiki/Key:cyclestreet:start_date) | [date](../SpecialInputElements.md#date) | - - - - -### images - - - -This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` - -This tagrendering has no question and is thus read-only - +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | @@ -137,11 +112,40 @@ This tagrendering is only visible in the popup if the following condition is met -### questions +### just_created -Show the images block at this location +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### images + + + +This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` + +This tagrendering has no question and is thus read-only + + + + + +### leftover-questions + + This tagrendering has no question and is thus read-only @@ -157,6 +161,40 @@ Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + +### split-button + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/themes/cyclestreets/cyclestreets.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/cyclestreets/cyclestreets.json) diff --git a/Docs/Layers/ambulancestation.md b/Docs/Layers/ambulancestation.md index 7391a9d9f..13cfe108e 100644 --- a/Docs/Layers/ambulancestation.md +++ b/Docs/Layers/ambulancestation.md @@ -29,21 +29,7 @@ An ambulance station is an area for storage of ambulance vehicles, medical equip - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - emergency=ambulance_station - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22emergency%22%3D%22ambulance_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/addr:street#values) [addr:street](https://wiki.openstreetmap.org/wiki/Key:addr:street) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/addr:place#values) [addr:place](https://wiki.openstreetmap.org/wiki/Key:addr:place) | [string](../SpecialInputElements.md#string) | @@ -69,6 +56,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### ambulance-name @@ -160,6 +166,52 @@ This block shows the known images which are linked with the `image`-keys, but al This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/ambulancestation/ambulancestation.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/ambulancestation/ambulancestation.json) diff --git a/Docs/Layers/artwork.md b/Docs/Layers/artwork.md index 58588320c..c9ac2ac94 100644 --- a/Docs/Layers/artwork.md +++ b/Docs/Layers/artwork.md @@ -30,21 +30,7 @@ An open map of statues, busts, graffitis and other artwork all over the world - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - tourism=artwork - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22tourism%22%3D%22artwork%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/artist:wikidata#values) [artist:wikidata](https://wiki.openstreetmap.org/wiki/Key:artist:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | [](https://taginfo.openstreetmap.org/keys/artist_name#values) [artist_name](https://wiki.openstreetmap.org/wiki/Key:artist_name) | [string](../SpecialInputElements.md#string) | @@ -68,18 +55,29 @@ attribute | type | values which are supported by this layer [](https://taginfo.openstreetmap.org/keys/wikidata#values) [wikidata](https://wiki.openstreetmap.org/wiki/Key:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | [](https://taginfo.openstreetmap.org/keys/subject:wikidata#values) [subject:wikidata](https://wiki.openstreetmap.org/wiki/Key:subject:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | [](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [bench](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbench) [](https://wiki.openstreetmap.org/wiki/Tag:amenity%3D) -[](https://taginfo.openstreetmap.org/keys/backrest#values) [backrest](https://wiki.openstreetmap.org/wiki/Key:backrest) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes) [yes](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dno) -[](https://taginfo.openstreetmap.org/keys/seats#values) [seats](https://wiki.openstreetmap.org/wiki/Key:seats) | [nat](../SpecialInputElements.md#nat) | -[](https://taginfo.openstreetmap.org/keys/material#values) [material](https://wiki.openstreetmap.org/wiki/Key:material) | [string](../SpecialInputElements.md#string) | [wood](https://wiki.openstreetmap.org/wiki/Tag:material%3Dwood) [metal](https://wiki.openstreetmap.org/wiki/Tag:material%3Dmetal) [stone](https://wiki.openstreetmap.org/wiki/Tag:material%3Dstone) [concrete](https://wiki.openstreetmap.org/wiki/Tag:material%3Dconcrete) [plastic](https://wiki.openstreetmap.org/wiki/Tag:material%3Dplastic) [steel](https://wiki.openstreetmap.org/wiki/Tag:material%3Dsteel) -[](https://taginfo.openstreetmap.org/keys/direction#values) [direction](https://wiki.openstreetmap.org/wiki/Key:direction) | [direction](../SpecialInputElements.md#direction) | -[](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) -[](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) -[](https://taginfo.openstreetmap.org/keys/inscription#values) [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [text](../SpecialInputElements.md#text) | -[](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) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -233,192 +231,70 @@ The question is *Does this artwork serve as a bench?* -### bench-backrest +### leftover-questions -The question is *Does this bench have a backrest?* +This tagrendering has no question and is thus read-only - - *This bench is two-sided and shares the backrest* corresponds with `backrest=yes&two_sided=yes` - - *Does have a backrest* corresponds with `backrest=yes` - - *Does not have a backrest* corresponds with `backrest=no` +### minimap -This tagrendering is only visible in the popup if the following condition is met: `amenity=bench` -This tagrendering has labels `bench-questions` +Shows a small map with the feature. Added by default to every popup +This tagrendering has no question and is thus read-only -### bench-seats -The question is *How many seats does this bench have?* +### move-button -This rendering asks information about the property [seats](https://wiki.openstreetmap.org/wiki/Key:seats) -This is rendered with `{seats} seats` +This tagrendering has no question and is thus read-only - - *This bench does not have separated seats* corresponds with `seats:separated=no` +### delete-button -This tagrendering is only visible in the popup if the following condition is met: `amenity=bench` -This tagrendering has labels `bench-questions` +This tagrendering has no question and is thus read-only -### bench-material -The question is *What is the bench (seating) made from?* +### last_edit -This rendering asks information about the property [material](https://wiki.openstreetmap.org/wiki/Key:material) -This is rendered with `Material: {material}` +Gives some metainfo about the last edit and who did edit it - rendering only +This tagrendering has no question and is thus read-only - - *The seating is made from wood* corresponds with `material=wood` - - *The seating is made from metal* corresponds with `material=metal` - - *The seating is made from stone* corresponds with `material=stone` - - *The seating is made from concrete* corresponds with `material=concrete` - - *The seating is made from plastic* corresponds with `material=plastic` - - *The seating is made from steel* corresponds with `material=steel` +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` -This tagrendering is only visible in the popup if the following condition is met: `amenity=bench` -This tagrendering has labels `bench-questions` +### all-tags -### bench-direction +This tagrendering has no question and is thus read-only -The question is *In which direction are you looking when sitting on the bench?* - -This rendering asks information about the property [direction](https://wiki.openstreetmap.org/wiki/Key:direction) - -This is rendered with `When sitting on the bench, one looks towards {direction}°.` - - - -This tagrendering is only visible in the popup if the following condition is met: `amenity=bench` - -This tagrendering has labels `bench-questions` - - - -### bench-colour - - - -The question is *Which colour does this bench have?* - -This rendering asks information about the property [colour](https://wiki.openstreetmap.org/wiki/Key:colour) - -This is rendered with `Colour: {colour}` - - - - - - - *Colour: brown* corresponds with `colour=brown` - - *Colour: green* corresponds with `colour=green` - - *Colour: gray* corresponds with `colour=gray` - - *Colour: white* corresponds with `colour=white` - - *Colour: red* corresponds with `colour=red` - - *Colour: black* corresponds with `colour=black` - - *Colour: blue* corresponds with `colour=blue` - - *Colour: yellow* corresponds with `colour=yellow` - - -This tagrendering is only visible in the popup if the following condition is met: `amenity=bench` - -This tagrendering has labels `bench-questions` - - - -### bench-survey:date - - - -The question is *When was this bench last surveyed?* - -This rendering asks information about the property [survey:date](https://wiki.openstreetmap.org/wiki/Key:survey:date) - -This is rendered with `This bench was last surveyed on {survey:date}` - - - - - - - *Surveyed today!* corresponds with `survey:date=` - - -This tagrendering is only visible in the popup if the following condition is met: `amenity=bench` - -This tagrendering has labels `bench-questions` - - - -### bench-inscription - - - -The question is *Does this bench have an inscription?* - -This rendering asks information about the property [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) - -This is rendered with `This bench does have the following inscription:

{inscription}

` - - - - - - - *This bench does not have an inscription* corresponds with `not:inscription=yes` - - *This bench does (probably) not have an inscription* corresponds with `` - - This option cannot be chosen as answer - - -This tagrendering is only visible in the popup if the following condition is met: `amenity=bench` - -This tagrendering has labels `bench-questions` - - - -### bench-memorial - - - -The question is *Does this bench act as memorial for someone or something?* - - - - - - - *This bench is a memorial for someone or something* corresponds with `historic=memorial` - - *This bench is a not a memorial for someone or something* corresponds with `not:historic=memorial` - - -This tagrendering is only visible in the popup if the following condition is met: `amenity=bench` - -This tagrendering has labels `bench-questions` - #### Filters diff --git a/Docs/Layers/atm.md b/Docs/Layers/atm.md index c49dac270..67d3780c0 100644 --- a/Docs/Layers/atm.md +++ b/Docs/Layers/atm.md @@ -29,21 +29,7 @@ ATMs to withdraw money - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=atm - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22atm%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/brand#values) [brand](https://wiki.openstreetmap.org/wiki/Key:brand) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | @@ -71,6 +58,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -222,6 +228,72 @@ This tagrendering is only visible in the popup if the following condition is met +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/bank.md b/Docs/Layers/bank.md index b79deb213..38488ca40 100644 --- a/Docs/Layers/bank.md +++ b/Docs/Layers/bank.md @@ -29,21 +29,7 @@ A financial institution to deposit money - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=bank - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bank%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,11 +46,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/atm#values) [atm](https://wiki.openstreetmap.org/wiki/Key:atm) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:atm%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:atm%3Dno) [separate](https://wiki.openstreetmap.org/wiki/Tag:atm%3Dseparate) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### has_atm @@ -82,6 +88,52 @@ The question is *Does this bank have an ATM?* +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/banks_with_atm.md b/Docs/Layers/banks_with_atm.md index 8c0d9bfd6..6c449b905 100644 --- a/Docs/Layers/banks_with_atm.md +++ b/Docs/Layers/banks_with_atm.md @@ -14,7 +14,7 @@ A financial institution to deposit money - - This layer is shown at zoomlevel **0** and higher + - This layer is shown at zoomlevel **14** and higher - Not visible in the layer selection by default. If you want to make this layer toggable, override `name` @@ -29,22 +29,7 @@ A financial institution to deposit money - [atm](https://mapcomplete.osm.be/atm) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=bank - - atm=yes - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bank%22%5D%5B%22atm%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,11 +46,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/atm#values) [atm](https://wiki.openstreetmap.org/wiki/Key:atm) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:atm%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:atm%3Dno) [separate](https://wiki.openstreetmap.org/wiki/Tag:atm%3Dseparate) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### has_atm @@ -83,12 +88,10 @@ The question is *Does this bank have an ATM?* -### questions +### leftover-questions -Show the images block at this location - This tagrendering has no question and is thus read-only @@ -107,6 +110,30 @@ This tagrendering has no question and is thus read-only +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/barrier.md b/Docs/Layers/barrier.md index 9bee4b990..9fa4ce16a 100644 --- a/Docs/Layers/barrier.md +++ b/Docs/Layers/barrier.md @@ -31,21 +31,7 @@ Obstacles while cycling, such as bollards and cycle barriers - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - barrier=bollard|barrier=cycle_barrier - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22barrier%22%3D%22bollard%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22barrier%22%3D%22cycle_barrier%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,6 +48,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/bicycle#values) [bicycle](https://wiki.openstreetmap.org/wiki/Key:bicycle) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:bicycle%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:bicycle%3Dno) [](https://taginfo.openstreetmap.org/keys/barrier#values) [barrier](https://wiki.openstreetmap.org/wiki/Key:barrier) | Multiple choice | [bollard](https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dbollard) [cycle_barrier](https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dcycle_barrier) [](https://taginfo.openstreetmap.org/keys/bollard#values) [bollard](https://wiki.openstreetmap.org/wiki/Key:bollard) | Multiple choice | [removable](https://wiki.openstreetmap.org/wiki/Tag:bollard%3Dremovable) [fixed](https://wiki.openstreetmap.org/wiki/Tag:bollard%3Dfixed) [foldable](https://wiki.openstreetmap.org/wiki/Tag:bollard%3Dfoldable) [flexible](https://wiki.openstreetmap.org/wiki/Tag:bollard%3Dflexible) [rising](https://wiki.openstreetmap.org/wiki/Tag:bollard%3Drising) @@ -74,6 +61,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -221,6 +227,62 @@ This is rendered with `Overlap: {overlap} m` -This tagrendering is only visible in the popup if the following condition is met: `cycle_barrier=double|cycle_barrier=triple` +This tagrendering is only visible in the popup if the following condition is met: `cycle_barrier=double|cycle_barrier=triple` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/barrier/barrier.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/barrier/barrier.json) diff --git a/Docs/Layers/bench.md b/Docs/Layers/bench.md index 5bb4cf217..9740fce5f 100644 --- a/Docs/Layers/bench.md +++ b/Docs/Layers/bench.md @@ -30,21 +30,7 @@ A bench is a wooden, metal, stone, … surface where a human can sit. This layer - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=bench - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bench%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/backrest#values) [backrest](https://wiki.openstreetmap.org/wiki/Key:backrest) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes) [yes](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:backrest%3Dno) [](https://taginfo.openstreetmap.org/keys/seats#values) [seats](https://wiki.openstreetmap.org/wiki/Key:seats) | [nat](../SpecialInputElements.md#nat) | [](https://taginfo.openstreetmap.org/keys/material#values) [material](https://wiki.openstreetmap.org/wiki/Key:material) | [string](../SpecialInputElements.md#string) | [wood](https://wiki.openstreetmap.org/wiki/Tag:material%3Dwood) [metal](https://wiki.openstreetmap.org/wiki/Tag:material%3Dmetal) [stone](https://wiki.openstreetmap.org/wiki/Tag:material%3Dstone) [concrete](https://wiki.openstreetmap.org/wiki/Tag:material%3Dconcrete) [plastic](https://wiki.openstreetmap.org/wiki/Tag:material%3Dplastic) [steel](https://wiki.openstreetmap.org/wiki/Tag:material%3Dsteel) @@ -70,15 +57,29 @@ attribute | type | values which are supported by this layer [](https://taginfo.openstreetmap.org/keys/inscription#values) [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [text](../SpecialInputElements.md#text) | [](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) [](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) -[](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) -[](https://taginfo.openstreetmap.org/keys/artist:wikidata#values) [artist:wikidata](https://wiki.openstreetmap.org/wiki/Key:artist:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | -[](https://taginfo.openstreetmap.org/keys/artist_name#values) [artist_name](https://wiki.openstreetmap.org/wiki/Key:artist_name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | -[](https://taginfo.openstreetmap.org/keys/subject:wikidata#values) [subject:wikidata](https://wiki.openstreetmap.org/wiki/Key:subject:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -281,111 +282,70 @@ This tagrendering has labels `bench-questions` -### artwork-artwork_type +### leftover-questions -The question is *What is the type of this artwork?* - -This rendering asks information about the property [artwork_type](https://wiki.openstreetmap.org/wiki/Key:artwork_type) - -This is rendered with `This is a {artwork_type}` +This tagrendering has no question and is thus read-only - - *Architecture* corresponds with `artwork_type=architecture` - - *Mural* corresponds with `artwork_type=mural` - - *Painting* corresponds with `artwork_type=painting` - - *Sculpture* corresponds with `artwork_type=sculpture` - - *Statue* corresponds with `artwork_type=statue` - - *Bust* corresponds with `artwork_type=bust` - - *Stone* corresponds with `artwork_type=stone` - - *Installation* corresponds with `artwork_type=installation` - - *Graffiti* corresponds with `artwork_type=graffiti` - - *Relief* corresponds with `artwork_type=relief` - - *Azulejo (Spanish decorative tilework)* corresponds with `artwork_type=azulejo` - - *Tilework* corresponds with `artwork_type=tilework` - - *Woodcarving* corresponds with `artwork_type=woodcarving` - - -This tagrendering is only visible in the popup if the following condition is met: `tourism=artwork` - -This tagrendering has labels `artwork-question` +### minimap -### artwork-artist-wikidata +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only -The question is *Who made this artwork?* -This rendering asks information about the property [artist:wikidata](https://wiki.openstreetmap.org/wiki/Key:artist:wikidata) -This is rendered with `This artwork was made by {wikidata_label(artist:wikidata):font-weight:bold}
{wikipedia(artist:wikidata)}` +### move-button -This tagrendering is only visible in the popup if the following condition is met: `tourism=artwork` - -This tagrendering has labels `artwork-question` +This tagrendering has no question and is thus read-only -### artwork-artist_name + + +### delete-button -The question is *Which artist created this?* - -This rendering asks information about the property [artist_name](https://wiki.openstreetmap.org/wiki/Key:artist_name) - -This is rendered with `Created by {artist_name}` +This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `tourism=artwork` -This tagrendering has labels `artwork-question` + +### last_edit -### artwork-website +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only -The question is *Is there a website with more information about this artwork?* - -This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) - -This is rendered with `More information on this website` +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` -This tagrendering is only visible in the popup if the following condition is met: `tourism=artwork` - -This tagrendering has labels `artwork-question` +### all-tags -### artwork_subject +This tagrendering has no question and is thus read-only -The question is *What does this artwork depict?* - -This rendering asks information about the property [subject:wikidata](https://wiki.openstreetmap.org/wiki/Key:subject:wikidata) - -This is rendered with `This artwork depicts {wikidata_label(subject:wikidata)}{wikipedia(subject:wikidata)}` - - - -This tagrendering is only visible in the popup if the following condition is met: `tourism=artwork` - -This tagrendering has labels `artwork-question` - #### Filters diff --git a/Docs/Layers/bench_at_pt.md b/Docs/Layers/bench_at_pt.md index ea47eddd1..62323a227 100644 --- a/Docs/Layers/bench_at_pt.md +++ b/Docs/Layers/bench_at_pt.md @@ -29,22 +29,7 @@ A layer showing all public-transport-stops which do have a bench - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=bus_stop - - bench=yes|bench=stand_up_bench - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22bus_stop%22%5D%5B%22bench%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22bus_stop%22%5D%5B%22bench%22%3D%22stand_up_bench%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,12 +46,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/bench#values) [bench](https://wiki.openstreetmap.org/wiki/Key:bench) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:bench%3Dyes) [stand_up_bench](https://wiki.openstreetmap.org/wiki/Tag:bench%3Dstand_up_bench) [no](https://wiki.openstreetmap.org/wiki/Tag:bench%3Dno) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -106,6 +111,62 @@ The question is *What kind of bench is this?* - *There is a normal, sit-down bench here* corresponds with `bench=yes` - *Stand up bench* corresponds with `bench=stand_up_bench` - *There is no bench here* corresponds with `bench=no` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/bench_at_pt/bench_at_pt.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bench_at_pt/bench_at_pt.json) diff --git a/Docs/Layers/bicycle_library.md b/Docs/Layers/bicycle_library.md index acefdaf07..06a7087c9 100644 --- a/Docs/Layers/bicycle_library.md +++ b/Docs/Layers/bicycle_library.md @@ -30,21 +30,7 @@ A facility where bicycles can be lent for longer period of times - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=bicycle_library - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bicycle_library%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | @@ -73,6 +60,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -226,6 +232,62 @@ This rendering asks information about the property [description](https://wiki.o This is rendered with `{description}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/bicycle_library/bicycle_library.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bicycle_library/bicycle_library.json) diff --git a/Docs/Layers/bicycle_rental.md b/Docs/Layers/bicycle_rental.md index d8d55df83..c67a14097 100644 --- a/Docs/Layers/bicycle_rental.md +++ b/Docs/Layers/bicycle_rental.md @@ -30,21 +30,7 @@ Bicycle rental stations - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=bicycle_rental|bicycle_rental~.+|service:bicycle:rental=yes|rental~^(.*bicycle.*)$ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bicycle_rental%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22service%3Abicycle%3Arental%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22bicycle_rental%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22rental%22~%22%5E(.*bicycle.*)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | @@ -77,6 +64,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -389,6 +395,72 @@ This is rendered with `{capacity:tandem_bicycle} tandem can be rented here` This tagrendering is only visible in the popup if the following condition is met: `rental~^(.*tandem_bicycle.*)$` -This tagrendering has labels `bicycle_rental` +This tagrendering has labels `bicycle_rental` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/bicycle_rental/bicycle_rental.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bicycle_rental/bicycle_rental.json) diff --git a/Docs/Layers/bicycle_rental_non_docking.md b/Docs/Layers/bicycle_rental_non_docking.md index 9c218261f..e8fabc44c 100644 --- a/Docs/Layers/bicycle_rental_non_docking.md +++ b/Docs/Layers/bicycle_rental_non_docking.md @@ -28,22 +28,7 @@ Bicycle rental stations - [cyclofix](https://mapcomplete.osm.be/cyclofix) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=bicycle_rental|bicycle_rental~.+|service:bicycle:rental=yes|rental~^(.*bicycle.*)$ - - bicycle_rental!=docking_station - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bicycle_rental%22%5D%5B%22bicycle_rental%22!%3D%22docking_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22service%3Abicycle%3Arental%22%3D%22yes%22%5D%5B%22bicycle_rental%22!%3D%22docking_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22bicycle_rental%22%5D%5B%22bicycle_rental%22!%3D%22docking_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22rental%22~%22%5E(.*bicycle.*)%24%22%5D%5B%22bicycle_rental%22!%3D%22docking_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +45,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | @@ -76,6 +62,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -392,12 +397,10 @@ This tagrendering has labels `bicycle_rental` -### questions +### leftover-questions -Show the images block at this location - This tagrendering has no question and is thus read-only @@ -412,6 +415,50 @@ Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/themes/cyclofix/cyclofix.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/cyclofix/cyclofix.json) diff --git a/Docs/Layers/bicycle_tube_vending_machine.md b/Docs/Layers/bicycle_tube_vending_machine.md index 4b0467396..1094b34c2 100644 --- a/Docs/Layers/bicycle_tube_vending_machine.md +++ b/Docs/Layers/bicycle_tube_vending_machine.md @@ -29,22 +29,7 @@ A layer showing vending machines for bicycle tubes (either purpose-built bicycle - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=vending_machine - - vending~^(.*bicycle_tube.*)$ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22vending_machine%22%5D%5B%22vending%22~%22%5E(.*bicycle_tube.*)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/operational_status#values) [operational_status](https://wiki.openstreetmap.org/wiki/Key:operational_status) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:operational_status%3D) [broken](https://wiki.openstreetmap.org/wiki/Tag:operational_status%3Dbroken) [closed](https://wiki.openstreetmap.org/wiki/Tag:operational_status%3Dclosed) [](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/brand#values) [brand](https://wiki.openstreetmap.org/wiki/Key:brand) | [string](../SpecialInputElements.md#string) | [Continental](https://wiki.openstreetmap.org/wiki/Tag:brand%3DContinental) [Schwalbe](https://wiki.openstreetmap.org/wiki/Tag:brand%3DSchwalbe) @@ -69,6 +55,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -196,6 +201,72 @@ The question is *Are other bicycle bicycle accessories sold here?* - Unselecting this answer will add vending:bicycle_pump=no - *Bicycle locks are sold here* corresponds with `vending:bicycle_lock=yes` - Unselecting this answer will add vending:bicycle_lock=no + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bicycle_tube_vending_machine/bicycle_tube_vending_machine.json) diff --git a/Docs/Layers/bike_cafe.md b/Docs/Layers/bike_cafe.md index eb469a1a1..0ff7478ba 100644 --- a/Docs/Layers/bike_cafe.md +++ b/Docs/Layers/bike_cafe.md @@ -29,22 +29,7 @@ A bike café is a café geared towards cyclists, for example with services such - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=pub|amenity=bar|amenity=cafe|amenity=restaurant - - pub=cycling|pub=bicycle|theme=cycling|theme=bicycle|^(service:bicycle:.*)$~~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22pub%22%5D%5B%22pub%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22pub%22%5D%5B%22pub%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22pub%22%5D%5B%22theme%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22pub%22%5D%5B%22theme%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22pub%22%5D%5B~%22%5E(service%3Abicycle%3A.*)%24%22~%22.%2B%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22bar%22%5D%5B%22pub%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22bar%22%5D%5B%22pub%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22bar%22%5D%5B%22theme%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22bar%22%5D%5B%22theme%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22bar%22%5D%5B~%22%5E(service%3Abicycle%3A.*)%24%22~%22.%2B%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cafe%22%5D%5B%22pub%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cafe%22%5D%5B%22pub%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cafe%22%5D%5B%22theme%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cafe%22%5D%5B%22theme%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cafe%22%5D%5B~%22%5E(service%3Abicycle%3A.*)%24%22~%22.%2B%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D%5B%22pub%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D%5B%22pub%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D%5B%22theme%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D%5B%22theme%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D%5B~%22%5E(service%3Abicycle%3A.*)%24%22~%22.%2B%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/service:bicycle:pump#values) [service:bicycle:pump](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:pump) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:pump%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:pump%3Dno) [](https://taginfo.openstreetmap.org/keys/service:bicycle:diy#values) [service:bicycle:diy](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:diy) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:diy%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:diy%3Dno) @@ -73,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -223,6 +228,52 @@ This rendering asks information about the property [opening_hours](https://wiki This is rendered with `

Opening hours

{opening_hours_table(opening_hours)}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/bike_cafe/bike_cafe.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_cafe/bike_cafe.json) diff --git a/Docs/Layers/bike_cleaning.md b/Docs/Layers/bike_cleaning.md index a695f5b5a..22ad6baf2 100644 --- a/Docs/Layers/bike_cleaning.md +++ b/Docs/Layers/bike_cleaning.md @@ -29,21 +29,7 @@ A layer showing facilities where one can clean their bike - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - service:bicycle:cleaning=yes|service:bicycle:cleaning=diy|amenity=bicycle_wash|amenity=bike_wash - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bicycle_wash%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22bike_wash%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22service%3Abicycle%3Acleaning%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22service%3Abicycle%3Acleaning%22%3D%22diy%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +46,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/service:bicycle:cleaning:charge#values) [service:bicycle:cleaning:charge](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:cleaning:charge) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -117,6 +123,72 @@ This is rendered with `Using the cleaning service costs {charge}` - *This cleaning service is paid* corresponds with `fee=yes` -This tagrendering is only visible in the popup if the following condition is met: `amenity=bike_wash|amenity=bicycle_wash` +This tagrendering is only visible in the popup if the following condition is met: `amenity=bike_wash|amenity=bicycle_wash` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/bike_cleaning/bike_cleaning.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_cleaning/bike_cleaning.json) diff --git a/Docs/Layers/bike_parking.md b/Docs/Layers/bike_parking.md index 5100b6e24..c310ae641 100644 --- a/Docs/Layers/bike_parking.md +++ b/Docs/Layers/bike_parking.md @@ -30,21 +30,7 @@ A layer showing where you can park your bike - [transit](https://mapcomplete.osm.be/transit) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=bicycle_parking - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bicycle_parking%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/bicycle_parking#values) [bicycle_parking](https://wiki.openstreetmap.org/wiki/Key:bicycle_parking) | [string](../SpecialInputElements.md#string) | [stands](https://wiki.openstreetmap.org/wiki/Tag:bicycle_parking%3Dstands) [wall_loops](https://wiki.openstreetmap.org/wiki/Tag:bicycle_parking%3Dwall_loops) [handlebar_holder](https://wiki.openstreetmap.org/wiki/Tag:bicycle_parking%3Dhandlebar_holder) [rack](https://wiki.openstreetmap.org/wiki/Tag:bicycle_parking%3Drack) [two_tier](https://wiki.openstreetmap.org/wiki/Tag:bicycle_parking%3Dtwo_tier) [shed](https://wiki.openstreetmap.org/wiki/Tag:bicycle_parking%3Dshed) [bollard](https://wiki.openstreetmap.org/wiki/Tag:bicycle_parking%3Dbollard) [floor](https://wiki.openstreetmap.org/wiki/Tag:bicycle_parking%3Dfloor) [](https://taginfo.openstreetmap.org/keys/location#values) [location](https://wiki.openstreetmap.org/wiki/Key:location) | Multiple choice | [underground](https://wiki.openstreetmap.org/wiki/Tag:location%3Dunderground) [surface](https://wiki.openstreetmap.org/wiki/Tag:location%3Dsurface) [rooftop](https://wiki.openstreetmap.org/wiki/Tag:location%3Drooftop) [](https://taginfo.openstreetmap.org/keys/covered#values) [covered](https://wiki.openstreetmap.org/wiki/Key:covered) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:covered%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:covered%3Dno) @@ -72,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -209,6 +215,72 @@ This is rendered with `This parking fits {capacity:cargo_bike} cargo bikes` -This tagrendering is only visible in the popup if the following condition is met: `cargo_bike~^(designated|yes)$` +This tagrendering is only visible in the popup if the following condition is met: `cargo_bike~^(designated|yes)$` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/bike_parking/bike_parking.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_parking/bike_parking.json) diff --git a/Docs/Layers/bike_repair_station.md b/Docs/Layers/bike_repair_station.md index 611537012..25781d313 100644 --- a/Docs/Layers/bike_repair_station.md +++ b/Docs/Layers/bike_repair_station.md @@ -29,21 +29,7 @@ A layer showing bicycle pumps and bicycle repair tool stands - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=bicycle_repair_station - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bicycle_repair_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/service:bicycle:tools#values) [service:bicycle:tools](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:tools) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:tools%3Dno) [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:tools%3Dyes) [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:tools%3Dyes) [](https://taginfo.openstreetmap.org/keys/service:bicycle:pump:operational_status#values) [service:bicycle:pump:operational_status](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:pump:operational_status) | Multiple choice | [broken](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:pump:operational_status%3Dbroken) [operational](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:pump:operational_status%3Doperational) [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [24/7](https://wiki.openstreetmap.org/wiki/Tag:opening_hours%3D24/7) @@ -77,6 +64,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -339,6 +345,72 @@ This is rendered with `Located on the {level}th floor` - 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` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/bike_repair_station/bike_repair_station.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_repair_station/bike_repair_station.json) diff --git a/Docs/Layers/bike_shop.md b/Docs/Layers/bike_shop.md index 56e96998d..58d01f00e 100644 --- a/Docs/Layers/bike_shop.md +++ b/Docs/Layers/bike_shop.md @@ -29,21 +29,7 @@ A shop specifically selling bicycles or related items - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - shop=bicycle|shop=sports&service:bicycle:retail!=no&service:bicycle:repair!=no&sport=bicycle|sport=cycling| - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22shop%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22shop%22%3D%22sports%22%5D%5B%22sport%22%3D%22bicycle%22%5D%5B%22service%3Abicycle%3Aretail%22!%3D%22no%22%5D%5B%22service%3Abicycle%3Arepair%22!%3D%22no%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22shop%22%3D%22sports%22%5D%5B%22sport%22%3D%22cycling%22%5D%5B%22service%3Abicycle%3Aretail%22!%3D%22no%22%5D%5B%22service%3Abicycle%3Arepair%22!%3D%22no%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22shop%22%3D%22sports%22%5D%5B!%22sport%22%5D%5B%22service%3Abicycle%3Aretail%22!%3D%22no%22%5D%5B%22service%3Abicycle%3Arepair%22!%3D%22no%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/shop#values) [shop](https://wiki.openstreetmap.org/wiki/Key:shop) | Multiple choice | [rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drental) [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | @@ -70,24 +57,34 @@ attribute | type | values which are supported by this layer [](https://taginfo.openstreetmap.org/keys/service:bicycle:retail#values) [service:bicycle:retail](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:retail) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:retail%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:retail%3Dno) [](https://taginfo.openstreetmap.org/keys/service:bicycle:repair#values) [service:bicycle:repair](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:repair) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:repair%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:repair%3Dno) [only_sold](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:repair%3Donly_sold) [brand](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:repair%3Dbrand) [](https://taginfo.openstreetmap.org/keys/service:bicycle:rental#values) [service:bicycle:rental](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:rental) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:rental%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:rental%3Dno) -[](https://taginfo.openstreetmap.org/keys/rental#values) [rental](https://wiki.openstreetmap.org/wiki/Key:rental) | [string](../SpecialInputElements.md#string) | [city_bike](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dcity_bike) [ebike](https://wiki.openstreetmap.org/wiki/Tag:rental%3Debike) [bmx](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dbmx) [mtb](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dmtb) [kid_bike](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dkid_bike) [tandem](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dtandem) [racebike](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dracebike) [bike_helmet](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dbike_helmet) -[](https://taginfo.openstreetmap.org/keys/capacity:city_bike#values) [capacity:city_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:city_bike) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/capacity:ebike#values) [capacity:ebike](https://wiki.openstreetmap.org/wiki/Key:capacity:ebike) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/capacity:kid_bike#values) [capacity:kid_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:kid_bike) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/capacity:bmx#values) [capacity:bmx](https://wiki.openstreetmap.org/wiki/Key:capacity:bmx) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/capacity:mtb#values) [capacity:mtb](https://wiki.openstreetmap.org/wiki/Key:capacity:mtb) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/capacity:bicycle_pannier#values) [capacity:bicycle_pannier](https://wiki.openstreetmap.org/wiki/Key:capacity:bicycle_pannier) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/capacity:tandem_bicycle#values) [capacity:tandem_bicycle](https://wiki.openstreetmap.org/wiki/Key:capacity:tandem_bicycle) | [pnat](../SpecialInputElements.md#pnat) | [](https://taginfo.openstreetmap.org/keys/service:bicycle:second_hand#values) [service:bicycle:second_hand](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:second_hand) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:second_hand%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:second_hand%3Dno) [only](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:second_hand%3Donly) [](https://taginfo.openstreetmap.org/keys/service:bicycle:pump#values) [service:bicycle:pump](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:pump) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:pump%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:pump%3Dno) [separate](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:pump%3Dseparate) [](https://taginfo.openstreetmap.org/keys/service:bicycle:diy#values) [service:bicycle:diy](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:diy) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:diy%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:diy%3Dno) [only_sold](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:diy%3Donly_sold) [](https://taginfo.openstreetmap.org/keys/service:bicycle:cleaning#values) [service:bicycle:cleaning](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:cleaning) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:cleaning%3Dyes) [diy](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:cleaning%3Ddiy) [no](https://wiki.openstreetmap.org/wiki/Tag:service:bicycle:cleaning%3Dno) -[](https://taginfo.openstreetmap.org/keys/service:bicycle:cleaning:charge#values) [service:bicycle:cleaning:charge](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:cleaning:charge) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [string](../SpecialInputElements.md#string) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -275,162 +272,6 @@ The question is *Does this shop rent out bikes?* -### bicycle-types - - - -The question is *What kind of bicycles and accessories are rented here?* - -This rendering asks information about the property [rental](https://wiki.openstreetmap.org/wiki/Key:rental) - -This is rendered with `{rental} is rented here` - - - - - - - *Normal city bikes can be rented here* corresponds with `rental=city_bike` - - *Electrical bikes can be rented here* corresponds with `rental=ebike` - - *BMX bikes can be rented here* corresponds with `rental=bmx` - - *Mountainbikes can be rented here* corresponds with `rental=mtb` - - *Bikes for children can be rented here* corresponds with `rental=kid_bike` - - *Tandem bicycles can be rented here* corresponds with `rental=tandem` - - *Race bicycles can be rented here* corresponds with `rental=racebike` - - *Bike helmets can be rented here* corresponds with `rental=bike_helmet` - - -This tagrendering is only visible in the popup if the following condition is met: `service:bicycle:rental=yes` - -This tagrendering has labels `bicycle_rental` - - - -### rental-capacity-city_bike - - - -The question is *How many city bikes can be rented here?* - -This rendering asks information about the property [capacity:city_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:city_bike) - -This is rendered with `{capacity:city_bike} city bikes can be rented here` - - - -This tagrendering is only visible in the popup if the following condition is met: `rental~^(.*city_bike.*)$&service:bicycle:rental=yes` - -This tagrendering has labels `bicycle_rental` - - - -### rental-capacity-ebike - - - -The question is *How many electrical bikes can be rented here?* - -This rendering asks information about the property [capacity:ebike](https://wiki.openstreetmap.org/wiki/Key:capacity:ebike) - -This is rendered with `{capacity:ebike} electrical bikes can be rented here` - - - -This tagrendering is only visible in the popup if the following condition is met: `rental~^(.*ebike.*)$&service:bicycle:rental=yes` - -This tagrendering has labels `bicycle_rental` - - - -### rental-capacity-kid_bike - - - -The question is *How many bikes for children can be rented here?* - -This rendering asks information about the property [capacity:kid_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:kid_bike) - -This is rendered with `{capacity:kid_bike} bikes for children can be rented here` - - - -This tagrendering is only visible in the popup if the following condition is met: `rental~^(.*kid_bike.*)$&service:bicycle:rental=yes` - -This tagrendering has labels `bicycle_rental` - - - -### rental-capacity-bmx - - - -The question is *How many BMX bikes can be rented here?* - -This rendering asks information about the property [capacity:bmx](https://wiki.openstreetmap.org/wiki/Key:capacity:bmx) - -This is rendered with `{capacity:bmx} BMX bikes can be rented here` - - - -This tagrendering is only visible in the popup if the following condition is met: `rental~^(.*bmx.*)$&service:bicycle:rental=yes` - -This tagrendering has labels `bicycle_rental` - - - -### rental-capacity-mtb - - - -The question is *How many mountainbikes can be rented here?* - -This rendering asks information about the property [capacity:mtb](https://wiki.openstreetmap.org/wiki/Key:capacity:mtb) - -This is rendered with `{capacity:mtb} mountainbikes can be rented here` - - - -This tagrendering is only visible in the popup if the following condition is met: `rental~^(.*mtb.*)$&service:bicycle:rental=yes` - -This tagrendering has labels `bicycle_rental` - - - -### rental-capacity-bicycle_pannier - - - -The question is *How many bicycle panniers can be rented here?* - -This rendering asks information about the property [capacity:bicycle_pannier](https://wiki.openstreetmap.org/wiki/Key:capacity:bicycle_pannier) - -This is rendered with `{capacity:bicycle_pannier} bicycle panniers can be rented here` - - - -This tagrendering is only visible in the popup if the following condition is met: `rental~^(.*bicycle_pannier.*)$&service:bicycle:rental=yes` - -This tagrendering has labels `bicycle_rental` - - - -### rental-capacity-tandem_bicycle - - - -The question is *How many tandem can be rented here?* - -This rendering asks information about the property [capacity:tandem_bicycle](https://wiki.openstreetmap.org/wiki/Key:capacity:tandem_bicycle) - -This is rendered with `{capacity:tandem_bicycle} tandem can be rented here` - - - -This tagrendering is only visible in the popup if the following condition is met: `rental~^(.*tandem_bicycle.*)$&service:bicycle:rental=yes` - -This tagrendering has labels `bicycle_rental` - - - ### bike_repair_second-hand-bikes @@ -499,23 +340,12 @@ The question is *Are bicycles washed here?* -### bike_cleaning-service:bicycle:cleaning:charge +### bikecleaningbikecleaningservicebicyclecleaningcharge -The question is *How much does it cost to use the cleaning service?* +This tagrendering has no question and is thus read-only -This rendering asks information about the property [service:bicycle:cleaning:charge](https://wiki.openstreetmap.org/wiki/Key:service:bicycle:cleaning:charge) - -This is rendered with `Using the cleaning service costs {service:bicycle:cleaning:charge}` - - - - - - - *The cleaning service is free to use* corresponds with `service:bicycle:cleaning:fee=no` - - *Free to use* corresponds with `service:bicycle:cleaning:fee=yes` - - This option cannot be chosen as answer @@ -534,6 +364,62 @@ This is rendered with `{description}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/bike_themed_object.md b/Docs/Layers/bike_themed_object.md index e259285f0..648e6b5d8 100644 --- a/Docs/Layers/bike_themed_object.md +++ b/Docs/Layers/bike_themed_object.md @@ -29,21 +29,7 @@ A layer with bike-themed objects but who don't match any other layer - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - theme=bicycle|theme=cycling|sport=cycling|association=cycling|association=bicycle|ngo=cycling|ngo=bicycle|club=bicycle|club=cycling - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22association%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22association%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22club%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22club%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22ngo%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22ngo%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22sport%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22theme%22%3D%22bicycle%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22theme%22%3D%22cycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -69,6 +56,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -171,6 +177,52 @@ This rendering asks information about the property [opening_hours](https://wiki This is rendered with `

Opening hours

{opening_hours_table(opening_hours)}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/bike_themed_object/bike_themed_object.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/bike_themed_object/bike_themed_object.json) diff --git a/Docs/Layers/binocular.md b/Docs/Layers/binocular.md index b6090611e..ef2953193 100644 --- a/Docs/Layers/binocular.md +++ b/Docs/Layers/binocular.md @@ -29,21 +29,7 @@ Binoculars - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=binoculars - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22binoculars%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +46,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:charge%3D) [](https://taginfo.openstreetmap.org/keys/direction#values) [direction](https://wiki.openstreetmap.org/wiki/Key:direction) | [direction](../SpecialInputElements.md#direction) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -107,6 +113,72 @@ This rendering asks information about the property [direction](https://wiki.ope This is rendered with `Looks towards {direction}°` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/binocular/binocular.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/binocular/binocular.json) diff --git a/Docs/Layers/birdhide.md b/Docs/Layers/birdhide.md index 0e7edcd05..5f6cd18ef 100644 --- a/Docs/Layers/birdhide.md +++ b/Docs/Layers/birdhide.md @@ -29,21 +29,7 @@ A birdhide - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=bird_hide - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22bird_hide%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/building#values) [building](https://wiki.openstreetmap.org/wiki/Key:building) | Multiple choice | [](https://wiki.openstreetmap.org/wiki/Tag:building%3D) [yes](https://wiki.openstreetmap.org/wiki/Tag:building%3Dyes) [tower](https://wiki.openstreetmap.org/wiki/Tag:building%3Dtower) [](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) [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [Natuurpunt](https://wiki.openstreetmap.org/wiki/Tag:operator%3DNatuurpunt) [Agentschap Natuur en Bos](https://wiki.openstreetmap.org/wiki/Tag:operator%3DAgentschap Natuur en Bos) @@ -67,6 +54,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -136,6 +142,72 @@ This is rendered with `Operated by {operator}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/cafe_pub.md b/Docs/Layers/cafe_pub.md index 691c3318d..a5b485aac 100644 --- a/Docs/Layers/cafe_pub.md +++ b/Docs/Layers/cafe_pub.md @@ -30,21 +30,7 @@ A layer showing cafés and pubs where one can gather around a drink. The layer a - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=bar|amenity=pub|amenity=cafe|amenity=biergarten|amenity=nightclub - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22bar%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22pub%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cafe%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22biergarten%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22nightclub%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [pub](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dpub) [bar](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbar) [cafe](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dcafe) [restaurant](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Drestaurant) [biergarten](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dbiergarten) [nightclub](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dnightclub) @@ -79,6 +66,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -393,6 +399,72 @@ This tagrendering has no question and is thus read-only +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/car_rental.md b/Docs/Layers/car_rental.md index 92d83eee4..5db6a8502 100644 --- a/Docs/Layers/car_rental.md +++ b/Docs/Layers/car_rental.md @@ -17,21 +17,7 @@ Places where you can rent a car - This layer is shown at zoomlevel **12** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=car_rental - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22car_rental%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -48,6 +34,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -57,6 +44,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -168,6 +174,62 @@ This is rendered with `

Opening hours

{opening_hours_table(opening_hours +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/caravansites.md b/Docs/Layers/caravansites.md index de51b0bf3..dcbbc0970 100644 --- a/Docs/Layers/caravansites.md +++ b/Docs/Layers/caravansites.md @@ -28,22 +28,7 @@ camper sites - [campersite](https://mapcomplete.osm.be/campersite) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - tourism=caravan_site - - permanent_camping!~^(only)$ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22tourism%22%3D%22caravan_site%22%5D%5B%22permanent_camping%22!~%22%5E(only)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +45,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/fee#values) [fee](https://wiki.openstreetmap.org/wiki/Key:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dno) [](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | @@ -77,6 +63,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -266,6 +271,8 @@ This is rendered with `More details about this place: {description}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -284,6 +291,42 @@ This tagrendering has no question and is thus read-only +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + ### operator @@ -310,30 +353,6 @@ The question is *Does this place have a power supply?* - *This place has a power supply* corresponds with `power_supply=yes` - *This place does not have power supply* corresponds with `power_supply=no` - - - - -### questions - - - -Show the images block at this location - -This tagrendering has no question and is thus read-only - - - - - -### minimap - - - -Shows a small map with the feature. Added by default to every popup - -This tagrendering has no question and is thus read-only - This document is autogenerated from [assets/themes/campersite/campersite.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/campersite/campersite.json) diff --git a/Docs/Layers/charging_station.md b/Docs/Layers/charging_station.md index 3d1ccb19f..aa3df7dd1 100644 --- a/Docs/Layers/charging_station.md +++ b/Docs/Layers/charging_station.md @@ -30,21 +30,7 @@ A charging station - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=charging_station|disused:amenity=charging_station|planned:amenity=charging_station|construction:amenity=charging_station - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22charging_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22construction%3Aamenity%22%3D%22charging_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22disused%3Aamenity%22%3D%22charging_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22planned%3Aamenity%22%3D%22charging_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | [string](../SpecialInputElements.md#string) | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [key](https://wiki.openstreetmap.org/wiki/Tag:access%3Dkey) [private](https://wiki.openstreetmap.org/wiki/Tag:access%3Dprivate) [](https://taginfo.openstreetmap.org/keys/capacity#values) [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) | [pnat](../SpecialInputElements.md#pnat) | [](https://taginfo.openstreetmap.org/keys/socket:schuko#values) [socket:schuko](https://wiki.openstreetmap.org/wiki/Key:socket:schuko) | [pnat](../SpecialInputElements.md#pnat) | @@ -145,6 +132,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -572,7 +578,7 @@ This is rendered with `
Schuko wall plu This tagrendering is only visible in the popup if the following condition is met: `socket:schuko~.+&socket:schuko!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -595,7 +601,7 @@ This is rendered with `
Schuko wall plu This tagrendering is only visible in the popup if the following condition is met: `socket:schuko~.+&socket:schuko!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -618,7 +624,7 @@ This is rendered with `
Schuko wall plu This tagrendering is only visible in the popup if the following condition is met: `socket:schuko~.+&socket:schuko!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -641,7 +647,7 @@ This is rendered with `
European wall p This tagrendering is only visible in the popup if the following condition is met: `socket:typee~.+&socket:typee!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -664,7 +670,7 @@ This is rendered with `
European wall p This tagrendering is only visible in the popup if the following condition is met: `socket:typee~.+&socket:typee!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -688,7 +694,7 @@ This is rendered with `
European wall p This tagrendering is only visible in the popup if the following condition is met: `socket:typee~.+&socket:typee!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -711,7 +717,7 @@ This is rendered with `
Chademo This tagrendering is only visible in the popup if the following condition is met: `socket:chademo~.+&socket:chademo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -734,7 +740,7 @@ This is rendered with `
Chademo This tagrendering is only visible in the popup if the following condition is met: `socket:chademo~.+&socket:chademo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -757,7 +763,7 @@ This is rendered with `
Chademo This tagrendering is only visible in the popup if the following condition is met: `socket:chademo~.+&socket:chademo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -781,7 +787,7 @@ This is rendered with `
Type 1 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type1_cable~.+&socket:type1_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -804,7 +810,7 @@ This is rendered with `
Type 1 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type1_cable~.+&socket:type1_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -828,7 +834,7 @@ This is rendered with `
Type 1 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type1_cable~.+&socket:type1_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -852,7 +858,7 @@ This is rendered with `
Type 1 witho This tagrendering is only visible in the popup if the following condition is met: `socket:type1~.+&socket:type1!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -875,7 +881,7 @@ This is rendered with `
Type 1 witho This tagrendering is only visible in the popup if the following condition is met: `socket:type1~.+&socket:type1!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -901,7 +907,7 @@ This is rendered with `
Type 1 witho This tagrendering is only visible in the popup if the following condition is met: `socket:type1~.+&socket:type1!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -925,7 +931,7 @@ This is rendered with `
Type 1 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type1_combo~.+&socket:type1_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -949,7 +955,7 @@ This is rendered with `
Type 1 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type1_combo~.+&socket:type1_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -975,7 +981,7 @@ This is rendered with `
Type 1 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type1_combo~.+&socket:type1_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -998,7 +1004,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger~.+&socket:tesla_supercharger!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1022,7 +1028,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger~.+&socket:tesla_supercharger!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1047,7 +1053,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger~.+&socket:tesla_supercharger!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1071,7 +1077,7 @@ This is rendered with `
Type 2 (men This tagrendering is only visible in the popup if the following condition is met: `socket:type2~.+&socket:type2!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1095,7 +1101,7 @@ This is rendered with `
Type 2 (men This tagrendering is only visible in the popup if the following condition is met: `socket:type2~.+&socket:type2!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1119,7 +1125,7 @@ This is rendered with `
Type 2 (men This tagrendering is only visible in the popup if the following condition is met: `socket:type2~.+&socket:type2!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1143,7 +1149,7 @@ This is rendered with `
Type 2 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type2_combo~.+&socket:type2_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1167,7 +1173,7 @@ This is rendered with `
Type 2 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type2_combo~.+&socket:type2_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1190,7 +1196,7 @@ This is rendered with `
Type 2 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type2_combo~.+&socket:type2_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1214,7 +1220,7 @@ This is rendered with `
Type 2 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type2_cable~.+&socket:type2_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1238,7 +1244,7 @@ This is rendered with `
Type 2 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type2_cable~.+&socket:type2_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1262,7 +1268,7 @@ This is rendered with `
Type 2 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type2_cable~.+&socket:type2_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1286,7 +1292,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger_ccs~.+&socket:tesla_supercharger_ccs!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1310,7 +1316,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger_ccs~.+&socket:tesla_supercharger_ccs!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1333,7 +1339,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger_ccs~.+&socket:tesla_supercharger_ccs!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1356,7 +1362,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1380,7 +1386,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1405,7 +1411,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1429,7 +1435,7 @@ This is rendered with `
Tesla superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1453,7 +1459,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1477,7 +1483,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1500,7 +1506,7 @@ This is rendered with `
USB to char This tagrendering is only visible in the popup if the following condition is met: `socket:USB-A~.+&socket:USB-A!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1524,7 +1530,7 @@ This is rendered with `
USB to char This tagrendering is only visible in the popup if the following condition is met: `socket:USB-A~.+&socket:USB-A!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1548,7 +1554,7 @@ This is rendered with `
USB to char This tagrendering is only visible in the popup if the following condition is met: `socket:USB-A~.+&socket:USB-A!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1571,7 +1577,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_3pin~.+&socket:bosch_3pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1594,7 +1600,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_3pin~.+&socket:bosch_3pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1617,7 +1623,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_3pin~.+&socket:bosch_3pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1640,7 +1646,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_5pin~.+&socket:bosch_5pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1663,7 +1669,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_5pin~.+&socket:bosch_5pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1686,7 +1692,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_5pin~.+&socket:bosch_5pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -2012,7 +2018,7 @@ This tagrendering has no question and is thus read-only -### questions +### questions-technical @@ -2020,7 +2026,71 @@ This tagrendering has no question and is thus read-only -This tagrendering is part of group `technical` + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + diff --git a/Docs/Layers/charging_station_ebikes.md b/Docs/Layers/charging_station_ebikes.md index ee57e42b1..d28282d96 100644 --- a/Docs/Layers/charging_station_ebikes.md +++ b/Docs/Layers/charging_station_ebikes.md @@ -28,22 +28,7 @@ A charging station - [cyclofix](https://mapcomplete.osm.be/cyclofix) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=charging_station|disused:amenity=charging_station|planned:amenity=charging_station|construction:amenity=charging_station - - bicycle=yes - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22bicycle%22%3D%22yes%22%5D%5B%22amenity%22%3D%22charging_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22bicycle%22%3D%22yes%22%5D%5B%22construction%3Aamenity%22%3D%22charging_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22bicycle%22%3D%22yes%22%5D%5B%22disused%3Aamenity%22%3D%22charging_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22bicycle%22%3D%22yes%22%5D%5B%22planned%3Aamenity%22%3D%22charging_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +45,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | [string](../SpecialInputElements.md#string) | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [key](https://wiki.openstreetmap.org/wiki/Tag:access%3Dkey) [private](https://wiki.openstreetmap.org/wiki/Tag:access%3Dprivate) [](https://taginfo.openstreetmap.org/keys/capacity#values) [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) | [pnat](../SpecialInputElements.md#pnat) | [](https://taginfo.openstreetmap.org/keys/socket:schuko#values) [socket:schuko](https://wiki.openstreetmap.org/wiki/Key:socket:schuko) | [pnat](../SpecialInputElements.md#pnat) | @@ -144,6 +130,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -571,7 +576,7 @@ This is rendered with `
Schuko wall plu This tagrendering is only visible in the popup if the following condition is met: `socket:schuko~.+&socket:schuko!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -594,7 +599,7 @@ This is rendered with `
Schuko wall plu This tagrendering is only visible in the popup if the following condition is met: `socket:schuko~.+&socket:schuko!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -617,7 +622,7 @@ This is rendered with `
Schuko wall plu This tagrendering is only visible in the popup if the following condition is met: `socket:schuko~.+&socket:schuko!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -640,7 +645,7 @@ This is rendered with `
European wall p This tagrendering is only visible in the popup if the following condition is met: `socket:typee~.+&socket:typee!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -663,7 +668,7 @@ This is rendered with `
European wall p This tagrendering is only visible in the popup if the following condition is met: `socket:typee~.+&socket:typee!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -687,7 +692,7 @@ This is rendered with `
European wall p This tagrendering is only visible in the popup if the following condition is met: `socket:typee~.+&socket:typee!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -710,7 +715,7 @@ This is rendered with `
Chademo This tagrendering is only visible in the popup if the following condition is met: `socket:chademo~.+&socket:chademo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -733,7 +738,7 @@ This is rendered with `
Chademo This tagrendering is only visible in the popup if the following condition is met: `socket:chademo~.+&socket:chademo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -756,7 +761,7 @@ This is rendered with `
Chademo This tagrendering is only visible in the popup if the following condition is met: `socket:chademo~.+&socket:chademo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -780,7 +785,7 @@ This is rendered with `
Type 1 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type1_cable~.+&socket:type1_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -803,7 +808,7 @@ This is rendered with `
Type 1 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type1_cable~.+&socket:type1_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -827,7 +832,7 @@ This is rendered with `
Type 1 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type1_cable~.+&socket:type1_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -851,7 +856,7 @@ This is rendered with `
Type 1 witho This tagrendering is only visible in the popup if the following condition is met: `socket:type1~.+&socket:type1!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -874,7 +879,7 @@ This is rendered with `
Type 1 witho This tagrendering is only visible in the popup if the following condition is met: `socket:type1~.+&socket:type1!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -900,7 +905,7 @@ This is rendered with `
Type 1 witho This tagrendering is only visible in the popup if the following condition is met: `socket:type1~.+&socket:type1!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -924,7 +929,7 @@ This is rendered with `
Type 1 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type1_combo~.+&socket:type1_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -948,7 +953,7 @@ This is rendered with `
Type 1 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type1_combo~.+&socket:type1_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -974,7 +979,7 @@ This is rendered with `
Type 1 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type1_combo~.+&socket:type1_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -997,7 +1002,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger~.+&socket:tesla_supercharger!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1021,7 +1026,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger~.+&socket:tesla_supercharger!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1046,7 +1051,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger~.+&socket:tesla_supercharger!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1070,7 +1075,7 @@ This is rendered with `
Type 2 (men This tagrendering is only visible in the popup if the following condition is met: `socket:type2~.+&socket:type2!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1094,7 +1099,7 @@ This is rendered with `
Type 2 (men This tagrendering is only visible in the popup if the following condition is met: `socket:type2~.+&socket:type2!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1118,7 +1123,7 @@ This is rendered with `
Type 2 (men This tagrendering is only visible in the popup if the following condition is met: `socket:type2~.+&socket:type2!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1142,7 +1147,7 @@ This is rendered with `
Type 2 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type2_combo~.+&socket:type2_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1166,7 +1171,7 @@ This is rendered with `
Type 2 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type2_combo~.+&socket:type2_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1189,7 +1194,7 @@ This is rendered with `
Type 2 CCS This tagrendering is only visible in the popup if the following condition is met: `socket:type2_combo~.+&socket:type2_combo!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1213,7 +1218,7 @@ This is rendered with `
Type 2 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type2_cable~.+&socket:type2_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1237,7 +1242,7 @@ This is rendered with `
Type 2 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type2_cable~.+&socket:type2_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1261,7 +1266,7 @@ This is rendered with `
Type 2 with cab This tagrendering is only visible in the popup if the following condition is met: `socket:type2_cable~.+&socket:type2_cable!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1285,7 +1290,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger_ccs~.+&socket:tesla_supercharger_ccs!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1309,7 +1314,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger_ccs~.+&socket:tesla_supercharger_ccs!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1332,7 +1337,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_supercharger_ccs~.+&socket:tesla_supercharger_ccs!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1355,7 +1360,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1379,7 +1384,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1404,7 +1409,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1428,7 +1433,7 @@ This is rendered with `
Tesla superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1452,7 +1457,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1476,7 +1481,7 @@ This is rendered with `
Tesla Superchar This tagrendering is only visible in the popup if the following condition is met: `socket:tesla_destination~.+&socket:tesla_destination!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1499,7 +1504,7 @@ This is rendered with `
USB to char This tagrendering is only visible in the popup if the following condition is met: `socket:USB-A~.+&socket:USB-A!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1523,7 +1528,7 @@ This is rendered with `
USB to char This tagrendering is only visible in the popup if the following condition is met: `socket:USB-A~.+&socket:USB-A!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1547,7 +1552,7 @@ This is rendered with `
USB to char This tagrendering is only visible in the popup if the following condition is met: `socket:USB-A~.+&socket:USB-A!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1570,7 +1575,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_3pin~.+&socket:bosch_3pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1593,7 +1598,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_3pin~.+&socket:bosch_3pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1616,7 +1621,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_3pin~.+&socket:bosch_3pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1639,7 +1644,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_5pin~.+&socket:bosch_5pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1662,7 +1667,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_5pin~.+&socket:bosch_5pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -1685,7 +1690,7 @@ This is rendered with `
Bosch Active Co This tagrendering is only visible in the popup if the following condition is met: `socket:bosch_5pin~.+&socket:bosch_5pin!=0` -This tagrendering is part of group `technical` +This tagrendering has labels `technical` @@ -2011,7 +2016,7 @@ This tagrendering has no question and is thus read-only -### questions +### questions-technical @@ -2019,16 +2024,12 @@ This tagrendering has no question and is thus read-only -This tagrendering is part of group `technical` - -### questions +### leftover-questions -Show the images block at this location - This tagrendering has no question and is thus read-only @@ -2043,6 +2044,50 @@ Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/themes/cyclofix/cyclofix.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/cyclofix/cyclofix.json) diff --git a/Docs/Layers/climbing.md b/Docs/Layers/climbing.md index 6c85aa3dc..9d238b716 100644 --- a/Docs/Layers/climbing.md +++ b/Docs/Layers/climbing.md @@ -20,21 +20,7 @@ A dummy layer which contains tagrenderings, shared among the climbing layers - Not rendered on the map by default. If you want to rendering this on the map, override `mapRenderings` - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - sport=climbing - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22sport%22%3D%22climbing%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -51,6 +37,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/url#values) [url](https://wiki.openstreetmap.org/wiki/Key:url) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pfloat](../SpecialInputElements.md#pfloat) | [](https://taginfo.openstreetmap.org/keys/climbing:grade:french:min#values) [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) | [string](../SpecialInputElements.md#string) | @@ -65,6 +52,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### website @@ -228,6 +234,52 @@ This is rendered with `A fee of {charge} should be paid for climbing here` - *Climbing here is free of charge* corresponds with `fee=no` - *Paying a fee is required to climb here* corresponds with `fee=yes` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/climbing/climbing.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/climbing/climbing.json) diff --git a/Docs/Layers/climbing_area.md b/Docs/Layers/climbing_area.md index b4d70aa7e..3d7ebc5d7 100644 --- a/Docs/Layers/climbing_area.md +++ b/Docs/Layers/climbing_area.md @@ -30,25 +30,7 @@ An area where climbing is possible, e.g. a crag, site, boulder, … Contains agg - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - sport=climbing - - climbing!~^(route)$ - - leisure!~^(sports_centre)$ - - climbing!=route_top - - climbing!=route_bottom - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22sport%22%3D%22climbing%22%5D%5B%22climbing%22!~%22%5E(route)%24%22%5D%5B%22climbing%22!%3D%22route_top%22%5D%5B%22climbing%22!%3D%22route_bottom%22%5D%5B%22leisure%22!~%22%5E(sports_centre)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -65,16 +47,33 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:name%3D) [](https://taginfo.openstreetmap.org/keys/climbing#values) [climbing](https://wiki.openstreetmap.org/wiki/Key:climbing) | Multiple choice | [boulder](https://wiki.openstreetmap.org/wiki/Tag:climbing%3Dboulder) [crag](https://wiki.openstreetmap.org/wiki/Tag:climbing%3Dcrag) [area](https://wiki.openstreetmap.org/wiki/Tag:climbing%3Darea) [](https://taginfo.openstreetmap.org/keys/rock#values) [rock](https://wiki.openstreetmap.org/wiki/Key:rock) | [string](../SpecialInputElements.md#string) | [limestone](https://wiki.openstreetmap.org/wiki/Tag:rock%3Dlimestone) -[](https://taginfo.openstreetmap.org/keys/url#values) [url](https://wiki.openstreetmap.org/wiki/Key:url) | [url](../SpecialInputElements.md#url) | -[](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:charge%3D) -[](https://taginfo.openstreetmap.org/keys/climbing:boulder#values) [climbing:boulder](https://wiki.openstreetmap.org/wiki/Key:climbing:boulder) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dlimited) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -186,57 +185,36 @@ This tagrendering is only visible in the popup if the following condition is met -### website +### leftover-questions -The question is *Is there a (unofficial) website with more informations (e.g. topos)?* - -This rendering asks information about the property [url](https://wiki.openstreetmap.org/wiki/Key:url) - -This is rendered with `{url}` - - - -This tagrendering is only visible in the popup if the following condition is met: `leisure!~^(sports_centre)$&sport=climbing` - - - -### fee - - - -The question is *Is a fee required to climb here?* - -This rendering asks information about the property [charge](https://wiki.openstreetmap.org/wiki/Key:charge) - -This is rendered with `A fee of {charge} should be paid for climbing here` +This tagrendering has no question and is thus read-only - - *Climbing here is free of charge* corresponds with `fee=no` - - *Paying a fee is required to climb here* corresponds with `fee=yes` +### last_edit +Gives some metainfo about the last edit and who did edit it - rendering only -### bouldering +This tagrendering has no question and is thus read-only -The question is *Is bouldering possible here?* +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` +### all-tags - - *Bouldering is possible here* corresponds with `climbing:boulder=yes` - - *Bouldering is not possible here* corresponds with `climbing:boulder=no` - - *Bouldering is possible, allthough there are only a few routes* corresponds with `climbing:boulder=limited` - - *There are {climbing:boulder} boulder routes* corresponds with `climbing:boulder~.+` - - This option cannot be chosen as answer + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/climbing_area/climbing_area.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/climbing_area/climbing_area.json) diff --git a/Docs/Layers/climbing_club.md b/Docs/Layers/climbing_club.md index 5f18d356f..7329a8744 100644 --- a/Docs/Layers/climbing_club.md +++ b/Docs/Layers/climbing_club.md @@ -29,21 +29,7 @@ A climbing club or organisation - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - club=climbing|sport=climbing&office~.+|club~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22club%22%3D%22climbing%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22sport%22%3D%22climbing%22%5D%5B%22club%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22sport%22%3D%22climbing%22%5D%5B%22office%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -69,6 +56,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### climbing_club-name @@ -159,6 +165,52 @@ This rendering asks information about the property [opening_hours](https://wiki This is rendered with `

Opening hours

{opening_hours_table(opening_hours)}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/climbing_club/climbing_club.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/climbing_club/climbing_club.json) diff --git a/Docs/Layers/climbing_gym.md b/Docs/Layers/climbing_gym.md index 66bcb94e3..046af7600 100644 --- a/Docs/Layers/climbing_gym.md +++ b/Docs/Layers/climbing_gym.md @@ -29,22 +29,7 @@ A climbing gym - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - sport=climbing - - leisure=sports_centre - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22sport%22%3D%22climbing%22%5D%5B%22leisure%22%3D%22sports_centre%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,26 +46,42 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | -[](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:charge%3D) [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/service:rental:climbing_shoes#values) [service:rental:climbing_shoes](https://wiki.openstreetmap.org/wiki/Key:service:rental:climbing_shoes) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:rental:climbing_shoes%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:rental:climbing_shoes%3Dno) [](https://taginfo.openstreetmap.org/keys/service:rental:climbing_harness#values) [service:rental:climbing_harness](https://wiki.openstreetmap.org/wiki/Key:service:rental:climbing_harness) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:rental:climbing_harness%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:rental:climbing_harness%3Dno) -[](https://taginfo.openstreetmap.org/keys/climbing:toprope#values) [climbing:toprope](https://wiki.openstreetmap.org/wiki/Key:climbing:toprope) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dno) -[](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pfloat](../SpecialInputElements.md#pfloat) | -[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:min#values) [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:max#values) [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/climbing:boulder#values) [climbing:boulder](https://wiki.openstreetmap.org/wiki/Key:climbing:boulder) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dlimited) -[](https://taginfo.openstreetmap.org/keys/climbing:sport#values) [climbing:sport](https://wiki.openstreetmap.org/wiki/Key:climbing:sport) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dno) -[](https://taginfo.openstreetmap.org/keys/climbing:bolts:max#values) [climbing:bolts:max](https://wiki.openstreetmap.org/wiki/Key:climbing:bolts:max) | [pnat](../SpecialInputElements.md#pnat) | +[](https://taginfo.openstreetmap.org/keys/service:rental:climbing_rope#values) [service:rental:climbing_rope](https://wiki.openstreetmap.org/wiki/Key:service:rental:climbing_rope) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:service:rental:climbing_rope%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:service:rental:climbing_rope%3Dno) [](https://taginfo.openstreetmap.org/keys/climbing:speed#values) [climbing:speed](https://wiki.openstreetmap.org/wiki/Key:climbing:speed) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dno) +[](https://taginfo.openstreetmap.org/keys/internet_access#values) [internet_access](https://wiki.openstreetmap.org/wiki/Key:internet_access) | Multiple choice | [wlan](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dwlan) [no](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dno) [terminal](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dterminal) [wired](https://wiki.openstreetmap.org/wiki/Tag:internet_access%3Dwired) +[](https://taginfo.openstreetmap.org/keys/internet_access:fee#values) [internet_access:fee](https://wiki.openstreetmap.org/wiki/Key:internet_access:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dno) [customers](https://wiki.openstreetmap.org/wiki/Tag:internet_access:fee%3Dcustomers) +[](https://taginfo.openstreetmap.org/keys/internet_access:ssid#values) [internet_access:ssid](https://wiki.openstreetmap.org/wiki/Key:internet_access:ssid) | [string](../SpecialInputElements.md#string) | [Telekom](https://wiki.openstreetmap.org/wiki/Tag:internet_access:ssid%3DTelekom) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -173,22 +174,22 @@ This tagrendering has labels `contact` -### fee +### payment-options -The question is *Is a fee required to climb here?* - -This rendering asks information about the property [charge](https://wiki.openstreetmap.org/wiki/Key:charge) - -This is rendered with `A fee of {charge} should be paid for climbing here` +The question is *Which methods of payment are accepted here?* - - *Climbing here is free of charge* corresponds with `fee=no` - - *Paying a fee is required to climb here* corresponds with `fee=yes` + - *Cash is accepted here* corresponds with `payment:cash=yes` + - Unselecting this answer will add payment:cash=no + - *Payment cards are accepted here* corresponds with `payment:cards=yes` + - Unselecting this answer will add payment:cards=no + - *Payment by QR-code is possible here* corresponds with `payment:qr_code=yes` + - Unselecting this answer will add payment:qr_code=no @@ -239,118 +240,29 @@ The question is *Can one rent a climbing harness here?* -### toprope +### rope_rental -The question is *Is toprope climbing possible here?* +The question is *Can one rent a climbing rope here?* - - *Toprope climbing is possible here* corresponds with `climbing:toprope=yes` - - *Toprope climbing is not possible here* corresponds with `climbing:toprope=no` - - *There are {climbing:toprope} toprope routes* corresponds with `climbing:toprope~.+` - - This option cannot be chosen as answer + - *A climbing rope can be rented here* corresponds with `service:rental:climbing_rope=yes` + - *A climbing rope can not be rented here* corresponds with `service:rental:climbing_rope=no` -### average_length +### climbingtoprope -The question is *What is the (average) length of the routes in meters?* +This tagrendering has no question and is thus read-only -This rendering asks information about the property [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) -This is rendered with `The routes are {canonical(climbing:length)} long on average` - - - - - -### min_difficulty - - - -The question is *What is the grade of the easiest route here, according to the french classification system?* - -This rendering asks information about the property [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) - -This is rendered with `The lowest grade is {climbing:grade:french:min} according to the french/belgian system` - - - - - -### max_difficulty - - - -The question is *What is the highest grade route here, according to the french classification system?* - -This rendering asks information about the property [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) - -This is rendered with `The highest grade is {climbing:grade:french:max} according to the french/belgian system` - - - -This tagrendering is only visible in the popup if the following condition is met: `climbing!~^(route)$&climbing:sport=yes|sport=climbing` - - - -### bouldering - - - -The question is *Is bouldering possible here?* - - - - - - - *Bouldering is possible here* corresponds with `climbing:boulder=yes` - - *Bouldering is not possible here* corresponds with `climbing:boulder=no` - - *Bouldering is possible, allthough there are only a few routes* corresponds with `climbing:boulder=limited` - - *There are {climbing:boulder} boulder routes* corresponds with `climbing:boulder~.+` - - This option cannot be chosen as answer - - - - -### sportclimbing - - - -The question is *Is sport climbing possible here on fixed anchors?* - - - - - - - *Sport climbing is possible here* corresponds with `climbing:sport=yes` - - *Sport climbing is not possible here* corresponds with `climbing:sport=no` - - *There are {climbing:sport} sport climbing routes* corresponds with `climbing:sport~.+` - - This option cannot be chosen as answer - - - - -### max_bolts - - - -The question is *How many bolts do routes in {title()} have at most?* - -This rendering asks information about the property [climbing:bolts:max](https://wiki.openstreetmap.org/wiki/Key:climbing:bolts:max) - -This is rendered with `The sport climbing routes here have at most {climbing:bolts:max} bolts.
This is without relays and indicates how much quickdraws a climber needs
` - - - -This tagrendering is only visible in the popup if the following condition is met: `climbing:sport=yes` @@ -368,6 +280,112 @@ The question is *Is there a speed climbing wall?* - *There is no speed climbing wall* corresponds with `climbing:speed=no` - *There are {climbing:speed} speed climbing walls* corresponds with `climbing:speed~.+` - This option cannot be chosen as answer + + + + +### internet + + + +The question is *Does this place offer internet access?* + + + + + + - *This place offers wireless internet access* corresponds with `internet_access=wlan` + - *This place does not offer internet access* corresponds with `internet_access=no` + - *This place offers internet access* corresponds with `internet_access=yes` + - This option cannot be chosen as answer + - *This place offers internet access via a terminal or computer* corresponds with `internet_access=terminal` + - *This place offers wired internet access* corresponds with `internet_access=wired` + + + + +### internet-fee + + + +The question is *Is there a fee for internet access?* + + + + + + - *There is a fee for the internet access at this place* corresponds with `internet_access:fee=yes` + - *Internet access is free at this place* corresponds with `internet_access:fee=no` + - *Internet access is free at this place, for customers only* corresponds with `internet_access:fee=customers` + + +This tagrendering is only visible in the popup if the following condition is met: `internet_access!=no&internet_access~.+` + + + +### internet-ssid + + + +The question is *What is the network name for the wireless internet access?* + +This rendering asks information about the property [internet_access:ssid](https://wiki.openstreetmap.org/wiki/Key:internet_access:ssid) + +This is rendered with `The network name is {internet_access:ssid}` + + + + + + - *Telekom* corresponds with `internet_access:ssid=Telekom` + + +This tagrendering is only visible in the popup if the following condition is met: `internet_access=wlan` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/climbing_gym/climbing_gym.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/climbing_gym/climbing_gym.json) diff --git a/Docs/Layers/climbing_opportunity.md b/Docs/Layers/climbing_opportunity.md index e87ea6e91..8571a8e35 100644 --- a/Docs/Layers/climbing_opportunity.md +++ b/Docs/Layers/climbing_opportunity.md @@ -29,22 +29,7 @@ Fallback layer with items on which climbing _might_ be possible. It is loaded wh - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=sports_centre|barrier=wall|barrier=retaining_wall|natural=cliff|natural=rock|natural=stone - - - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22barrier%22%3D%22wall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22barrier%22%3D%22retaining_wall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22leisure%22%3D%22sports_centre%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22natural%22%3D%22cliff%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22natural%22%3D%22rock%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22natural%22%3D%22stone%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -53,6 +38,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### climbing-opportunity-name @@ -81,6 +96,52 @@ The question is *Is climbing possible here?* - *Climbing is not possible here* corresponds with `climbing=no` - *Climbing is not possible here* corresponds with `sport!~^(climbing)$` - This option cannot be chosen as answer + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/climbing_opportunity/climbing_opportunity.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/climbing_opportunity/climbing_opportunity.json) diff --git a/Docs/Layers/climbing_route.md b/Docs/Layers/climbing_route.md index a453fbe35..668898b8b 100644 --- a/Docs/Layers/climbing_route.md +++ b/Docs/Layers/climbing_route.md @@ -30,21 +30,7 @@ A single climbing route and its properties. Some properties are derived from the - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - climbing=route - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22climbing%22%3D%22route%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:name%3D) [](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pnat](../SpecialInputElements.md#pnat) | [](https://taginfo.openstreetmap.org/keys/climbing:grade:french#values) [climbing:grade:french](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french) | [string](../SpecialInputElements.md#string) | @@ -71,6 +58,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -173,6 +179,52 @@ This rendering asks information about the property [_embedding_features_with_ro This is rendered with `The rock type is {_embedding_features_with_rock:rock} as stated on the surrounding crag` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/climbing_route/climbing_route.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/climbing_route/climbing_route.json) diff --git a/Docs/Layers/clock.md b/Docs/Layers/clock.md index cb92006af..c3ffafc41 100644 --- a/Docs/Layers/clock.md +++ b/Docs/Layers/clock.md @@ -30,21 +30,7 @@ Layer with public clocks - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=clock - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22clock%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/support#values) [support](https://wiki.openstreetmap.org/wiki/Key:support) | Multiple choice | [pole](https://wiki.openstreetmap.org/wiki/Tag:support%3Dpole) [wall_mounted](https://wiki.openstreetmap.org/wiki/Tag:support%3Dwall_mounted) [billboard](https://wiki.openstreetmap.org/wiki/Tag:support%3Dbillboard) [ground](https://wiki.openstreetmap.org/wiki/Tag:support%3Dground) [](https://taginfo.openstreetmap.org/keys/display#values) [display](https://wiki.openstreetmap.org/wiki/Key:display) | Multiple choice | [analog](https://wiki.openstreetmap.org/wiki/Tag:display%3Danalog) [digital](https://wiki.openstreetmap.org/wiki/Tag:display%3Ddigital) [sundial](https://wiki.openstreetmap.org/wiki/Tag:display%3Dsundial) [unorthodox](https://wiki.openstreetmap.org/wiki/Tag:display%3Dunorthodox) [](https://taginfo.openstreetmap.org/keys/visibility#values) [visibility](https://wiki.openstreetmap.org/wiki/Key:visibility) | Multiple choice | [house](https://wiki.openstreetmap.org/wiki/Tag:visibility%3Dhouse) [street](https://wiki.openstreetmap.org/wiki/Tag:visibility%3Dstreet) [area](https://wiki.openstreetmap.org/wiki/Tag:visibility%3Darea) @@ -73,6 +60,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -227,6 +233,72 @@ This is rendered with `This clock has {faces} faces` - *This clock has one face* corresponds with `faces=1` - *This clock has two faces* corresponds with `faces=2` - *This clock has four faces* corresponds with `faces=4` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/clock/clock.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/clock/clock.json) diff --git a/Docs/Layers/cluster_style.md b/Docs/Layers/cluster_style.md deleted file mode 100644 index 19209617f..000000000 --- a/Docs/Layers/cluster_style.md +++ /dev/null @@ -1,56 +0,0 @@ -[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources) - - cluster_style -=============== - - - - - -The style for the clustering in all themes. Enable `debug=true` to peak into clustered tiles - - - - - - - - This layer is shown at zoomlevel **0** and higher - - Not visible in the layer selection by default. If you want to make this layer toggable, override `name` - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - tileId~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22tileId%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - - - - Supported attributes ----------------------- - - - - - -### all_tags - - - -Shows a table with all the tags of the feature - -This tagrendering has no question and is thus read-only - - - -This document is autogenerated from [assets/layers/cluster_style/cluster_style.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/cluster_style/cluster_style.json) diff --git a/Docs/Layers/crab_address.md b/Docs/Layers/crab_address.md index b4cd9800a..296cf17c3 100644 --- a/Docs/Layers/crab_address.md +++ b/Docs/Layers/crab_address.md @@ -18,21 +18,7 @@ Address data for Flanders by the governement, suited for import into OpenStreetM - This layer is loaded from an external source, namely `https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/CRAB_2021_10_26/tile_{z}_{x}_{y}.geojson` - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - HUISNR~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22HUISNR%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -41,6 +27,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### render_crab @@ -49,6 +65,52 @@ Elements must have the all of following tags to be shown on this layer: This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/crab_address/crab_address.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/crab_address/crab_address.json) diff --git a/Docs/Layers/crossings.md b/Docs/Layers/crossings.md index 400bef822..70fb4334a 100644 --- a/Docs/Layers/crossings.md +++ b/Docs/Layers/crossings.md @@ -33,21 +33,7 @@ Crossings for pedestrians and cyclists - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=traffic_signals|highway=crossing - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22traffic_signals%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22crossing%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -64,6 +50,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/crossing#values) [crossing](https://wiki.openstreetmap.org/wiki/Key:crossing) | Multiple choice | [uncontrolled](https://wiki.openstreetmap.org/wiki/Tag:crossing%3Duncontrolled) [traffic_signals](https://wiki.openstreetmap.org/wiki/Tag:crossing%3Dtraffic_signals) [unmarked](https://wiki.openstreetmap.org/wiki/Tag:crossing%3Dunmarked) [](https://taginfo.openstreetmap.org/keys/crossing_ref#values) [crossing_ref](https://wiki.openstreetmap.org/wiki/Key:crossing_ref) | Multiple choice | [zebra](https://wiki.openstreetmap.org/wiki/Tag:crossing_ref%3Dzebra) [](https://wiki.openstreetmap.org/wiki/Tag:crossing_ref%3D) [](https://taginfo.openstreetmap.org/keys/bicycle#values) [bicycle](https://wiki.openstreetmap.org/wiki/Key:bicycle) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:bicycle%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:bicycle%3Dno) @@ -80,6 +67,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -317,6 +323,52 @@ This tagrendering is only visible in the popup if the following condition is met +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/cultural_places_without_etymology.md b/Docs/Layers/cultural_places_without_etymology.md index 594b792c8..a07626850 100644 --- a/Docs/Layers/cultural_places_without_etymology.md +++ b/Docs/Layers/cultural_places_without_etymology.md @@ -28,22 +28,7 @@ All objects which have an etymology known - [etymology](https://mapcomplete.osm.be/etymology) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - name~.+ - - amenity=arts_centre|amenity=cinema|amenity=community_centre|amenity=library|amenity=theatre - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22arts_centre%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cinema%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22community_centre%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22library%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22theatre%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +45,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) | [](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### etymology-images-from-wikipedia @@ -125,6 +130,8 @@ This is rendered with `Named after {name:etymology}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -169,6 +176,30 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` +This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) diff --git a/Docs/Layers/cycleways_and_roads.md b/Docs/Layers/cycleways_and_roads.md index 5544f8018..d5cfff49f 100644 --- a/Docs/Layers/cycleways_and_roads.md +++ b/Docs/Layers/cycleways_and_roads.md @@ -37,21 +37,7 @@ All infrastructure that someone can cycle over, accompanied with questions about - [rainbow_crossings](https://mapcomplete.osm.be/rainbow_crossings) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=cycleway|cycleway=lane|cycleway=shared_lane|cycleway=track|cyclestreet=yes|highway=residential|highway=tertiary|highway=unclassified|highway=primary|highway=secondary|highway=tertiary_link|highway=primary_link|highway=secondary_link|highway=service|highway=footway|highway=pedestrian|highway=living_street|highway=path&bicycle=designated - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22cyclestreet%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22cycleway%22%3D%22lane%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22cycleway%22%3D%22shared_lane%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22cycleway%22%3D%22track%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22cycleway%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22residential%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22tertiary%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22unclassified%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22primary%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22secondary%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22tertiary_link%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22primary_link%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22secondary_link%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22service%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22footway%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22pedestrian%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22living_street%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22bicycle%22%3D%22designated%22%5D%5B%22highway%22%3D%22path%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -68,6 +54,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/cycleway#values) [cycleway](https://wiki.openstreetmap.org/wiki/Key:cycleway) | Multiple choice | [shared_lane](https://wiki.openstreetmap.org/wiki/Tag:cycleway%3Dshared_lane) [lane](https://wiki.openstreetmap.org/wiki/Tag:cycleway%3Dlane) [track](https://wiki.openstreetmap.org/wiki/Tag:cycleway%3Dtrack) [separate](https://wiki.openstreetmap.org/wiki/Tag:cycleway%3Dseparate) [no](https://wiki.openstreetmap.org/wiki/Tag:cycleway%3Dno) [no](https://wiki.openstreetmap.org/wiki/Tag:cycleway%3Dno) [](https://taginfo.openstreetmap.org/keys/lit#values) [lit](https://wiki.openstreetmap.org/wiki/Key:lit) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dno) [24/7](https://wiki.openstreetmap.org/wiki/Tag:lit%3D24/7) [](https://taginfo.openstreetmap.org/keys/cyclestreet#values) [cyclestreet](https://wiki.openstreetmap.org/wiki/Key:cyclestreet) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3Dyes) [yes](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3Dyes) [](https://wiki.openstreetmap.org/wiki/Tag:cyclestreet%3D) @@ -86,6 +73,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### Cycleway type for a road @@ -419,6 +425,62 @@ The question is *How is this cycleway separated from the road?* - *This cycleway is separated by a kerb* corresponds with `separation=kerb` -This tagrendering is only visible in the popup if the following condition is met: `highway=cycleway|highway=path` +This tagrendering is only visible in the popup if the following condition is met: `highway=cycleway|highway=path` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### split-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/cycleways_and_roads/cycleways_and_roads.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/cycleways_and_roads/cycleways_and_roads.json) diff --git a/Docs/Layers/defibrillator.md b/Docs/Layers/defibrillator.md index 17f1481f4..fab162e0e 100644 --- a/Docs/Layers/defibrillator.md +++ b/Docs/Layers/defibrillator.md @@ -5,7 +5,7 @@ - + A layer showing defibrillators which can be used in case of emergency. This contains public defibrillators, but also defibrillators which might need staff to fetch the actual device @@ -30,21 +30,7 @@ A layer showing defibrillators which can be used in case of emergency. This cont - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - emergency=defibrillator - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22emergency%22%3D%22defibrillator%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/indoor#values) [indoor](https://wiki.openstreetmap.org/wiki/Key:indoor) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:indoor%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:indoor%3Dno) [](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | [string](../SpecialInputElements.md#string) | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [private](https://wiki.openstreetmap.org/wiki/Tag:access%3Dprivate) [no](https://wiki.openstreetmap.org/wiki/Tag:access%3Dno) [](https://taginfo.openstreetmap.org/keys/defibrillator#values) [defibrillator](https://wiki.openstreetmap.org/wiki/Key:defibrillator) | Multiple choice | [manual](https://wiki.openstreetmap.org/wiki/Tag:defibrillator%3Dmanual) [automatic](https://wiki.openstreetmap.org/wiki/Tag:defibrillator%3Dautomatic) @@ -80,6 +67,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -344,6 +350,72 @@ This is rendered with `Extra information for OpenStreetMap experts: {fixme}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/dentist.md b/Docs/Layers/dentist.md index 78addb66b..47da7add6 100644 --- a/Docs/Layers/dentist.md +++ b/Docs/Layers/dentist.md @@ -29,21 +29,7 @@ This layer shows dentist offices - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=dentist - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22dentist%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -69,6 +56,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -175,6 +181,72 @@ This is rendered with `This dentist is called {name}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/direction.md b/Docs/Layers/direction.md index 9b419f3a8..723f341c4 100644 --- a/Docs/Layers/direction.md +++ b/Docs/Layers/direction.md @@ -1,4 +1,4 @@ - +[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources) direction =========== @@ -15,7 +15,7 @@ This layer visualizes directions - This layer is shown at zoomlevel **16** and higher - - This layer cannot be toggled in the filter view. 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. @@ -30,27 +30,89 @@ This layer visualizes directions - [surveillance](https://mapcomplete.osm.be/surveillance) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - camera:direction~^..*$|direction~^..*$ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22camera%3Adirection%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22direction%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap Supported attributes ---------------------- + + +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + -This document is autogenerated from [assets/layers/direction/direction.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/direction/direction.json) \ No newline at end of file +This document is autogenerated from [assets/layers/direction/direction.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/direction/direction.json) diff --git a/Docs/Layers/doctors.md b/Docs/Layers/doctors.md index 0ca0712ee..d230498d7 100644 --- a/Docs/Layers/doctors.md +++ b/Docs/Layers/doctors.md @@ -30,21 +30,7 @@ This layer shows doctor offices - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=doctors - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22doctors%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | ["by appointment"](https://wiki.openstreetmap.org/wiki/Tag:opening_hours%3D"by appointment") [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | @@ -71,6 +58,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -206,6 +212,72 @@ This is rendered with `This doctor is specialized in {healthcare:speciality}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/dogfoodb.md b/Docs/Layers/dogfoodb.md index 8d26a6d0a..436541f5d 100644 --- a/Docs/Layers/dogfoodb.md +++ b/Docs/Layers/dogfoodb.md @@ -28,22 +28,7 @@ A layer showing restaurants and fast-food amenities (with a special rendering fo - [pets](https://mapcomplete.osm.be/pets) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=restaurant|amenity=cafe - - dog=unleashed|dog=leashed|dog=yes - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D%5B%22dog%22%3D%22unleashed%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D%5B%22dog%22%3D%22leashed%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D%5B%22dog%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cafe%22%5D%5B%22dog%22%3D%22unleashed%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cafe%22%5D%5B%22dog%22%3D%22leashed%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22cafe%22%5D%5B%22dog%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +45,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](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) @@ -90,6 +76,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -634,12 +639,10 @@ This tagrendering has no question and is thus read-only -### questions +### leftover-questions -Show the images block at this location - This tagrendering has no question and is thus read-only @@ -658,6 +661,50 @@ This tagrendering has no question and is thus read-only +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/dogpark.md b/Docs/Layers/dogpark.md index 926785ecd..030baa339 100644 --- a/Docs/Layers/dogpark.md +++ b/Docs/Layers/dogpark.md @@ -29,21 +29,7 @@ A layer showing dogparks, which are areas where dog are allowed to run without a - [pets](https://mapcomplete.osm.be/pets) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=dog_park|leisure=park&dog=unleashed - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22dog_park%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22dog%22%3D%22unleashed%22%5D%5B%22leisure%22%3D%22park%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/barrier#values) [barrier](https://wiki.openstreetmap.org/wiki/Key:barrier) | Multiple choice | [fence](https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dfence) [no](https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dno) [](https://taginfo.openstreetmap.org/keys/small_dog#values) [small_dog](https://wiki.openstreetmap.org/wiki/Key:small_dog) | Multiple choice | [separate](https://wiki.openstreetmap.org/wiki/Tag:small_dog%3Dseparate) [shared](https://wiki.openstreetmap.org/wiki/Tag:small_dog%3Dshared) [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | @@ -67,6 +54,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### dogpark-fenced @@ -143,6 +149,52 @@ This block shows the known images which are linked with the `image`-keys, but al This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/dogpark/dogpark.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/dogpark/dogpark.json) diff --git a/Docs/Layers/dogshop.md b/Docs/Layers/dogshop.md index c38ce6f4c..6207656e5 100644 --- a/Docs/Layers/dogshop.md +++ b/Docs/Layers/dogshop.md @@ -14,7 +14,7 @@ A shop - - This layer is shown at zoomlevel **16** and higher + - This layer is shown at zoomlevel **12** and higher @@ -28,22 +28,7 @@ A shop - [pets](https://mapcomplete.osm.be/pets) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - shop~.+ - - dog=leashed|dog=yes|shop=pet - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22dog%22%3D%22leashed%22%5D%5B%22shop%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22dog%22%3D%22yes%22%5D%5B%22shop%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22shop%22%3D%22pet%22%5D%5B%22shop%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,8 +45,8 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/shop#values) [shop](https://wiki.openstreetmap.org/wiki/Key:shop) | [string](../SpecialInputElements.md#string) | [agrarian](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dagrarian) [alcohol](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dalcohol) [anime](https://wiki.openstreetmap.org/wiki/Tag:shop%3Danime) [antiques](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dantiques) [appliance](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dappliance) [art](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dart) [baby_goods](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbaby_goods) [bag](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbag) [bakery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbakery) [bathroom_furnishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbathroom_furnishing) [beauty](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeauty) [bed](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbed) [beverages](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeverages) [bicycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbicycle) [boat](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dboat) [bookmaker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbookmaker) [books](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbooks) [brewing_supplies](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbrewing_supplies) [butcher](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbutcher) [camera](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcamera) [candles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcandles) [cannabis](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcannabis) [car](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar) [car_parts](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_parts) [car_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_repair) [caravan](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcaravan) [carpet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcarpet) [catalogue](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcatalogue) [charity](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcharity) [cheese](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcheese) [chemist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchemist) [chocolate](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchocolate) [clothes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dclothes) [coffee](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcoffee) [collector](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcollector) [computer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcomputer) [confectionery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconfectionery) [convenience](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconvenience) [copyshop](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcopyshop) [cosmetics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcosmetics) [country_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcountry_store) [craft](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcraft) [curtain](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcurtain) [dairy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddairy) [deli](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddeli) [department_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddepartment_store) [doityourself](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoityourself) [doors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoors) [dry_cleaning](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddry_cleaning) [e-cigarette](https://wiki.openstreetmap.org/wiki/Tag:shop%3De-cigarette) [electrical](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectrical) [electronics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectronics) [erotic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Derotic) [fabric](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfabric) [farm](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfarm) [fashion_accessories](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfashion_accessories) [fireplace](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfireplace) [fishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfishing) [flooring](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflooring) [florist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflorist) [frame](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dframe) [frozen_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfrozen_food) [fuel](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuel) [funeral_directors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuneral_directors) [furniture](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfurniture) [games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgames) [garden_centre](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgarden_centre) [gas](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgas) [general](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgeneral) [gift](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgift) [greengrocer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgreengrocer) [hairdresser](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser) [hairdresser_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser_supply) [hardware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhardware) [health_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhealth_food) [hearing_aids](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhearing_aids) [herbalist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dherbalist) [hifi](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhifi) [hobby](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhobby) [household_linen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhousehold_linen) [houseware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhouseware) [hunting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhunting) [interior_decoration](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dinterior_decoration) [jewelry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Djewelry) [kiosk](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkiosk) [kitchen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkitchen) [laundry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlaundry) [leather](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dleather) [lighting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlighting) [locksmith](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlocksmith) [lottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlottery) [mall](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmall) [massage](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmassage) [medical_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmedical_supply) [military_surplus](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmilitary_surplus) [mobile_phone](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmobile_phone) [model](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmodel) [money_lender](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmoney_lender) [motorcycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle) [motorcycle_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle_repair) [music](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusic) [musical_instrument](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusical_instrument) [newsagent](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnewsagent) [nutrition_supplements](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnutrition_supplements) [optician](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doptician) [outdoor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutdoor) [outpost](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutpost) [paint](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpaint) [party](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dparty) [pastry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpastry) [pawnbroker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpawnbroker) [perfumery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dperfumery) [pet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet) [pet_grooming](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet_grooming) [photo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dphoto) [pottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpottery) [printer_ink](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dprinter_ink) [psychic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpsychic) [pyrotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpyrotechnics) [radiotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dradiotechnics) [religion](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dreligion) [rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drental) [repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drepair) [scuba_diving](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dscuba_diving) [seafood](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dseafood) [second_hand](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsecond_hand) [sewing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsewing) [shoe_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoe_repair) [shoes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoes) [spices](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dspices) [sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsports) [stationery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstationery) [storage_rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstorage_rental) [supermarket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsupermarket) [swimming_pool](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dswimming_pool) [tailor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtailor) [tattoo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtattoo) [tea](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtea) [telecommunication](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtelecommunication) [ticket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dticket) [tiles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtiles) [tobacco](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtobacco) [tool_hire](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtool_hire) [toys](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtoys) [trade](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrade) [travel_agency](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtravel_agency) [trophy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrophy) [tyres](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtyres) [vacuum_cleaner](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvacuum_cleaner) [variety_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvariety_store) [video](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo) [video_games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo_games) [watches](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwatches) [water](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater) [water_sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater_sports) [weapons](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dweapons) [wholesale](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwholesale) [wigs](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwigs) [window_blind](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwindow_blind) [wine](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwine) [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -75,6 +60,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -101,184 +105,6 @@ This is rendered with `This shop is called {name}` -### shop_types - - - -The question is *What kind of shop is this?* - -This rendering asks information about the property [shop](https://wiki.openstreetmap.org/wiki/Key:shop) - -This is rendered with `This is a {shop}` - - - - - - - *Farm Supply Shop* corresponds with `shop=agrarian` - - *Liquor Store* corresponds with `shop=alcohol` - - *Anime / Manga Shop* corresponds with `shop=anime` - - *Antiques Shop* corresponds with `shop=antiques` - - *Appliance Store* corresponds with `shop=appliance` - - *Art Store* corresponds with `shop=art` - - *Baby Goods Store* corresponds with `shop=baby_goods` - - *Bag/Luggage Store* corresponds with `shop=bag` - - *Bakery* corresponds with `shop=bakery` - - *Bathroom Furnishing Store* corresponds with `shop=bathroom_furnishing` - - *Beauty Shop* corresponds with `shop=beauty` - - *Bedding/Mattress Store* corresponds with `shop=bed` - - *Beverage Store* corresponds with `shop=beverages` - - *Bicycle Shop* corresponds with `shop=bicycle` - - *Boat Store* corresponds with `shop=boat` - - *Bookmaker* corresponds with `shop=bookmaker` - - *Book Store* corresponds with `shop=books` - - *Brewing Supply Store* corresponds with `shop=brewing_supplies` - - *Butcher* corresponds with `shop=butcher` - - *Camera Equipment Store* corresponds with `shop=camera` - - *Candle Shop* corresponds with `shop=candles` - - *Cannabis Shop* corresponds with `shop=cannabis` - - *Car Dealership* corresponds with `shop=car` - - *Car Parts Store* corresponds with `shop=car_parts` - - *Car Repair Shop* corresponds with `shop=car_repair` - - *RV Dealership* corresponds with `shop=caravan` - - *Carpet Store* corresponds with `shop=carpet` - - *Catalog Shop* corresponds with `shop=catalogue` - - *Charity Store* corresponds with `shop=charity` - - *Cheese Store* corresponds with `shop=cheese` - - *Drugstore* corresponds with `shop=chemist` - - *Chocolate Store* corresponds with `shop=chocolate` - - *Clothing Store* corresponds with `shop=clothes` - - *Coffee Store* corresponds with `shop=coffee` - - *Collectibles Shop* corresponds with `shop=collector` - - *Computer Store* corresponds with `shop=computer` - - *Candy Store* corresponds with `shop=confectionery` - - *Convenience Store* corresponds with `shop=convenience` - - *Copy Store* corresponds with `shop=copyshop` - - *Cosmetics Store* corresponds with `shop=cosmetics` - - *Country Store* corresponds with `shop=country_store` - - *Arts & Crafts Store* corresponds with `shop=craft` - - *Curtain Store* corresponds with `shop=curtain` - - *Dairy Store* corresponds with `shop=dairy` - - *Deli* corresponds with `shop=deli` - - *Department Store* corresponds with `shop=department_store` - - *DIY Store* corresponds with `shop=doityourself` - - *Door Shop* corresponds with `shop=doors` - - *Dry Cleaner* corresponds with `shop=dry_cleaning` - - *E-Cigarette Shop* corresponds with `shop=e-cigarette` - - *Electrical Equipment Store* corresponds with `shop=electrical` - - *Electronics Store* corresponds with `shop=electronics` - - *Erotic Store* corresponds with `shop=erotic` - - *Fabric Store* corresponds with `shop=fabric` - - *Produce Stand* corresponds with `shop=farm` - - *Fashion Accessories Store* corresponds with `shop=fashion_accessories` - - *Fireplace Store* corresponds with `shop=fireplace` - - *Fishing Shop* corresponds with `shop=fishing` - - *Flooring Supply Shop* corresponds with `shop=flooring` - - *Florist* corresponds with `shop=florist` - - *Framing Shop* corresponds with `shop=frame` - - *Frozen Food Store* corresponds with `shop=frozen_food` - - *Fuel Shop* corresponds with `shop=fuel` - - *Funeral Home* corresponds with `shop=funeral_directors` - - *Furniture Store* corresponds with `shop=furniture` - - *Tabletop Game Store* corresponds with `shop=games` - - *Garden Center* corresponds with `shop=garden_centre` - - *Bottled Gas Shop* corresponds with `shop=gas` - - *General Store* corresponds with `shop=general` - - *Gift Shop* corresponds with `shop=gift` - - *Greengrocer* corresponds with `shop=greengrocer` - - *Hairdresser* corresponds with `shop=hairdresser` - - *Hairdresser Supply Store* corresponds with `shop=hairdresser_supply` - - *Hardware Store* corresponds with `shop=hardware` - - *Health Food Shop* corresponds with `shop=health_food` - - *Hearing Aids Store* corresponds with `shop=hearing_aids` - - *Herbalist* corresponds with `shop=herbalist` - - *Hifi Store* corresponds with `shop=hifi` - - *Hobby Shop* corresponds with `shop=hobby` - - *Household Linen Shop* corresponds with `shop=household_linen` - - *Houseware Store* corresponds with `shop=houseware` - - *Hunting Shop* corresponds with `shop=hunting` - - *Interior Decoration Store* corresponds with `shop=interior_decoration` - - *Jewelry Store* corresponds with `shop=jewelry` - - *Kiosk* corresponds with `shop=kiosk` - - *Kitchen Design Store* corresponds with `shop=kitchen` - - *Laundry* corresponds with `shop=laundry` - - *Leather Store* corresponds with `shop=leather` - - *Lighting Store* corresponds with `shop=lighting` - - *Locksmith* corresponds with `shop=locksmith` - - *Lottery Shop* corresponds with `shop=lottery` - - *Mall* corresponds with `shop=mall` - - *Massage Shop* corresponds with `shop=massage` - - *Medical Supply Store* corresponds with `shop=medical_supply` - - *Military Surplus Store* corresponds with `shop=military_surplus` - - *Mobile Phone Store* corresponds with `shop=mobile_phone` - - *Model Shop* corresponds with `shop=model` - - *Money Lender* corresponds with `shop=money_lender` - - *Motorcycle Dealership* corresponds with `shop=motorcycle` - - *Motorcycle Repair Shop* corresponds with `shop=motorcycle_repair` - - *Music Store* corresponds with `shop=music` - - *Musical Instrument Store* corresponds with `shop=musical_instrument` - - *Newspaper/Magazine Shop* corresponds with `shop=newsagent` - - *Nutrition Supplements Store* corresponds with `shop=nutrition_supplements` - - *Optician* corresponds with `shop=optician` - - *Outdoors Store* corresponds with `shop=outdoor` - - *Online Retailer Outpost* corresponds with `shop=outpost` - - *Paint Store* corresponds with `shop=paint` - - *Party Supply Store* corresponds with `shop=party` - - *Pastry Shop* corresponds with `shop=pastry` - - *Pawn Shop* corresponds with `shop=pawnbroker` - - *Perfume Store* corresponds with `shop=perfumery` - - *Pet Store* corresponds with `shop=pet` - - *Pet Grooming Store* corresponds with `shop=pet_grooming` - - *Photography Store* corresponds with `shop=photo` - - *Pottery Store* corresponds with `shop=pottery` - - *Printer Ink Store* corresponds with `shop=printer_ink` - - *Psychic* corresponds with `shop=psychic` - - *Fireworks Store* corresponds with `shop=pyrotechnics` - - *Radio/Electronic Component Store* corresponds with `shop=radiotechnics` - - *Religious Store* corresponds with `shop=religion` - - *Rental Shop* corresponds with `shop=rental` - - *Repair Shop* corresponds with `shop=repair` - - *Scuba Diving Shop* corresponds with `shop=scuba_diving` - - *Seafood Shop* corresponds with `shop=seafood` - - *Consignment/Thrift Store* corresponds with `shop=second_hand` - - *Sewing Supply Shop* corresponds with `shop=sewing` - - *Shoe Repair Shop* corresponds with `shop=shoe_repair` - - *Shoe Store* corresponds with `shop=shoes` - - *Spice Shop* corresponds with `shop=spices` - - *Sporting Goods Store* corresponds with `shop=sports` - - *Stationery Store* corresponds with `shop=stationery` - - *Storage Rental* corresponds with `shop=storage_rental` - - *Supermarket* corresponds with `shop=supermarket` - - *Pool Supply Store* corresponds with `shop=swimming_pool` - - *Tailor* corresponds with `shop=tailor` - - *Tattoo Parlor* corresponds with `shop=tattoo` - - *Tea Store* corresponds with `shop=tea` - - *Telecom Retail Store* corresponds with `shop=telecommunication` - - *Ticket Seller* corresponds with `shop=ticket` - - *Tile Shop* corresponds with `shop=tiles` - - *Tobacco Shop* corresponds with `shop=tobacco` - - *Tool Rental* corresponds with `shop=tool_hire` - - *Toy Store* corresponds with `shop=toys` - - *Trade Shop* corresponds with `shop=trade` - - *Travel Agency* corresponds with `shop=travel_agency` - - *Trophy Shop* corresponds with `shop=trophy` - - *Tire Store* corresponds with `shop=tyres` - - *Vacuum Cleaner Store* corresponds with `shop=vacuum_cleaner` - - *Variety Store* corresponds with `shop=variety_store` - - *Video Store* corresponds with `shop=video` - - *Video Game Store* corresponds with `shop=video_games` - - *Watches Shop* corresponds with `shop=watches` - - *Drinking Water Shop* corresponds with `shop=water` - - *Watersport/Swim Shop* corresponds with `shop=water_sports` - - *Weapon Shop* corresponds with `shop=weapons` - - *Wholesale Store* corresponds with `shop=wholesale` - - *Wig Shop* corresponds with `shop=wigs` - - *Window Blind Store* corresponds with `shop=window_blind` - - *Wine Shop* corresponds with `shop=wine` - - - - ### opening_hours @@ -513,6 +339,8 @@ This tagrendering is only visible in the popup if the following condition is met +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -531,11 +359,11 @@ This tagrendering has no question and is thus read-only -### questions +### minimap -Show the images block at this location +Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only @@ -543,11 +371,43 @@ This tagrendering has no question and is thus read-only -### minimap +### move-button -Shows a small map with the feature. Added by default to every popup +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + This tagrendering has no question and is thus read-only diff --git a/Docs/Layers/drinking_water.md b/Docs/Layers/drinking_water.md index f2e4121ac..a85ce7bf0 100644 --- a/Docs/Layers/drinking_water.md +++ b/Docs/Layers/drinking_water.md @@ -33,24 +33,7 @@ A layer showing drinking water fountains - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=drinking_water|drinking_water=yes - - man_made!=reservoir_covered - - access!=permissive - - access!=private - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22drinking_water%22%5D%5B%22man_made%22!%3D%22reservoir_covered%22%5D%5B%22access%22!%3D%22permissive%22%5D%5B%22access%22!%3D%22private%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22drinking_water%22%3D%22yes%22%5D%5B%22man_made%22!%3D%22reservoir_covered%22%5D%5B%22access%22!%3D%22permissive%22%5D%5B%22access%22!%3D%22private%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -67,12 +50,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/operational_status#values) [operational_status](https://wiki.openstreetmap.org/wiki/Key:operational_status) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:operational_status%3D) [broken](https://wiki.openstreetmap.org/wiki/Tag:operational_status%3Dbroken) [closed](https://wiki.openstreetmap.org/wiki/Tag:operational_status%3Dclosed) [](https://taginfo.openstreetmap.org/keys/bottle#values) [bottle](https://wiki.openstreetmap.org/wiki/Key:bottle) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:bottle%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:bottle%3Dno) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -130,6 +133,72 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `_closest_other_drinking_water_id~.+` +This tagrendering is only visible in the popup if the following condition is met: `_closest_other_drinking_water_id~.+` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/drinking_water/drinking_water.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/drinking_water/drinking_water.json) diff --git a/Docs/Layers/dumpstations.md b/Docs/Layers/dumpstations.md index 119296efe..806216a7d 100644 --- a/Docs/Layers/dumpstations.md +++ b/Docs/Layers/dumpstations.md @@ -28,22 +28,7 @@ Sanitary dump stations - [campersite](https://mapcomplete.osm.be/campersite) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=sanitary_dump_station - - vehicle!~^(no)$ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22sanitary_dump_station%22%5D%5B%22vehicle%22!~%22%5E(no)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +45,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/fee#values) [fee](https://wiki.openstreetmap.org/wiki/Key:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dno) [](https://taginfo.openstreetmap.org/keys/charge#values) [charge](https://wiki.openstreetmap.org/wiki/Key:charge) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/water_point#values) [water_point](https://wiki.openstreetmap.org/wiki/Key:water_point) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:water_point%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:water_point%3Dno) @@ -73,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -198,6 +203,52 @@ This is rendered with `This station is part of network {network}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + ### operator @@ -224,30 +275,6 @@ The question is *Does this place have a power supply?* - *This place has a power supply* corresponds with `power_supply=yes` - *This place does not have power supply* corresponds with `power_supply=no` - - - - -### questions - - - -Show the images block at this location - -This tagrendering has no question and is thus read-only - - - - - -### minimap - - - -Shows a small map with the feature. Added by default to every popup - -This tagrendering has no question and is thus read-only - This document is autogenerated from [assets/themes/campersite/campersite.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/campersite/campersite.json) diff --git a/Docs/Layers/education_institutions_without_etymology.md b/Docs/Layers/education_institutions_without_etymology.md index a4c84324c..b4ecfc82c 100644 --- a/Docs/Layers/education_institutions_without_etymology.md +++ b/Docs/Layers/education_institutions_without_etymology.md @@ -28,22 +28,7 @@ All objects which have an etymology known - [etymology](https://mapcomplete.osm.be/etymology) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - name~.+ - - amenity=school|amenity=kindergarten|amenity=university|amenity=college|landuse=education - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22school%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22kindergarten%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22university%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22college%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22landuse%22%3D%22education%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +45,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) | [](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### etymology-images-from-wikipedia @@ -125,6 +130,8 @@ This is rendered with `Named after {name:etymology}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -169,6 +176,30 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` +This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) diff --git a/Docs/Layers/elevator.md b/Docs/Layers/elevator.md index 34a8f87d5..c57ea45c3 100644 --- a/Docs/Layers/elevator.md +++ b/Docs/Layers/elevator.md @@ -31,21 +31,7 @@ This layer show elevators and asks for operational status and elevator dimension - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=elevator - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22elevator%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,6 +48,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/level#values) [level](https://wiki.openstreetmap.org/wiki/Key:level) | [string](../SpecialInputElements.md#string) | [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) [](https://taginfo.openstreetmap.org/keys/operational_status#values) [operational_status](https://wiki.openstreetmap.org/wiki/Key:operational_status) | Multiple choice | [broken](https://wiki.openstreetmap.org/wiki/Tag:operational_status%3Dbroken) [closed](https://wiki.openstreetmap.org/wiki/Tag:operational_status%3Dclosed) [ok](https://wiki.openstreetmap.org/wiki/Tag:operational_status%3Dok) [](https://taginfo.openstreetmap.org/keys/door:width#values) [door:width](https://wiki.openstreetmap.org/wiki/Key:door:width) | [pfloat](../SpecialInputElements.md#pfloat) | @@ -72,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -204,6 +210,52 @@ This tagrendering has no question and is thus read-only This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/elevator/elevator.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/elevator/elevator.json) diff --git a/Docs/Layers/entrance.md b/Docs/Layers/entrance.md index 3e2d67c48..0b9af8b9a 100644 --- a/Docs/Layers/entrance.md +++ b/Docs/Layers/entrance.md @@ -34,21 +34,7 @@ A layer showing entrances and offering capabilities to survey some advanced data - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - entrance~.+|indoor=door|door~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22indoor%22%3D%22door%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22door%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22entrance%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -65,6 +51,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/entrance#values) [entrance](https://wiki.openstreetmap.org/wiki/Key:entrance) | Multiple choice | [](https://wiki.openstreetmap.org/wiki/Tag:entrance%3D) [main](https://wiki.openstreetmap.org/wiki/Tag:entrance%3Dmain) [secondary](https://wiki.openstreetmap.org/wiki/Tag:entrance%3Dsecondary) [service](https://wiki.openstreetmap.org/wiki/Tag:entrance%3Dservice) [exit](https://wiki.openstreetmap.org/wiki/Tag:entrance%3Dexit) [entrance](https://wiki.openstreetmap.org/wiki/Tag:entrance%3Dentrance) [emergency](https://wiki.openstreetmap.org/wiki/Tag:entrance%3Demergency) [home](https://wiki.openstreetmap.org/wiki/Tag:entrance%3Dhome) [](https://taginfo.openstreetmap.org/keys/door#values) [door](https://wiki.openstreetmap.org/wiki/Key:door) | Multiple choice | [hinged](https://wiki.openstreetmap.org/wiki/Tag:door%3Dhinged) [revolving](https://wiki.openstreetmap.org/wiki/Tag:door%3Drevolving) [sliding](https://wiki.openstreetmap.org/wiki/Tag:door%3Dsliding) [overhead](https://wiki.openstreetmap.org/wiki/Tag:door%3Doverhead) [no](https://wiki.openstreetmap.org/wiki/Tag:door%3Dno) @@ -75,6 +62,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -210,6 +216,52 @@ This is rendered with `The kerb height of this door is {kerb:height}` - *This door does not have a kerb* corresponds with `kerb:height=0` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/entrance/entrance.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/entrance/entrance.json) diff --git a/Docs/Layers/etymology.md b/Docs/Layers/etymology.md index b1c6c3078..acfb8150a 100644 --- a/Docs/Layers/etymology.md +++ b/Docs/Layers/etymology.md @@ -29,21 +29,7 @@ All objects which have an etymology known - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - name:etymology:wikidata~.+|name:etymology~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22name%3Aetymology%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22name%3Aetymology%3Awikidata%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +46,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) | [](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### etymology-images-from-wikipedia @@ -125,6 +131,8 @@ This is rendered with `Named after {name:etymology}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -169,6 +177,30 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` +This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/etymology/etymology.json) diff --git a/Docs/Layers/extinguisher.md b/Docs/Layers/extinguisher.md index 1b77936a7..9880f4aa2 100644 --- a/Docs/Layers/extinguisher.md +++ b/Docs/Layers/extinguisher.md @@ -29,21 +29,7 @@ Map layer to show fire extinguishers. - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - emergency=fire_extinguisher - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22emergency%22%3D%22fire_extinguisher%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,11 +46,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/location#values) [location](https://wiki.openstreetmap.org/wiki/Key:location) | [string](../SpecialInputElements.md#string) | [indoor](https://wiki.openstreetmap.org/wiki/Tag:location%3Dindoor) [outdoor](https://wiki.openstreetmap.org/wiki/Tag:location%3Doutdoor) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### extinguisher-location @@ -93,6 +99,52 @@ This block shows the known images which are linked with the `image`-keys, but al This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/extinguisher/extinguisher.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/extinguisher/extinguisher.json) diff --git a/Docs/Layers/facadegardens.md b/Docs/Layers/facadegardens.md index 574d446b0..c1f297172 100644 --- a/Docs/Layers/facadegardens.md +++ b/Docs/Layers/facadegardens.md @@ -28,22 +28,7 @@ Facade gardens - [facadegardens](https://mapcomplete.osm.be/facadegardens) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=garden - - garden:type=facade_garden - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22garden%3Atype%22%3D%22facade_garden%22%5D%5B%22leisure%22%3D%22garden%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +45,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/direction#values) [direction](https://wiki.openstreetmap.org/wiki/Key:direction) | [direction](../SpecialInputElements.md#direction) | [](https://taginfo.openstreetmap.org/keys/direct_sunlight#values) [direct_sunlight](https://wiki.openstreetmap.org/wiki/Key:direct_sunlight) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:direct_sunlight%3Dyes) [partial](https://wiki.openstreetmap.org/wiki/Tag:direct_sunlight%3Dpartial) [no](https://wiki.openstreetmap.org/wiki/Tag:direct_sunlight%3Dno) [](https://taginfo.openstreetmap.org/keys/rain_barrel#values) [rain_barrel](https://wiki.openstreetmap.org/wiki/Key:rain_barrel) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:rain_barrel%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:rain_barrel%3Dno) @@ -71,6 +57,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -192,12 +197,10 @@ This is rendered with `More details: {description}` -### questions +### leftover-questions -Show the images block at this location - This tagrendering has no question and is thus read-only @@ -212,6 +215,50 @@ Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/themes/facadegardens/facadegardens.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/facadegardens/facadegardens.json) diff --git a/Docs/Layers/fietsstraat.md b/Docs/Layers/fietsstraat.md index b540f4b06..bb706e542 100644 --- a/Docs/Layers/fietsstraat.md +++ b/Docs/Layers/fietsstraat.md @@ -28,21 +28,7 @@ A cyclestreet is a street where motorized traffic is not allowed to overtake a c - [cyclestreets](https://mapcomplete.osm.be/cyclestreets) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - cyclestreet=yes|bicycle_road=yes - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22bicycle_road%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22cyclestreet%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,18 +47,7 @@ attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ [](https://taginfo.openstreetmap.org/keys/traffic_sign#values) [traffic_sign](https://wiki.openstreetmap.org/wiki/Key:traffic_sign) | Multiple choice | [DE:244.1,1020-30](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1020-30) [DE:244.1,1022-12,1024-10](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1022-12,1024-10) [DE:244.1,1022-12](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1022-12) [DE:244.1,1024-10](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1024-10) [DE:244.1](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1) [](https://taginfo.openstreetmap.org/keys/cyclestreet:start_date#values) [cyclestreet:start_date](https://wiki.openstreetmap.org/wiki/Key:cyclestreet:start_date) | [date](../SpecialInputElements.md#date) | - - - - -### images - - - -This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` - -This tagrendering has no question and is thus read-only - +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | @@ -136,11 +111,40 @@ This tagrendering is only visible in the popup if the following condition is met -### questions +### just_created -Show the images block at this location +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### images + + + +This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` + +This tagrendering has no question and is thus read-only + + + + + +### leftover-questions + + This tagrendering has no question and is thus read-only @@ -156,6 +160,40 @@ Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + +### split-button + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/themes/cyclestreets/cyclestreets.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/cyclestreets/cyclestreets.json) diff --git a/Docs/Layers/filters.md b/Docs/Layers/filters.md deleted file mode 100644 index 2f3374afe..000000000 --- a/Docs/Layers/filters.md +++ /dev/null @@ -1,106 +0,0 @@ -[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources) - - filters -========= - - - - - -This layer acts as library for common filters - - - - - - - - This layer is shown at zoomlevel **0** and higher - - 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. - - 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` - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - id~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22id%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - - - - Supported attributes ----------------------- - - - - - -#### Filters - - - - - -id | question | osmTags ----- | ---------- | --------- -open_now.0 | Open now | _isOpen=yes - - - - -id | question | osmTags ----- | ---------- | --------- -accepts_cash.0 | Accepts cash | payment:cash=yes - - - - -id | question | osmTags ----- | ---------- | --------- -accepts_cards.0 | Accepts payment cards | payment:cards=yes - - - - -id | question | osmTags ----- | ---------- | --------- -has_image.0 | With and without images (default) | -has_image.1 | Has at least one image | image~.+\|image:0~.+|image:1~.+|image:2~.+|image:3~.+|mapillary~.+ -has_image.2 | Probably does not have an image | - - - - -id | question | osmTags ----- | ---------- | --------- -tactile_paving.0 | With tactile paving | tactile_paving=yes - - - - -id | question | osmTags ----- | ---------- | --------- -tactile_paving_advanced.0 | With or without tactile paving (default) | -tactile_paving_advanced.1 | With tactile paving | tactile_paving=yes -tactile_paving_advanced.2 | Without tactile paving | tactile_paving=no -tactile_paving_advanced.3 | No information about tactile paving | - - - - -id | question | osmTags ----- | ---------- | --------- -has_organic.0 | Has organic options | organic=yes\|organic=only - - -This document is autogenerated from [assets/layers/filters/filters.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/filters/filters.json) diff --git a/Docs/Layers/fire_station.md b/Docs/Layers/fire_station.md index e17573f0e..bf361d2de 100644 --- a/Docs/Layers/fire_station.md +++ b/Docs/Layers/fire_station.md @@ -29,21 +29,7 @@ Map layer to show fire stations. - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=fire_station - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22fire_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/addr:street#values) [addr:street](https://wiki.openstreetmap.org/wiki/Key:addr:street) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/addr:place#values) [addr:place](https://wiki.openstreetmap.org/wiki/Key:addr:place) | [string](../SpecialInputElements.md#string) | @@ -69,6 +56,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### station-name @@ -160,6 +166,52 @@ This block shows the known images which are linked with the `image`-keys, but al This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/fire_station/fire_station.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/fire_station/fire_station.json) diff --git a/Docs/Layers/fitness_centre.md b/Docs/Layers/fitness_centre.md index 26cc98884..7800a8d8d 100644 --- a/Docs/Layers/fitness_centre.md +++ b/Docs/Layers/fitness_centre.md @@ -29,21 +29,7 @@ Layer showing fitness centres - [sports](https://mapcomplete.osm.be/sports) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=fitness_centre - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22fitness_centre%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -71,6 +58,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### name @@ -237,6 +243,52 @@ This tagrendering has no question and is thus read-only +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/fitness_station.md b/Docs/Layers/fitness_station.md index 4d717ae68..adb3a3881 100644 --- a/Docs/Layers/fitness_station.md +++ b/Docs/Layers/fitness_station.md @@ -29,21 +29,7 @@ Find a fitness station near you, and add missing ones. - [sports](https://mapcomplete.osm.be/sports) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=fitness_station - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22fitness_station%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/fitness_station#values) [fitness_station](https://wiki.openstreetmap.org/wiki/Key:fitness_station) | Multiple choice | [horizontal_bar](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dhorizontal_bar) [sign](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dsign) [sit-up](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dsit-up) [push-up](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dpush-up) [stretch_bars](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dstretch_bars) [hyperextension](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dhyperextension) [rings](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Drings) [horizontal_ladder](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dhorizontal_ladder) [wall_bars](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dwall_bars) [slalom](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dslalom) [stepping_stones](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dstepping_stones) [leapfrog](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dleapfrog) [beam_jump](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dbeam_jump) [hurdling](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dhurdling) [wall](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dwall) [balance_beam](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dbalance_beam) [log_lifting](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dlog_lifting) [captains_chair](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dcaptains_chair) [box](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dbox) [battling_ropes](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dbattling_ropes) [excercise_bike](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dexcercise_bike) [elliptical_trainer](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Delliptical_trainer) [air_walker](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dair_walker) [rower](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Drower) [slackline](https://wiki.openstreetmap.org/wiki/Tag:fitness_station%3Dslackline) [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | @@ -68,6 +55,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -171,6 +177,62 @@ This is rendered with `

Opening hours

{opening_hours_table(opening_hours +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/fixme.md b/Docs/Layers/fixme.md index 1cb129d24..cd5963c79 100644 --- a/Docs/Layers/fixme.md +++ b/Docs/Layers/fixme.md @@ -30,21 +30,7 @@ OSM objects that likely need to be fixed, based on a FIXME tag. - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - fixme~.+|FIXME~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22FIXME%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22fixme%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -53,6 +39,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### fixme @@ -85,6 +101,42 @@ Shows a table with all the tags of the feature This tagrendering has no question and is thus read-only - + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` This document is autogenerated from [assets/layers/fixme/fixme.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/fixme/fixme.json) diff --git a/Docs/Layers/food.md b/Docs/Layers/food.md index a340c43ee..f27a91d31 100644 --- a/Docs/Layers/food.md +++ b/Docs/Layers/food.md @@ -32,21 +32,7 @@ A layer showing restaurants and fast-food amenities (with a special rendering fo - [pets](https://mapcomplete.osm.be/pets) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=fast_food|amenity=restaurant - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22fast_food%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -63,6 +49,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](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) @@ -93,6 +80,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -637,6 +643,72 @@ This tagrendering has no question and is thus read-only +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/friture.md b/Docs/Layers/friture.md index 91dc9c9e6..bf88fc404 100644 --- a/Docs/Layers/friture.md +++ b/Docs/Layers/friture.md @@ -28,22 +28,7 @@ A layer showing restaurants and fast-food amenities (with a special rendering fo - [fritures](https://mapcomplete.osm.be/fritures) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - cuisine~^((.*;)?friture(;.*)?)$ - - amenity=fast_food|amenity=restaurant - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22fast_food%22%5D%5B%22cuisine%22~%22%5E((.*%3B)%3Ffriture(%3B.*)%3F)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22restaurant%22%5D%5B%22cuisine%22~%22%5E((.*%3B)%3Ffriture(%3B.*)%3F)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +45,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](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) @@ -90,6 +76,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -634,12 +639,10 @@ This tagrendering has no question and is thus read-only -### questions +### leftover-questions -Show the images block at this location - This tagrendering has no question and is thus read-only @@ -658,6 +661,50 @@ This tagrendering has no question and is thus read-only +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/ghost_bike.md b/Docs/Layers/ghost_bike.md index db5d1794c..c7feee4cb 100644 --- a/Docs/Layers/ghost_bike.md +++ b/Docs/Layers/ghost_bike.md @@ -29,21 +29,7 @@ A layer showing memorials for cyclists, killed in road accidents - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - memorial=ghost_bike - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22memorial%22%3D%22ghost_bike%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/source#values) [source](https://wiki.openstreetmap.org/wiki/Key:source) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/inscription#values) [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [string](../SpecialInputElements.md#string) | @@ -68,6 +55,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### ghost-bike-explanation @@ -147,6 +153,72 @@ This rendering asks information about the property [start_date](https://wiki.op This is rendered with `Placed on {start_date}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/ghost_bike/ghost_bike.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/ghost_bike/ghost_bike.json) diff --git a/Docs/Layers/governments.md b/Docs/Layers/governments.md index 202868ad6..fd889527a 100644 --- a/Docs/Layers/governments.md +++ b/Docs/Layers/governments.md @@ -29,21 +29,7 @@ This layer show governmental buildings. It was setup as commissioned layer for t - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - office=government - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22office%22%3D%22government%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | @@ -68,6 +55,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -156,6 +162,52 @@ This rendering asks information about the property [name](https://wiki.openstre This is rendered with `This Governmental Office is called {name}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/governments/governments.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/governments/governments.json) diff --git a/Docs/Layers/grass_in_parks.md b/Docs/Layers/grass_in_parks.md deleted file mode 100644 index d28cf4019..000000000 --- a/Docs/Layers/grass_in_parks.md +++ /dev/null @@ -1,75 +0,0 @@ -[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources) - - grass_in_parks -================ - - - - - -Searches for all accessible grass patches within public parks - these are 'groenzones' - - - - - - - - This layer is shown at zoomlevel **0** and higher - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - name=Park Oude God|landuse=grass&access=public|access=yes - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22name%22%3D%22Park%20Oude%20God%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22landuse%22%3D%22grass%22%5D%5B%22access%22%3D%22public%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22landuse%22%3D%22grass%22%5D%5B%22access%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - - - - Supported attributes ----------------------- - - - - - -### images - - - -This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` - -This tagrendering has no question and is thus read-only - - - - - -### explanation - - - -This tagrendering has no question and is thus read-only - - - - - -### grass-in-parks-reviews - - - -This tagrendering has no question and is thus read-only - - - -This document is autogenerated from [assets/layers/grass_in_parks/grass_in_parks.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/grass_in_parks/grass_in_parks.json) diff --git a/Docs/Layers/hackerspace.md b/Docs/Layers/hackerspace.md index 6cf750d48..c89f0d2bd 100644 --- a/Docs/Layers/hackerspace.md +++ b/Docs/Layers/hackerspace.md @@ -29,21 +29,7 @@ Hackerspace - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=hackerspace - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22hackerspace%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/hackerspace#values) [hackerspace](https://wiki.openstreetmap.org/wiki/Key:hackerspace) | Multiple choice | [makerspace](https://wiki.openstreetmap.org/wiki/Tag:hackerspace%3Dmakerspace) [](https://wiki.openstreetmap.org/wiki/Tag:hackerspace%3D) [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](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) @@ -77,6 +64,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -329,6 +335,8 @@ This is rendered with `This hackerspace was founded at {start_date}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -343,6 +351,62 @@ Shows the reviews module (including the possibility to leave a review) This tagrendering has no question and is thus read-only + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/hackerspace/hackerspace.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/hackerspace/hackerspace.json) diff --git a/Docs/Layers/hackerspaces.md b/Docs/Layers/hackerspaces.md deleted file mode 100644 index 3c0e8953d..000000000 --- a/Docs/Layers/hackerspaces.md +++ /dev/null @@ -1,227 +0,0 @@ - - - hackerspaces -============== - - - - - -Hackerspace - - - - - - - - This layer is shown at zoomlevel **8** and higher - - - - -#### Themes using this layer - - - - - - - [hackerspaces](https://mapcomplete.osm.be/hackerspaces) - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=hackerspace - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22hackerspace%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - - - - Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - - - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/hackerspace#values) [hackerspace](https://wiki.openstreetmap.org/wiki/Key:hackerspace) | Multiple choice | [makerspace](https://wiki.openstreetmap.org/wiki/Tag:hackerspace%3Dmakerspace) [](https://wiki.openstreetmap.org/wiki/Tag:hackerspace%3D) -[](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | -[](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | -[](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | -[](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [24/7](https://wiki.openstreetmap.org/wiki/Tag:opening_hours%3D24/7) -[](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) -[](https://taginfo.openstreetmap.org/keys/drink:club-mate#values) [drink:club-mate](https://wiki.openstreetmap.org/wiki/Key:drink:club-mate) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:drink:club-mate%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:drink:club-mate%3Dno) -[](https://taginfo.openstreetmap.org/keys/start_date#values) [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) | [date](../SpecialInputElements.md#date) | - - - - -### is_makerspace - - - -The question is **Is this a hackerspace or a makerspace?** - - - - - - - **This is a makerspace** corresponds with hackerspace=makerspace - - **This is a traditional (software oriented) hackerspace** corresponds with - - - - -### hackerspaces-name - - - -The question is **What is the name of this hackerspace?** - -This rendering asks information about the property [name](https://wiki.openstreetmap.org/wiki/Key:name) -This is rendered with `This hackerspace is named {name}` - - - -### website - - - -The question is **What is the website of {title()}?** - -This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website) -This is rendered with `{website}` - - - - - **{contact:website}** corresponds with contact:website~^..*$_This option cannot be chosen as answer_ - - - - -### email - - - -The question is **What is the email address of {title()}?** - -This rendering asks information about the property [email](https://wiki.openstreetmap.org/wiki/Key:email) -This is rendered with `{email}` - - - - - **{contact:email}** corresponds with contact:email~^..*$_This option cannot be chosen as answer_ - - - - -### phone - - - -The question is **What is the phone number of {title()}?** - -This rendering asks information about the property [phone](https://wiki.openstreetmap.org/wiki/Key:phone) -This is rendered with `{phone}` - - - - - **{contact:phone}** corresponds with contact:phone~^..*$_This option cannot be chosen as answer_ - - - - -### hackerspaces-opening_hours - - - -The question is **When is this hackerspace opened?** - -This rendering asks information about the property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) -This is rendered with `{opening_hours_table()}` - - - - - **Opened 24/7** corresponds with opening_hours=24/7 - - - - -### wheelchair-access - - - -The question is **Is this place accessible with a wheelchair?** - - - - - - - **This place is specially adapted for wheelchair users** corresponds with wheelchair=designated - - **This place is easily reachable with a wheelchair** corresponds with wheelchair=yes - - **It is possible to reach this place in a wheelchair, but it is not easy** corresponds with wheelchair=limited - - **This place is not reachable with a wheelchair** corresponds with wheelchair=no - - - - -### hs-club-mate - - - -The question is **Does this hackerspace serve Club Mate?** - - - - - - - **This hackerspace serves club mate** corresponds with drink:club-mate=yes - - **This hackerspace does not serve club mate** corresponds with drink:club-mate=no - - - - -### hackerspaces-start_date - - - -The question is **When was this hackerspace founded?** - -This rendering asks information about the property [start_date](https://wiki.openstreetmap.org/wiki/Key:start_date) -This is rendered with `This hackerspace was founded at {start_date}` - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - - - - -### minimap - - - -_This tagrendering has no question and is thus read-only_ - - - -This document is autogenerated from [assets/themes/hackerspaces/hackerspaces.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/hackerspaces/hackerspaces.json) \ No newline at end of file diff --git a/Docs/Layers/health_and_social_places_without_etymology.md b/Docs/Layers/health_and_social_places_without_etymology.md index fad8bc4ea..0db149153 100644 --- a/Docs/Layers/health_and_social_places_without_etymology.md +++ b/Docs/Layers/health_and_social_places_without_etymology.md @@ -28,22 +28,7 @@ All objects which have an etymology known - [etymology](https://mapcomplete.osm.be/etymology) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - name~.+ - - amenity=clinic|amenity=hospital|amenity=social_facility - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22clinic%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22hospital%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22social_facility%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +45,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) | [](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### etymology-images-from-wikipedia @@ -125,6 +130,8 @@ This is rendered with `Named after {name:etymology}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -169,6 +176,30 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` +This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) diff --git a/Docs/Layers/hospital.md b/Docs/Layers/hospital.md index 2b226fa17..87b55829a 100644 --- a/Docs/Layers/hospital.md +++ b/Docs/Layers/hospital.md @@ -30,21 +30,7 @@ A layer showing hospital grounds - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=hospital|amenity=clinic - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22hospital%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22clinic%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [clinic](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dclinic) [hospital](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dhospital) [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | @@ -71,6 +58,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### name @@ -177,6 +183,52 @@ This rendering asks information about the property [opening_hours:visitors](htt This is rendered with `

Opening hours for visitors

Regular visitors are allowed at the following moments: {opening_hours_table(opening_hours:visitors)}

Some wands might have different opening hours. Many hospitals allow visits during emergencies too.

` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/hospital/hospital.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/hospital/hospital.json) diff --git a/Docs/Layers/hotel.md b/Docs/Layers/hotel.md index ce012d6e6..fe39f055d 100644 --- a/Docs/Layers/hotel.md +++ b/Docs/Layers/hotel.md @@ -30,21 +30,7 @@ Layer showing all hotels - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - tourism=hotel - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22tourism%22%3D%22hotel%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -73,6 +60,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -251,6 +257,62 @@ This is rendered with `The network name is {internet_access:ssid}` - *Telekom* corresponds with `internet_access:ssid=Telekom` -This tagrendering is only visible in the popup if the following condition is met: `internet_access=wlan` +This tagrendering is only visible in the popup if the following condition is met: `internet_access=wlan` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/hotel/hotel.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/hotel/hotel.json) diff --git a/Docs/Layers/hydrant.md b/Docs/Layers/hydrant.md index 2429fda6c..62d93ce05 100644 --- a/Docs/Layers/hydrant.md +++ b/Docs/Layers/hydrant.md @@ -29,21 +29,7 @@ Map layer to show fire hydrants. - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - emergency=fire_hydrant - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22emergency%22%3D%22fire_hydrant%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/colour#values) [colour](https://wiki.openstreetmap.org/wiki/Key:colour) | [string](../SpecialInputElements.md#string) | [yellow](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dyellow) [red](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dred) [](https://taginfo.openstreetmap.org/keys/fire_hydrant:type#values) [fire_hydrant:type](https://wiki.openstreetmap.org/wiki/Key:fire_hydrant:type) | [string](../SpecialInputElements.md#string) | [pillar](https://wiki.openstreetmap.org/wiki/Tag:fire_hydrant:type%3Dpillar) [pipe](https://wiki.openstreetmap.org/wiki/Tag:fire_hydrant:type%3Dpipe) [wall](https://wiki.openstreetmap.org/wiki/Tag:fire_hydrant:type%3Dwall) [underground](https://wiki.openstreetmap.org/wiki/Tag:fire_hydrant:type%3Dunderground) [](https://taginfo.openstreetmap.org/keys/emergency#values) [emergency](https://wiki.openstreetmap.org/wiki/Key:emergency) | Multiple choice | [fire_hydrant](https://wiki.openstreetmap.org/wiki/Tag:emergency%3Dfire_hydrant) [](https://wiki.openstreetmap.org/wiki/Tag:emergency%3D) [](https://wiki.openstreetmap.org/wiki/Tag:emergency%3D) @@ -71,6 +58,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### hydrant-color @@ -201,6 +207,52 @@ This block shows the known images which are linked with the `image`-keys, but al This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/hydrant/hydrant.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/hydrant/hydrant.json) diff --git a/Docs/Layers/icons.md b/Docs/Layers/icons.md deleted file mode 100644 index 72222252f..000000000 --- a/Docs/Layers/icons.md +++ /dev/null @@ -1,174 +0,0 @@ -[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources) - - icons -======= - - - - - -A layer acting as library for icon-tagrenderings, especially to show as badge next to a POI - - - - - - - - This layer is shown at zoomlevel **0** and higher - - 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. - - 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` - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - id~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22id%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - - - - Supported attributes ----------------------- - - - -Warning: - -this quick overview is incomplete - - - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/wikipedia#values) [wikipedia](https://wiki.openstreetmap.org/wiki/Key:wikipedia) | Multiple choice | [](https://wiki.openstreetmap.org/wiki/Tag:wikipedia%3D) -[](https://taginfo.openstreetmap.org/keys/_isOpen#values) [_isOpen](https://wiki.openstreetmap.org/wiki/Key:_isOpen) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:_isOpen%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:_isOpen%3Dno) [](https://wiki.openstreetmap.org/wiki/Tag:_isOpen%3D) [parse_error](https://wiki.openstreetmap.org/wiki/Tag:_isOpen%3Dparse_error) -[](https://taginfo.openstreetmap.org/keys/smoking#values) [smoking](https://wiki.openstreetmap.org/wiki/Key:smoking) | Multiple choice | [no](https://wiki.openstreetmap.org/wiki/Tag:smoking%3Dno) [yes](https://wiki.openstreetmap.org/wiki/Tag:smoking%3Dyes) - - - - -### wikipedialink - - - -This tagrendering has no question and is thus read-only - - - - - - - *WD* corresponds with `` - - -This tagrendering is only visible in the popup if the following condition is met: `wikipedia~.+|wikidata~.+` - -This tagrendering has labels `defaults` - - - -### isOpen - - - -This tagrendering has no question and is thus read-only - - - - - - - *clock:#0f0;ring:#0f0* corresponds with `_isOpen=yes` - - *circle:#f00;clock:#fff* corresponds with `_isOpen=no` - - *clock:#ff0;ring:#ff0* corresponds with `opening_hours~.+` - - *circle:#f0f;clock:#fff* corresponds with `_isOpen=parse_error&opening_hours~.+` - - - - -### phonelink - - - -This tagrendering has no question and is thus read-only - - - -This tagrendering is only visible in the popup if the following condition is met: `phone~.+` - -This tagrendering has labels `defaults` - - - -### emaillink - - - -This tagrendering has no question and is thus read-only - - - -This tagrendering is only visible in the popup if the following condition is met: `email~.+` - -This tagrendering has labels `defaults` - - - -### smokingicon - - - -This tagrendering has no question and is thus read-only - - - - - - - *no-smoking* corresponds with `smoking=no` - - *smoking-allowed* corresponds with `smoking=yes` - - -This tagrendering has labels `defaults` - - - -### sharelink - - - -This tagrendering has no question and is thus read-only - - - -This tagrendering has labels `defaults` - - - -### osmlink - - - -This tagrendering has no question and is thus read-only - - - - - - - ** corresponds with `id~^(.*\/-.*)$` - - ** corresponds with `_backend~.+` - - -This tagrendering is only visible in the popup if the following condition is met: `id~^((node|way|relation)\/[0-9]*)$` - -This tagrendering has labels `defaults` - -This document is autogenerated from [assets/layers/icons/icons.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/icons/icons.json) diff --git a/Docs/Layers/id_presets.md b/Docs/Layers/id_presets.md deleted file mode 100644 index 143e81951..000000000 --- a/Docs/Layers/id_presets.md +++ /dev/null @@ -1,398 +0,0 @@ -[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources) - - id_presets -============ - - - - - -Layer containing various presets and questions generated by ID. These are meant to be reused in other layers by importing the tagRenderings with `id_preset. - - - - - - - - This layer is shown at zoomlevel **0** and higher - - 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. - - 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` - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - id~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22id%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - - - - Supported attributes ----------------------- - - - -Warning: - -this quick overview is incomplete - - - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/shop#values) [shop](https://wiki.openstreetmap.org/wiki/Key:shop) | Multiple choice | [agrarian](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dagrarian) [alcohol](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dalcohol) [anime](https://wiki.openstreetmap.org/wiki/Tag:shop%3Danime) [antiques](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dantiques) [appliance](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dappliance) [art](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dart) [baby_goods](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbaby_goods) [bag](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbag) [bakery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbakery) [bathroom_furnishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbathroom_furnishing) [beauty](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeauty) [bed](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbed) [beverages](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeverages) [bicycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbicycle) [boat](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dboat) [bookmaker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbookmaker) [books](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbooks) [brewing_supplies](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbrewing_supplies) [butcher](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbutcher) [camera](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcamera) [candles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcandles) [cannabis](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcannabis) [car](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar) [car_parts](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_parts) [car_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_repair) [caravan](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcaravan) [carpet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcarpet) [catalogue](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcatalogue) [charity](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcharity) [cheese](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcheese) [chemist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchemist) [chocolate](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchocolate) [clothes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dclothes) [coffee](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcoffee) [collector](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcollector) [computer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcomputer) [confectionery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconfectionery) [convenience](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconvenience) [copyshop](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcopyshop) [cosmetics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcosmetics) [country_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcountry_store) [craft](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcraft) [curtain](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcurtain) [dairy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddairy) [deli](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddeli) [department_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddepartment_store) [doityourself](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoityourself) [doors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoors) [dry_cleaning](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddry_cleaning) [e-cigarette](https://wiki.openstreetmap.org/wiki/Tag:shop%3De-cigarette) [electrical](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectrical) [electronics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectronics) [erotic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Derotic) [fabric](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfabric) [farm](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfarm) [fashion_accessories](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfashion_accessories) [fireplace](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfireplace) [fishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfishing) [flooring](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflooring) [florist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflorist) [frame](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dframe) [frozen_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfrozen_food) [fuel](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuel) [funeral_directors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuneral_directors) [furniture](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfurniture) [games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgames) [garden_centre](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgarden_centre) [gas](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgas) [general](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgeneral) [gift](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgift) [greengrocer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgreengrocer) [hairdresser](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser) [hairdresser_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser_supply) [hardware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhardware) [health_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhealth_food) [hearing_aids](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhearing_aids) [herbalist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dherbalist) [hifi](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhifi) [hobby](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhobby) [household_linen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhousehold_linen) [houseware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhouseware) [hunting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhunting) [interior_decoration](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dinterior_decoration) [jewelry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Djewelry) [kiosk](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkiosk) [kitchen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkitchen) [laundry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlaundry) [leather](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dleather) [lighting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlighting) [locksmith](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlocksmith) [lottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlottery) [mall](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmall) [massage](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmassage) [medical_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmedical_supply) [military_surplus](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmilitary_surplus) [mobile_phone](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmobile_phone) [model](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmodel) [money_lender](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmoney_lender) [motorcycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle) [motorcycle_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle_repair) [music](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusic) [musical_instrument](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusical_instrument) [newsagent](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnewsagent) [nutrition_supplements](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnutrition_supplements) [optician](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doptician) [outdoor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutdoor) [outpost](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutpost) [paint](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpaint) [party](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dparty) [pastry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpastry) [pawnbroker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpawnbroker) [perfumery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dperfumery) [pet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet) [pet_grooming](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet_grooming) [photo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dphoto) [pottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpottery) [printer_ink](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dprinter_ink) [psychic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpsychic) [pyrotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpyrotechnics) [radiotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dradiotechnics) [religion](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dreligion) [rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drental) [repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drepair) [scuba_diving](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dscuba_diving) [seafood](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dseafood) [second_hand](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsecond_hand) [sewing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsewing) [shoe_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoe_repair) [shoes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoes) [spices](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dspices) [sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsports) [stationery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstationery) [storage_rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstorage_rental) [supermarket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsupermarket) [swimming_pool](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dswimming_pool) [tailor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtailor) [tattoo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtattoo) [tea](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtea) [telecommunication](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtelecommunication) [ticket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dticket) [tiles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtiles) [tobacco](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtobacco) [tool_hire](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtool_hire) [toys](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtoys) [trade](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrade) [travel_agency](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtravel_agency) [trophy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrophy) [tyres](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtyres) [vacuum_cleaner](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvacuum_cleaner) [variety_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvariety_store) [video](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo) [video_games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo_games) [watches](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwatches) [water](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater) [water_sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater_sports) [weapons](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dweapons) [wholesale](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwholesale) [wigs](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwigs) [window_blind](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwindow_blind) [wine](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwine) -[](https://taginfo.openstreetmap.org/keys/shop#values) [shop](https://wiki.openstreetmap.org/wiki/Key:shop) | Multiple choice | [boutique](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dboutique) [fashion](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfashion) [vacant](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvacant) [yes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dyes) [agrarian](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dagrarian) [alcohol](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dalcohol) [anime](https://wiki.openstreetmap.org/wiki/Tag:shop%3Danime) [antiques](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dantiques) [appliance](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dappliance) [art](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dart) [baby_goods](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbaby_goods) [bag](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbag) [bakery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbakery) [bathroom_furnishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbathroom_furnishing) [beauty](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeauty) [bed](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbed) [beverages](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeverages) [bicycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbicycle) [boat](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dboat) [bookmaker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbookmaker) [books](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbooks) [brewing_supplies](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbrewing_supplies) [butcher](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbutcher) [camera](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcamera) [cannabis](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcannabis) [car](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar) [car_parts](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_parts) [car_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_repair) [caravan](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcaravan) [carpet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcarpet) [catalogue](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcatalogue) [charity](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcharity) [cheese](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcheese) [chocolate](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchocolate) [clothes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dclothes) [coffee](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcoffee) [computer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcomputer) [confectionery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconfectionery) [copyshop](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcopyshop) [cosmetics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcosmetics) [country_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcountry_store) [curtain](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcurtain) [dairy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddairy) [deli](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddeli) [department_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddepartment_store) [doityourself](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoityourself) [doors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoors) [dry_cleaning](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddry_cleaning) [e-cigarette](https://wiki.openstreetmap.org/wiki/Tag:shop%3De-cigarette) [electrical](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectrical) [electronics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectronics) [erotic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Derotic) [fabric](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfabric) [fashion_accessories](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfashion_accessories) [fireplace](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfireplace) [fishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfishing) [flooring](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflooring) [florist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflorist) [frame](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dframe) [frozen_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfrozen_food) [fuel](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuel) [funeral_directors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuneral_directors) [furniture](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfurniture) [games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgames) [garden_centre](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgarden_centre) [gas](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgas) [general](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgeneral) [gift](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgift) [greengrocer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgreengrocer) [hairdresser](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser) [hairdresser_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser_supply) [hardware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhardware) [health_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhealth_food) [hearing_aids](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhearing_aids) [herbalist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dherbalist) [hifi](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhifi) [hobby](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhobby) [household_linen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhousehold_linen) [houseware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhouseware) [hunting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhunting) [interior_decoration](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dinterior_decoration) [jewelry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Djewelry) [kiosk](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkiosk) [kitchen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkitchen) [laundry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlaundry) [leather](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dleather) [lighting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlighting) [locksmith](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlocksmith) [mall](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmall) [massage](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmassage) [medical_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmedical_supply) [military_surplus](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmilitary_surplus) [model](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmodel) [money_lender](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmoney_lender) [motorcycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle) [motorcycle_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle_repair) [music](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusic) [musical_instrument](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusical_instrument) [newsagent](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnewsagent) [nutrition_supplements](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnutrition_supplements) [optician](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doptician) [outdoor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutdoor) [outpost](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutpost) [paint](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpaint) [party](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dparty) [pastry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpastry) [pawnbroker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpawnbroker) [perfumery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dperfumery) [pet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet) [pet_grooming](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet_grooming) [photo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dphoto) [pottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpottery) [printer_ink](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dprinter_ink) [psychic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpsychic) [pyrotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpyrotechnics) [radiotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dradiotechnics) [religion](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dreligion) [rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drental) [scuba_diving](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dscuba_diving) [seafood](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dseafood) [second_hand](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsecond_hand) [sewing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsewing) [shoe_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoe_repair) [shoes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoes) [spices](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dspices) [sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsports) [stationery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstationery) [storage_rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstorage_rental) [supermarket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsupermarket) [tailor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtailor) [tattoo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtattoo) [tea](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtea) [telecommunication](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtelecommunication) [tiles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtiles) [tobacco](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtobacco) [tool_hire](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtool_hire) [toys](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtoys) [trade](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrade) [travel_agency](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtravel_agency) [trophy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrophy) [tyres](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtyres) [vacuum_cleaner](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvacuum_cleaner) [variety_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvariety_store) [video](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo) [video_games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo_games) [watches](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwatches) [water](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater) [weapons](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dweapons) [wholesale](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwholesale) [wigs](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwigs) [window_blind](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwindow_blind) [wine](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwine) - - - - -### shop_types - - - -This tagrendering has no question and is thus read-only - - - - - - - *Farm Supply Shop* corresponds with `shop=agrarian` - - *Liquor Store* corresponds with `shop=alcohol` - - *Anime / Manga Shop* corresponds with `shop=anime` - - *Antiques Shop* corresponds with `shop=antiques` - - *Appliance Store* corresponds with `shop=appliance` - - *Art Store* corresponds with `shop=art` - - *Baby Goods Store* corresponds with `shop=baby_goods` - - *Bag/Luggage Store* corresponds with `shop=bag` - - *Bakery* corresponds with `shop=bakery` - - *Bathroom Furnishing Store* corresponds with `shop=bathroom_furnishing` - - *Beauty Shop* corresponds with `shop=beauty` - - *Bedding/Mattress Store* corresponds with `shop=bed` - - *Beverage Store* corresponds with `shop=beverages` - - *Bicycle Shop* corresponds with `shop=bicycle` - - *Boat Store* corresponds with `shop=boat` - - *Bookmaker* corresponds with `shop=bookmaker` - - *Book Store* corresponds with `shop=books` - - *Brewing Supply Store* corresponds with `shop=brewing_supplies` - - *Butcher* corresponds with `shop=butcher` - - *Camera Equipment Store* corresponds with `shop=camera` - - *Candle Shop* corresponds with `shop=candles` - - *Cannabis Shop* corresponds with `shop=cannabis` - - *Car Dealership* corresponds with `shop=car` - - *Car Parts Store* corresponds with `shop=car_parts` - - *Car Repair Shop* corresponds with `shop=car_repair` - - *RV Dealership* corresponds with `shop=caravan` - - *Carpet Store* corresponds with `shop=carpet` - - *Catalog Shop* corresponds with `shop=catalogue` - - *Charity Store* corresponds with `shop=charity` - - *Cheese Store* corresponds with `shop=cheese` - - *Drugstore* corresponds with `shop=chemist` - - *Chocolate Store* corresponds with `shop=chocolate` - - *Clothing Store* corresponds with `shop=clothes` - - *Coffee Store* corresponds with `shop=coffee` - - *Collectibles Shop* corresponds with `shop=collector` - - *Computer Store* corresponds with `shop=computer` - - *Candy Store* corresponds with `shop=confectionery` - - *Convenience Store* corresponds with `shop=convenience` - - *Copy Store* corresponds with `shop=copyshop` - - *Cosmetics Store* corresponds with `shop=cosmetics` - - *Country Store* corresponds with `shop=country_store` - - *Arts & Crafts Store* corresponds with `shop=craft` - - *Curtain Store* corresponds with `shop=curtain` - - *Dairy Store* corresponds with `shop=dairy` - - *Deli* corresponds with `shop=deli` - - *Department Store* corresponds with `shop=department_store` - - *DIY Store* corresponds with `shop=doityourself` - - *Door Shop* corresponds with `shop=doors` - - *Dry Cleaner* corresponds with `shop=dry_cleaning` - - *E-Cigarette Shop* corresponds with `shop=e-cigarette` - - *Electrical Equipment Store* corresponds with `shop=electrical` - - *Electronics Store* corresponds with `shop=electronics` - - *Erotic Store* corresponds with `shop=erotic` - - *Fabric Store* corresponds with `shop=fabric` - - *Produce Stand* corresponds with `shop=farm` - - *Fashion Accessories Store* corresponds with `shop=fashion_accessories` - - *Fireplace Store* corresponds with `shop=fireplace` - - *Fishing Shop* corresponds with `shop=fishing` - - *Flooring Supply Shop* corresponds with `shop=flooring` - - *Florist* corresponds with `shop=florist` - - *Framing Shop* corresponds with `shop=frame` - - *Frozen Food Store* corresponds with `shop=frozen_food` - - *Fuel Shop* corresponds with `shop=fuel` - - *Funeral Home* corresponds with `shop=funeral_directors` - - *Furniture Store* corresponds with `shop=furniture` - - *Tabletop Game Store* corresponds with `shop=games` - - *Garden Center* corresponds with `shop=garden_centre` - - *Bottled Gas Shop* corresponds with `shop=gas` - - *General Store* corresponds with `shop=general` - - *Gift Shop* corresponds with `shop=gift` - - *Greengrocer* corresponds with `shop=greengrocer` - - *Hairdresser* corresponds with `shop=hairdresser` - - *Hairdresser Supply Store* corresponds with `shop=hairdresser_supply` - - *Hardware Store* corresponds with `shop=hardware` - - *Health Food Shop* corresponds with `shop=health_food` - - *Hearing Aids Store* corresponds with `shop=hearing_aids` - - *Herbalist* corresponds with `shop=herbalist` - - *Hifi Store* corresponds with `shop=hifi` - - *Hobby Shop* corresponds with `shop=hobby` - - *Household Linen Shop* corresponds with `shop=household_linen` - - *Houseware Store* corresponds with `shop=houseware` - - *Hunting Shop* corresponds with `shop=hunting` - - *Interior Decoration Store* corresponds with `shop=interior_decoration` - - *Jewelry Store* corresponds with `shop=jewelry` - - *Kiosk* corresponds with `shop=kiosk` - - *Kitchen Design Store* corresponds with `shop=kitchen` - - *Laundry* corresponds with `shop=laundry` - - *Leather Store* corresponds with `shop=leather` - - *Lighting Store* corresponds with `shop=lighting` - - *Locksmith* corresponds with `shop=locksmith` - - *Lottery Shop* corresponds with `shop=lottery` - - *Mall* corresponds with `shop=mall` - - *Massage Shop* corresponds with `shop=massage` - - *Medical Supply Store* corresponds with `shop=medical_supply` - - *Military Surplus Store* corresponds with `shop=military_surplus` - - *Mobile Phone Store* corresponds with `shop=mobile_phone` - - *Model Shop* corresponds with `shop=model` - - *Money Lender* corresponds with `shop=money_lender` - - *Motorcycle Dealership* corresponds with `shop=motorcycle` - - *Motorcycle Repair Shop* corresponds with `shop=motorcycle_repair` - - *Music Store* corresponds with `shop=music` - - *Musical Instrument Store* corresponds with `shop=musical_instrument` - - *Newspaper/Magazine Shop* corresponds with `shop=newsagent` - - *Nutrition Supplements Store* corresponds with `shop=nutrition_supplements` - - *Optician* corresponds with `shop=optician` - - *Outdoors Store* corresponds with `shop=outdoor` - - *Online Retailer Outpost* corresponds with `shop=outpost` - - *Paint Store* corresponds with `shop=paint` - - *Party Supply Store* corresponds with `shop=party` - - *Pastry Shop* corresponds with `shop=pastry` - - *Pawn Shop* corresponds with `shop=pawnbroker` - - *Perfume Store* corresponds with `shop=perfumery` - - *Pet Store* corresponds with `shop=pet` - - *Pet Grooming Store* corresponds with `shop=pet_grooming` - - *Photography Store* corresponds with `shop=photo` - - *Pottery Store* corresponds with `shop=pottery` - - *Printer Ink Store* corresponds with `shop=printer_ink` - - *Psychic* corresponds with `shop=psychic` - - *Fireworks Store* corresponds with `shop=pyrotechnics` - - *Radio/Electronic Component Store* corresponds with `shop=radiotechnics` - - *Religious Store* corresponds with `shop=religion` - - *Rental Shop* corresponds with `shop=rental` - - *Repair Shop* corresponds with `shop=repair` - - *Scuba Diving Shop* corresponds with `shop=scuba_diving` - - *Seafood Shop* corresponds with `shop=seafood` - - *Consignment/Thrift Store* corresponds with `shop=second_hand` - - *Sewing Supply Shop* corresponds with `shop=sewing` - - *Shoe Repair Shop* corresponds with `shop=shoe_repair` - - *Shoe Store* corresponds with `shop=shoes` - - *Spice Shop* corresponds with `shop=spices` - - *Sporting Goods Store* corresponds with `shop=sports` - - *Stationery Store* corresponds with `shop=stationery` - - *Storage Rental* corresponds with `shop=storage_rental` - - *Supermarket* corresponds with `shop=supermarket` - - *Pool Supply Store* corresponds with `shop=swimming_pool` - - *Tailor* corresponds with `shop=tailor` - - *Tattoo Parlor* corresponds with `shop=tattoo` - - *Tea Store* corresponds with `shop=tea` - - *Telecom Retail Store* corresponds with `shop=telecommunication` - - *Ticket Seller* corresponds with `shop=ticket` - - *Tile Shop* corresponds with `shop=tiles` - - *Tobacco Shop* corresponds with `shop=tobacco` - - *Tool Rental* corresponds with `shop=tool_hire` - - *Toy Store* corresponds with `shop=toys` - - *Trade Shop* corresponds with `shop=trade` - - *Travel Agency* corresponds with `shop=travel_agency` - - *Trophy Shop* corresponds with `shop=trophy` - - *Tire Store* corresponds with `shop=tyres` - - *Vacuum Cleaner Store* corresponds with `shop=vacuum_cleaner` - - *Variety Store* corresponds with `shop=variety_store` - - *Video Store* corresponds with `shop=video` - - *Video Game Store* corresponds with `shop=video_games` - - *Watches Shop* corresponds with `shop=watches` - - *Drinking Water Shop* corresponds with `shop=water` - - *Watersport/Swim Shop* corresponds with `shop=water_sports` - - *Weapon Shop* corresponds with `shop=weapons` - - *Wholesale Store* corresponds with `shop=wholesale` - - *Wig Shop* corresponds with `shop=wigs` - - *Window Blind Store* corresponds with `shop=window_blind` - - *Wine Shop* corresponds with `shop=wine` - - - - -### shop_rendering - - - -This tagrendering has no question and is thus read-only - - - - - - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=boutique` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=fashion` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=vacant` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=yes` - - *circle:white;./assets/layers/id_presets/fas-tractor.svg* corresponds with `shop=agrarian` - - *circle:white;./assets/layers/id_presets/fas-wine-bottle.svg* corresponds with `shop=alcohol` - - *circle:white;./assets/layers/id_presets/fas-dragon.svg* corresponds with `shop=anime` - - *circle:white;./assets/layers/id_presets/temaki-furniture.svg* corresponds with `shop=antiques` - - *circle:white;./assets/layers/id_presets/temaki-laundry.svg* corresponds with `shop=appliance` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=art` - - *circle:white;./assets/layers/id_presets/fas-baby-carriage.svg* corresponds with `shop=baby_goods` - - *circle:white;./assets/layers/id_presets/fas-suitcase-rolling.svg* corresponds with `shop=bag` - - *circle:white;./assets/layers/id_presets/maki-bakery.svg* corresponds with `shop=bakery` - - *circle:white;./assets/layers/id_presets/fas-bath.svg* corresponds with `shop=bathroom_furnishing` - - *circle:white;./assets/layers/id_presets/temaki-lipstick.svg* corresponds with `shop=beauty` - - *circle:white;./assets/layers/id_presets/maki-lodging.svg* corresponds with `shop=bed` - - *circle:white;./assets/layers/id_presets/temaki-bottles.svg* corresponds with `shop=beverages` - - *circle:white;./assets/layers/id_presets/maki-bicycle.svg* corresponds with `shop=bicycle` - - *circle:white;./assets/layers/id_presets/temaki-boat.svg* corresponds with `shop=boat` - - *circle:white;./assets/layers/id_presets/temaki-money_hand.svg* corresponds with `shop=bookmaker` - - *circle:white;./assets/layers/id_presets/fas-book.svg* corresponds with `shop=books` - - *circle:white;./assets/layers/id_presets/temaki-storage_fermenter.svg* corresponds with `shop=brewing_supplies` - - *circle:white;./assets/layers/id_presets/temaki-cleaver.svg* corresponds with `shop=butcher` - - *circle:white;./assets/layers/id_presets/fas-camera-retro.svg* corresponds with `shop=camera` - - *circle:white;./assets/layers/id_presets/fas-cannabis.svg* corresponds with `shop=cannabis` - - *circle:white;./assets/layers/id_presets/maki-car.svg* corresponds with `shop=car` - - *circle:white;./assets/layers/id_presets/fas-car-battery.svg* corresponds with `shop=car_parts` - - *circle:white;./assets/layers/id_presets/maki-car-repair.svg* corresponds with `shop=car_repair` - - *circle:white;./assets/layers/id_presets/temaki-camper_trailer.svg* corresponds with `shop=caravan` - - *circle:white;./assets/layers/id_presets/fas-tape.svg* corresponds with `shop=carpet` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=catalogue` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=charity` - - *circle:white;./assets/layers/id_presets/fas-cheese.svg* corresponds with `shop=cheese` - - *circle:white;./assets/layers/id_presets/maki-confectionery.svg* corresponds with `shop=chocolate` - - *circle:white;./assets/layers/id_presets/maki-clothing-store.svg* corresponds with `shop=clothes` - - *circle:white;./assets/layers/id_presets/temaki-coffee.svg* corresponds with `shop=coffee` - - *circle:white;./assets/layers/id_presets/fas-laptop.svg* corresponds with `shop=computer` - - *circle:white;./assets/layers/id_presets/maki-confectionery.svg* corresponds with `shop=confectionery` - - *circle:white;./assets/layers/id_presets/fas-print.svg* corresponds with `shop=copyshop` - - *circle:white;./assets/layers/id_presets/temaki-lipstick.svg* corresponds with `shop=cosmetics` - - *circle:white;./assets/layers/id_presets/fas-hat-cowboy-side.svg* corresponds with `shop=country_store` - - *circle:white;./assets/layers/id_presets/temaki-curtains.svg* corresponds with `shop=curtain` - - *circle:white;./assets/layers/id_presets/fas-cheese.svg* corresponds with `shop=dairy` - - *circle:white;./assets/layers/id_presets/temaki-meat.svg* corresponds with `shop=deli` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=department_store` - - *circle:white;./assets/layers/id_presets/temaki-tools.svg* corresponds with `shop=doityourself` - - *circle:white;./assets/layers/id_presets/fas-door-open.svg* corresponds with `shop=doors` - - *circle:white;./assets/layers/id_presets/temaki-clothes_hanger.svg* corresponds with `shop=dry_cleaning` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=e-cigarette` - - *circle:white;./assets/layers/id_presets/temaki-power.svg* corresponds with `shop=electrical` - - *circle:white;./assets/layers/id_presets/fas-plug.svg* corresponds with `shop=electronics` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=erotic` - - *circle:white;./assets/layers/id_presets/fas-tape.svg* corresponds with `shop=fabric` - - *circle:white;./assets/layers/id_presets/temaki-fashion_accessories.svg* corresponds with `shop=fashion_accessories` - - *circle:white;./assets/layers/id_presets/temaki-fireplace.svg* corresponds with `shop=fireplace` - - *circle:white;./assets/layers/id_presets/temaki-ice_fishing.svg* corresponds with `shop=fishing` - - *circle:white;./assets/layers/id_presets/temaki-tools.svg* corresponds with `shop=flooring` - - *circle:white;./assets/layers/id_presets/maki-florist.svg* corresponds with `shop=florist` - - *circle:white;./assets/layers/id_presets/fas-vector-square.svg* corresponds with `shop=frame` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=frozen_food` - - *circle:white;./assets/layers/id_presets/temaki-propane_tank.svg* corresponds with `shop=fuel` - - *circle:white;./assets/layers/id_presets/maki-cemetery.svg* corresponds with `shop=funeral_directors` - - *circle:white;./assets/layers/id_presets/fas-couch.svg* corresponds with `shop=furniture` - - *circle:white;./assets/layers/id_presets/fas-dice.svg* corresponds with `shop=games` - - *circle:white;./assets/layers/id_presets/maki-garden-centre.svg* corresponds with `shop=garden_centre` - - *circle:white;./assets/layers/id_presets/temaki-propane_tank.svg* corresponds with `shop=gas` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=general` - - *circle:white;./assets/layers/id_presets/maki-gift.svg* corresponds with `shop=gift` - - *circle:white;./assets/layers/id_presets/fas-carrot.svg* corresponds with `shop=greengrocer` - - *circle:white;./assets/layers/id_presets/temaki-beauty_salon.svg* corresponds with `shop=hairdresser` - - *circle:white;./assets/layers/id_presets/temaki-hair_care.svg* corresponds with `shop=hairdresser_supply` - - *circle:white;./assets/layers/id_presets/temaki-tools.svg* corresponds with `shop=hardware` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=health_food` - - *circle:white;./assets/layers/id_presets/temaki-hearing_aid.svg* corresponds with `shop=hearing_aids` - - *circle:white;./assets/layers/id_presets/fas-leaf.svg* corresponds with `shop=herbalist` - - *circle:white;./assets/layers/id_presets/temaki-speaker.svg* corresponds with `shop=hifi` - - *circle:white;./assets/layers/id_presets/fas-dragon.svg* corresponds with `shop=hobby` - - *circle:white;./assets/layers/id_presets/temaki-cloth.svg* corresponds with `shop=household_linen` - - *circle:white;./assets/layers/id_presets/fas-blender.svg* corresponds with `shop=houseware` - - *circle:white;./assets/layers/id_presets/temaki-bow_and_arrow.svg* corresponds with `shop=hunting` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=interior_decoration` - - *circle:white;./assets/layers/id_presets/maki-jewelry-store.svg* corresponds with `shop=jewelry` - - *circle:white;./assets/layers/id_presets/fas-store.svg* corresponds with `shop=kiosk` - - *circle:white;./assets/layers/id_presets/temaki-kitchen_sink.svg* corresponds with `shop=kitchen` - - *circle:white;./assets/layers/id_presets/temaki-laundry.svg* corresponds with `shop=laundry` - - *circle:white;./assets/layers/id_presets/temaki-handbag.svg* corresponds with `shop=leather` - - *circle:white;./assets/layers/id_presets/temaki-desk_lamp.svg* corresponds with `shop=lighting` - - *circle:white;./assets/layers/id_presets/fas-key.svg* corresponds with `shop=locksmith` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=mall` - - *circle:white;./assets/layers/id_presets/temaki-spa.svg* corresponds with `shop=massage` - - *circle:white;./assets/layers/id_presets/fas-crutch.svg* corresponds with `shop=medical_supply` - - *circle:white;./assets/layers/id_presets/temaki-military.svg* corresponds with `shop=military_surplus` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=model` - - *circle:white;./assets/layers/id_presets/temaki-money_hand.svg* corresponds with `shop=money_lender` - - *circle:white;./assets/layers/id_presets/fas-motorcycle.svg* corresponds with `shop=motorcycle` - - *circle:white;./assets/layers/id_presets/temaki-motorcycle_repair.svg* corresponds with `shop=motorcycle_repair` - - *circle:white;./assets/layers/id_presets/fas-compact-disc.svg* corresponds with `shop=music` - - *circle:white;./assets/layers/id_presets/fas-guitar.svg* corresponds with `shop=musical_instrument` - - *circle:white;./assets/layers/id_presets/fas-newspaper.svg* corresponds with `shop=newsagent` - - *circle:white;./assets/layers/id_presets/fas-pills.svg* corresponds with `shop=nutrition_supplements` - - *circle:white;./assets/layers/id_presets/maki-optician.svg* corresponds with `shop=optician` - - *circle:white;./assets/layers/id_presets/temaki-compass.svg* corresponds with `shop=outdoor` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=outpost` - - *circle:white;./assets/layers/id_presets/fas-paint-roller.svg* corresponds with `shop=paint` - - *circle:white;./assets/layers/id_presets/temaki-balloon.svg* corresponds with `shop=party` - - *circle:white;./assets/layers/id_presets/maki-bakery.svg* corresponds with `shop=pastry` - - *circle:white;./assets/layers/id_presets/temaki-money_hand.svg* corresponds with `shop=pawnbroker` - - *circle:white;./assets/layers/id_presets/temaki-perfume.svg* corresponds with `shop=perfumery` - - *circle:white;./assets/layers/id_presets/fas-cat.svg* corresponds with `shop=pet` - - *circle:white;./assets/layers/id_presets/temaki-pet_grooming.svg* corresponds with `shop=pet_grooming` - - *circle:white;./assets/layers/id_presets/fas-camera-retro.svg* corresponds with `shop=photo` - - *circle:white;./assets/layers/id_presets/temaki-vase.svg* corresponds with `shop=pottery` - - *circle:white;./assets/layers/id_presets/fas-print.svg* corresponds with `shop=printer_ink` - - *circle:white;./assets/layers/id_presets/temaki-psychic.svg* corresponds with `shop=psychic` - - *circle:white;./assets/layers/id_presets/temaki-rocket_firework.svg* corresponds with `shop=pyrotechnics` - - *circle:white;./assets/layers/id_presets/fas-microchip.svg* corresponds with `shop=radiotechnics` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=religion` - - *circle:white;./assets/layers/id_presets/fas-dolly.svg* corresponds with `shop=rental` - - *circle:white;./assets/layers/id_presets/temaki-scuba_diving.svg* corresponds with `shop=scuba_diving` - - *circle:white;./assets/layers/id_presets/temaki-fish_cleaning.svg* corresponds with `shop=seafood` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=second_hand` - - *circle:white;./assets/layers/id_presets/temaki-needle_and_spool.svg* corresponds with `shop=sewing` - - *circle:white;./assets/layers/id_presets/temaki-hammer_shoe.svg* corresponds with `shop=shoe_repair` - - *circle:white;./assets/layers/id_presets/maki-shoe.svg* corresponds with `shop=shoes` - - *circle:white;./assets/layers/id_presets/temaki-spice_bottle.svg* corresponds with `shop=spices` - - *circle:white;./assets/layers/id_presets/fas-futbol.svg* corresponds with `shop=sports` - - *circle:white;./assets/layers/id_presets/fas-paperclip.svg* corresponds with `shop=stationery` - - *circle:white;./assets/layers/id_presets/temaki-storage_rental.svg* corresponds with `shop=storage_rental` - - *circle:white;./assets/layers/id_presets/maki-grocery.svg* corresponds with `shop=supermarket` - - *circle:white;./assets/layers/id_presets/temaki-needle_and_spool.svg* corresponds with `shop=tailor` - - *circle:white;./assets/layers/id_presets/temaki-tattoo_machine.svg* corresponds with `shop=tattoo` - - *circle:white;./assets/layers/id_presets/maki-teahouse.svg* corresponds with `shop=tea` - - *circle:white;./assets/layers/id_presets/maki-telephone.svg* corresponds with `shop=telecommunication` - - *circle:white;./assets/layers/id_presets/temaki-tiling.svg* corresponds with `shop=tiles` - - *circle:white;./assets/layers/id_presets/temaki-pipe.svg* corresponds with `shop=tobacco` - - *circle:white;./assets/layers/id_presets/temaki-tools.svg* corresponds with `shop=tool_hire` - - *circle:white;./assets/layers/id_presets/fas-rocket.svg* corresponds with `shop=toys` - - *circle:white;./assets/layers/id_presets/temaki-tools.svg* corresponds with `shop=trade` - - *circle:white;./assets/layers/id_presets/fas-suitcase.svg* corresponds with `shop=travel_agency` - - *circle:white;./assets/layers/id_presets/fas-trophy.svg* corresponds with `shop=trophy` - - *circle:white;./assets/layers/id_presets/temaki-tire.svg* corresponds with `shop=tyres` - - *circle:white;./assets/layers/id_presets/temaki-vacuum.svg* corresponds with `shop=vacuum_cleaner` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=variety_store` - - *circle:white;./assets/layers/id_presets/temaki-movie_rental.svg* corresponds with `shop=video` - - *circle:white;./assets/layers/id_presets/maki-gaming.svg* corresponds with `shop=video_games` - - *circle:white;./assets/layers/id_presets/maki-watch.svg* corresponds with `shop=watches` - - *circle:white;./assets/layers/id_presets/temaki-water_bottle.svg* corresponds with `shop=water` - - *circle:white;./assets/layers/id_presets/temaki-dagger.svg* corresponds with `shop=weapons` - - *circle:white;./assets/layers/id_presets/maki-warehouse.svg* corresponds with `shop=wholesale` - - *circle:white;./assets/layers/id_presets/maki-shop.svg* corresponds with `shop=wigs` - - *circle:white;./assets/layers/id_presets/temaki-window.svg* corresponds with `shop=window_blind` - - *circle:white;./assets/layers/id_presets/maki-alcohol-shop.svg* corresponds with `shop=wine` - - -This document is autogenerated from [assets/layers/id_presets/id_presets.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/id_presets/id_presets.json) diff --git a/Docs/Layers/indoors.md b/Docs/Layers/indoors.md index 8d245d954..1b1129ea5 100644 --- a/Docs/Layers/indoors.md +++ b/Docs/Layers/indoors.md @@ -31,21 +31,7 @@ Basic indoor mapping: shows room outlines - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - indoor=room|indoor=area|indoor=wall|indoor=door|indoor=level - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22indoor%22%3D%22room%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22indoor%22%3D%22area%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22indoor%22%3D%22wall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22indoor%22%3D%22door%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22indoor%22%3D%22level%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,12 +48,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/ref#values) [ref](https://wiki.openstreetmap.org/wiki/Key:ref) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -108,6 +114,52 @@ This is rendered with `This room is named {name}` -This tagrendering is only visible in the popup if the following condition is met: `indoor=room|indoor=area|indoor=corridor` +This tagrendering is only visible in the popup if the following condition is met: `indoor=room|indoor=area|indoor=corridor` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/indoors/indoors.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/indoors/indoors.json) diff --git a/Docs/Layers/information_board.md b/Docs/Layers/information_board.md index 181405c9f..f18919e35 100644 --- a/Docs/Layers/information_board.md +++ b/Docs/Layers/information_board.md @@ -29,21 +29,7 @@ A layer showing touristical, road side information boards (e.g. giving informati - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - information=board - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22information%22%3D%22board%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -52,6 +38,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### images @@ -62,6 +78,72 @@ This block shows the known images which are linked with the `image`-keys, but al This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/information_board/information_board.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/information_board/information_board.json) diff --git a/Docs/Layers/kerbs.md b/Docs/Layers/kerbs.md index 545141344..8371c6758 100644 --- a/Docs/Layers/kerbs.md +++ b/Docs/Layers/kerbs.md @@ -34,21 +34,7 @@ A layer showing kerbs. - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - barrier=kerb - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22barrier%22%3D%22kerb%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -65,6 +51,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/kerb#values) [kerb](https://wiki.openstreetmap.org/wiki/Key:kerb) | Multiple choice | [raised](https://wiki.openstreetmap.org/wiki/Tag:kerb%3Draised) [lowered](https://wiki.openstreetmap.org/wiki/Tag:kerb%3Dlowered) [flush](https://wiki.openstreetmap.org/wiki/Tag:kerb%3Dflush) [](https://taginfo.openstreetmap.org/keys/tactile_paving#values) [tactile_paving](https://wiki.openstreetmap.org/wiki/Key:tactile_paving) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:tactile_paving%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:tactile_paving%3Dno) [](https://taginfo.openstreetmap.org/keys/kerb:height#values) [kerb:height](https://wiki.openstreetmap.org/wiki/Key:kerb:height) | [pnat](../SpecialInputElements.md#pnat) | [0](https://wiki.openstreetmap.org/wiki/Tag:kerb:height%3D0) @@ -72,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -146,6 +152,52 @@ This is rendered with `Kerb height: {kerb:height}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/kindergarten_childcare.md b/Docs/Layers/kindergarten_childcare.md index e02e525cf..abfb914fb 100644 --- a/Docs/Layers/kindergarten_childcare.md +++ b/Docs/Layers/kindergarten_childcare.md @@ -29,21 +29,7 @@ Shows kindergartens and preschools. Both are grouped in one layer, as they are r - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=childcare|amenity=kindergarten|isced:level:2011=early_childhood - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22childcare%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22kindergarten%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22isced%3Alevel%3A2011%22%3D%22early_childhood%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [kindergarten](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dkindergarten) [childcare](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dchildcare) [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | @@ -71,6 +58,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### childcare-type @@ -193,6 +199,72 @@ This rendering asks information about the property [capacity](https://wiki.open This is rendered with `This facility has room for {capacity} kids` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/kindergarten_childcare/kindergarten_childcare.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/kindergarten_childcare/kindergarten_childcare.json) diff --git a/Docs/Layers/lit_streets.md b/Docs/Layers/lit_streets.md index f7884cfd9..984da9ad7 100644 --- a/Docs/Layers/lit_streets.md +++ b/Docs/Layers/lit_streets.md @@ -27,24 +27,7 @@ - [street_lighting](https://mapcomplete.osm.be/street_lighting) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway~.+ - - lit!=no - - lit~.+ - - service!=driveway - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%5D%5B%22lit%22!%3D%22no%22%5D%5B%22lit%22%5D%5B%22service%22!%3D%22driveway%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,11 +44,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/lit#values) [lit](https://wiki.openstreetmap.org/wiki/Key:lit) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dno) [24/7](https://wiki.openstreetmap.org/wiki/Tag:lit%3D24/7) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -97,12 +100,10 @@ The question is *Is this street lit?* -### questions +### leftover-questions -Show the images block at this location - This tagrendering has no question and is thus read-only @@ -117,6 +118,40 @@ Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only + + + + +### split-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/themes/street_lighting/street_lighting.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/street_lighting/street_lighting.json) diff --git a/Docs/Layers/map.md b/Docs/Layers/map.md index 0b61b34b2..7b0381577 100644 --- a/Docs/Layers/map.md +++ b/Docs/Layers/map.md @@ -30,21 +30,7 @@ A map, meant for tourists which is permanently installed in the public space - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - tourism=map|information=map - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22information%22%3D%22map%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22map%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,12 +47,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/map_source#values) [map_source](https://wiki.openstreetmap.org/wiki/Key:map_source) | [string](../SpecialInputElements.md#string) | [OpenStreetMap](https://wiki.openstreetmap.org/wiki/Tag:map_source%3DOpenStreetMap) [](https://taginfo.openstreetmap.org/keys/map_source:attribution#values) [map_source:attribution](https://wiki.openstreetmap.org/wiki/Key:map_source:attribution) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:map_source:attribution%3Dyes) [incomplete](https://wiki.openstreetmap.org/wiki/Tag:map_source:attribution%3Dincomplete) [sticker](https://wiki.openstreetmap.org/wiki/Tag:map_source:attribution%3Dsticker) [none](https://wiki.openstreetmap.org/wiki/Tag:map_source:attribution%3Dnone) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -120,6 +126,72 @@ The question is *Is the OpenStreetMap-attribution given?* This tagrendering is only visible in the popup if the following condition is met: `map_source~^((O|)pen(S|s)treet(M|m)ap)$|map_source=osm|map_source=OSM` -This tagrendering has labels `map` +This tagrendering has labels `map` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/map/map.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/map/map.json) diff --git a/Docs/Layers/maproulette.md b/Docs/Layers/maproulette.md index 1e41542b5..0d31be149 100644 --- a/Docs/Layers/maproulette.md +++ b/Docs/Layers/maproulette.md @@ -18,21 +18,7 @@ Layer showing all tasks in MapRoulette - This layer is loaded from an external source, namely `https://maproulette.org/api/v2/tasks/box/{x_min}/{y_min}/{x_max}/{y_max}` - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - title~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22title%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -49,11 +35,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/status#values) [status](https://wiki.openstreetmap.org/wiki/Key:status) | Multiple choice | [0](https://wiki.openstreetmap.org/wiki/Tag:status%3D0) [1](https://wiki.openstreetmap.org/wiki/Tag:status%3D1) [2](https://wiki.openstreetmap.org/wiki/Tag:status%3D2) [3](https://wiki.openstreetmap.org/wiki/Tag:status%3D3) [4](https://wiki.openstreetmap.org/wiki/Tag:status%3D4) [5](https://wiki.openstreetmap.org/wiki/Tag:status%3D5) [6](https://wiki.openstreetmap.org/wiki/Tag:status%3D6) [9](https://wiki.openstreetmap.org/wiki/Tag:status%3D9) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### status @@ -84,6 +90,8 @@ This tagrendering has no question and is thus read-only +This tagrendering has labels `controls` + ### mark_duplicate @@ -94,6 +102,8 @@ This tagrendering has no question and is thus read-only +This tagrendering has labels `controls` + ### mark_too_hard @@ -104,6 +114,54 @@ This tagrendering has no question and is thus read-only +This tagrendering has labels `controls` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + #### Filters diff --git a/Docs/Layers/maproulette_challenge.md b/Docs/Layers/maproulette_challenge.md index de57d43ce..d3ef35026 100644 --- a/Docs/Layers/maproulette_challenge.md +++ b/Docs/Layers/maproulette_challenge.md @@ -27,25 +27,12 @@ Layer showing tasks of a single MapRoulette challenge. This layer is intended to + - [atm](https://mapcomplete.osm.be/atm) - [onwheels](https://mapcomplete.osm.be/onwheels) - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - mr_taskId~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22mr_taskId%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,11 +49,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/mr_taskStatus#values) [mr_taskStatus](https://wiki.openstreetmap.org/wiki/Key:mr_taskStatus) | Multiple choice | [Created](https://wiki.openstreetmap.org/wiki/Tag:mr_taskStatus%3DCreated) [Fixed](https://wiki.openstreetmap.org/wiki/Tag:mr_taskStatus%3DFixed) [False positive](https://wiki.openstreetmap.org/wiki/Tag:mr_taskStatus%3DFalse positive) [Skipped](https://wiki.openstreetmap.org/wiki/Tag:mr_taskStatus%3DSkipped) [Deleted](https://wiki.openstreetmap.org/wiki/Tag:mr_taskStatus%3DDeleted) [Already fixed](https://wiki.openstreetmap.org/wiki/Tag:mr_taskStatus%3DAlready fixed) [Too hard](https://wiki.openstreetmap.org/wiki/Tag:mr_taskStatus%3DToo hard) [Disabled](https://wiki.openstreetmap.org/wiki/Tag:mr_taskStatus%3DDisabled) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### details @@ -99,6 +106,52 @@ This tagrendering has no question and is thus read-only +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/maxspeed.md b/Docs/Layers/maxspeed.md index 8ec1b834c..f0387a6db 100644 --- a/Docs/Layers/maxspeed.md +++ b/Docs/Layers/maxspeed.md @@ -30,23 +30,7 @@ Shows the allowed speed for every road - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=residential|highway=living_street|highway=motorway|highway=tertiary|highway=unclassified|highway=secondary|highway=primary|highway=trunk|highway=motorway|highway=tertiary_link|highway=secondary_link|highway=primary_link|highway=trunk_link|highway=motorway_link - - type!=multipolygon - - area!=yes - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22residential%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22living_street%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22motorway%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22tertiary%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22unclassified%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22secondary%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22primary%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22trunk%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22motorway%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22tertiary_link%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22secondary_link%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22primary_link%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22trunk_link%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22motorway_link%22%5D%5B%22area%22!%3D%22yes%22%5D%5B%22type%22!%3D%22multipolygon%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -63,11 +47,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/maxspeed#values) [maxspeed](https://wiki.openstreetmap.org/wiki/Key:maxspeed) | [pnat](../SpecialInputElements.md#pnat) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### maxspeed-maxspeed @@ -85,6 +89,62 @@ This is rendered with `The maximum allowed speed on this road is {canonical(max - *This is a living street, which has a maxspeed of 20km/h* corresponds with `highway=living_street&_country!=be` - This option cannot be chosen as answer - *This is a living street, which has a maxspeed of 20km/h* corresponds with `highway=living_street` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### split-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/maxspeed/maxspeed.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/maxspeed/maxspeed.json) diff --git a/Docs/Layers/maybe_climbing.md b/Docs/Layers/maybe_climbing.md deleted file mode 100644 index 06a2965b9..000000000 --- a/Docs/Layers/maybe_climbing.md +++ /dev/null @@ -1,346 +0,0 @@ - - - maybe_climbing -================ - - - - - -A climbing opportunity? - - - - - - - - This layer is shown at zoomlevel **19** and higher - - This layer will automatically load [climbing](./climbing.md) into the layout as it depends on it: A calculated tag loads features from this layer (calculatedTag[0] which calculates the value for _embedding_feature_properties) - - - - -#### Themes using this layer - - - - - - - [climbing](https://mapcomplete.osm.be/climbing) - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=sports_centre|barrier=wall|barrier=retaining_wall|natural=cliff|natural=rock|natural=stone - - - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22barrier%22%3D%22wall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22barrier%22%3D%22retaining_wall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22leisure%22%3D%22sports_centre%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22natural%22%3D%22cliff%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22natural%22%3D%22rock%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B!%22climbing%22%5D%5B%22natural%22%3D%22stone%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - - - - Supported attributes ----------------------- - - - -**Warning** This quick overview is incomplete - - - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/url#values) [url](https://wiki.openstreetmap.org/wiki/Key:url) | [url](../SpecialInputElements.md#url) | -[](https://taginfo.openstreetmap.org/keys/_embedding_feature:access#values) [_embedding_feature:access](https://wiki.openstreetmap.org/wiki/Key:_embedding_feature:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:_embedding_feature:access%3Dno) -[](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [permit](https://wiki.openstreetmap.org/wiki/Tag:access%3Dpermit) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [members](https://wiki.openstreetmap.org/wiki/Tag:access%3Dmembers) [no](https://wiki.openstreetmap.org/wiki/Tag:access%3Dno) -[](https://taginfo.openstreetmap.org/keys/access:description#values) [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/climbing:length#values) [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:min#values) [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/climbing:grade:french:max#values) [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/climbing:boulder#values) [climbing:boulder](https://wiki.openstreetmap.org/wiki/Key:climbing:boulder) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dno) [limited](https://wiki.openstreetmap.org/wiki/Tag:climbing:boulder%3Dlimited) -[](https://taginfo.openstreetmap.org/keys/climbing:toprope#values) [climbing:toprope](https://wiki.openstreetmap.org/wiki/Key:climbing:toprope) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:toprope%3Dno) -[](https://taginfo.openstreetmap.org/keys/climbing:sport#values) [climbing:sport](https://wiki.openstreetmap.org/wiki/Key:climbing:sport) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:sport%3Dno) -[](https://taginfo.openstreetmap.org/keys/climbing:traditional#values) [climbing:traditional](https://wiki.openstreetmap.org/wiki/Key:climbing:traditional) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:traditional%3Dno) -[](https://taginfo.openstreetmap.org/keys/climbing:speed#values) [climbing:speed](https://wiki.openstreetmap.org/wiki/Key:climbing:speed) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:climbing:speed%3Dno) - - - - -### climbing-opportunity-name - - - -_This tagrendering has no question and is thus read-only_ - - - -Only visible if `name~^..*$` is shown - - - -### climbing-possible - - - -The question is **Is climbing possible here?** - - - - - - - **Climbing is possible here** corresponds with sport=climbing - - **Climbing is not possible here** corresponds with climbing=no - - **Climbing is not possible here** corresponds with sport!~^climbing$_This option cannot be chosen as answer_ - - - - -### Website - - - -The question is **Is there a (unofficial) website with more informations (e.g. topos)?** - -This rendering asks information about the property [url](https://wiki.openstreetmap.org/wiki/Key:url) -This is rendered with `{url}` - -Only visible if `leisure!~^sports_centre$&sport=climbing` is shown - - - -### Access from containing feature - - - -_This tagrendering has no question and is thus read-only_ - - - - - - - **The containing feature states that this is publicly accessible
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=yes - - **The containing feature states that a permit is needed to access
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=permit - - **The containing feature states that this is only accessible to customers
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=customers - - **The containing feature states that this is only accessible to club members
{_embedding_feature:access:description}** corresponds with _embedding_feature:access=members - - **Not accessible as stated by the containing feature** corresponds with _embedding_feature:access=no - - -Only visible if `_embedding_feature:access~^..*$` is shown - - - -### Access - - - -The question is **Who can access here?** - - - - - - - **Publicly accessible to anyone** corresponds with access=yes - - **You need a permit to access here** corresponds with access=permit - - **Only customers** corresponds with access=customers - - **Only club members** corresponds with access=members - - **Not accessible** corresponds with access=no - - -Only visible if `climbing!~^no$&sport=climbing|climbing:sport=yes&access~^..*$|` is shown - - - -### Access description (without _embedding_feature:access:description) - - - -_This tagrendering has no question and is thus read-only_ - -This rendering asks information about the property [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) -This is rendered with `{access:description}` - - - -### Avg length? - - - -The question is **What is the (average) length of the routes in meters?** - -This rendering asks information about the property [climbing:length](https://wiki.openstreetmap.org/wiki/Key:climbing:length) -This is rendered with `The routes are {canonical(climbing:length)} long on average` - -Only visible if `climbing!~^route$&climbing:toprope!~^no$&sport=climbing|climbing:sport=yes|climbing=traditional|climbing=gym` is shown - - - -### Difficulty-min - - - -The question is **What is the grade of the easiest route here, according to the french classification system?** - -This rendering asks information about the property [climbing:grade:french:min](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:min) -This is rendered with `The lowest grade is {climbing:grade:french:min} according to the french/belgian system` - -Only visible if `climbing!~^route$&climbing:sport=yes|sport=climbing` is shown - - - -### Difficulty-max - - - -The question is **What is the highest grade route here, according to the french classification system?** - -This rendering asks information about the property [climbing:grade:french:max](https://wiki.openstreetmap.org/wiki/Key:climbing:grade:french:max) -This is rendered with `The highest grade is {climbing:grade:french:max} according to the french/belgian system` - -Only visible if `climbing!~^route$&climbing:sport=yes|sport=climbing` is shown - - - -### Boldering? - - - -The question is **Is bouldering possible here?** - - - - - - - **Bouldering is possible here** corresponds with climbing:boulder=yes - - **Bouldering is not possible here** corresponds with climbing:boulder=no - - **Bouldering is possible, allthough there are only a few routes** corresponds with climbing:boulder=limited - - **There are {climbing:boulder} boulder routes** corresponds with climbing:boulder~^..*$_This option cannot be chosen as answer_ - - -Only visible if `climbing:sport=yes|sport=climbing` is shown - - - -### Toproping? - - - -The question is **Is toprope climbing possible here?** - - - - - - - **Toprope climbing is possible here** corresponds with climbing:toprope=yes - - **Toprope climbing is not possible here** corresponds with climbing:toprope=no - - **There are {climbing:toprope} toprope routes** corresponds with climbing:toprope~^..*$_This option cannot be chosen as answer_ - - -Only visible if `climbing:sport=yes|sport=climbing` is shown - - - -### Sportclimbing? - - - -The question is **Is sport climbing possible here on fixed anchors?** - - - - - - - **Sport climbing is possible here** corresponds with climbing:sport=yes - - **Sport climbing is not possible here** corresponds with climbing:sport=no - - **There are {climbing:sport} sport climbing routes** corresponds with climbing:sport~^..*$_This option cannot be chosen as answer_ - - -Only visible if `climbing:sport=yes|sport=climbing` is shown - - - -### Traditional climbing? - - - -The question is **Is traditional climbing possible here (using own gear e.g. chocks)?** - - - - - - - **Traditional climbing is possible here** corresponds with climbing:traditional=yes - - **Traditional climbing is not possible here** corresponds with climbing:traditional=no - - **There are {climbing:traditional} traditional climbing routes** corresponds with climbing:traditional~^..*$_This option cannot be chosen as answer_ - - -Only visible if `climbing:sport=yes|sport=climbing` is shown - - - -### Speed climbing? - - - -The question is **Is there a speed climbing wall?** - - - - - - - **There is a speed climbing wall** corresponds with climbing:speed=yes - - **There is no speed climbing wall** corresponds with climbing:speed=no - - **There are {climbing:speed} speed climbing walls** corresponds with climbing:speed~^..*$_This option cannot be chosen as answer_ - - -Only visible if `leisure=sports_centre&climbing:sport=yes|sport=climbing` is shown - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - - - - -### reviews - - - -_This tagrendering has no question and is thus read-only_ - - - - - -### questions - - - -_This tagrendering has no question and is thus read-only_ - - - - - -### minimap - - - -_This tagrendering has no question and is thus read-only_ - - - -This document is autogenerated from [assets/themes/climbing/climbing.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/climbing/climbing.json) \ No newline at end of file diff --git a/Docs/Layers/medical-shops.md b/Docs/Layers/medical-shops.md index f3bb87911..0324b6812 100644 --- a/Docs/Layers/medical-shops.md +++ b/Docs/Layers/medical-shops.md @@ -5,7 +5,7 @@ - + A shop @@ -28,23 +28,7 @@ A shop - [healthcare](https://mapcomplete.osm.be/healthcare) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - shop~.+ - - shop!=mall - - shop=medical_supply|shop=hearing_aids|shop=optician - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22shop%22%3D%22medical_supply%22%5D%5B%22shop%22%5D%5B%22shop%22!%3D%22mall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22shop%22%3D%22hearing_aids%22%5D%5B%22shop%22%5D%5B%22shop%22!%3D%22mall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22shop%22%3D%22optician%22%5D%5B%22shop%22%5D%5B%22shop%22!%3D%22mall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,8 +45,8 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/shop#values) [shop](https://wiki.openstreetmap.org/wiki/Key:shop) | [string](../SpecialInputElements.md#string) | [agrarian](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dagrarian) [alcohol](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dalcohol) [anime](https://wiki.openstreetmap.org/wiki/Tag:shop%3Danime) [antiques](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dantiques) [appliance](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dappliance) [art](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dart) [baby_goods](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbaby_goods) [bag](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbag) [bakery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbakery) [bathroom_furnishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbathroom_furnishing) [beauty](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeauty) [bed](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbed) [beverages](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeverages) [bicycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbicycle) [boat](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dboat) [bookmaker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbookmaker) [books](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbooks) [brewing_supplies](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbrewing_supplies) [butcher](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbutcher) [camera](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcamera) [candles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcandles) [cannabis](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcannabis) [car](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar) [car_parts](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_parts) [car_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_repair) [caravan](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcaravan) [carpet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcarpet) [catalogue](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcatalogue) [charity](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcharity) [cheese](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcheese) [chemist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchemist) [chocolate](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchocolate) [clothes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dclothes) [coffee](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcoffee) [collector](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcollector) [computer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcomputer) [confectionery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconfectionery) [convenience](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconvenience) [copyshop](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcopyshop) [cosmetics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcosmetics) [country_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcountry_store) [craft](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcraft) [curtain](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcurtain) [dairy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddairy) [deli](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddeli) [department_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddepartment_store) [doityourself](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoityourself) [doors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoors) [dry_cleaning](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddry_cleaning) [e-cigarette](https://wiki.openstreetmap.org/wiki/Tag:shop%3De-cigarette) [electrical](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectrical) [electronics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectronics) [erotic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Derotic) [fabric](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfabric) [farm](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfarm) [fashion_accessories](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfashion_accessories) [fireplace](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfireplace) [fishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfishing) [flooring](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflooring) [florist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflorist) [frame](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dframe) [frozen_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfrozen_food) [fuel](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuel) [funeral_directors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuneral_directors) [furniture](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfurniture) [games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgames) [garden_centre](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgarden_centre) [gas](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgas) [general](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgeneral) [gift](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgift) [greengrocer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgreengrocer) [hairdresser](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser) [hairdresser_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser_supply) [hardware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhardware) [health_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhealth_food) [hearing_aids](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhearing_aids) [herbalist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dherbalist) [hifi](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhifi) [hobby](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhobby) [household_linen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhousehold_linen) [houseware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhouseware) [hunting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhunting) [interior_decoration](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dinterior_decoration) [jewelry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Djewelry) [kiosk](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkiosk) [kitchen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkitchen) [laundry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlaundry) [leather](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dleather) [lighting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlighting) [locksmith](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlocksmith) [lottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlottery) [mall](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmall) [massage](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmassage) [medical_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmedical_supply) [military_surplus](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmilitary_surplus) [mobile_phone](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmobile_phone) [model](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmodel) [money_lender](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmoney_lender) [motorcycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle) [motorcycle_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle_repair) [music](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusic) [musical_instrument](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusical_instrument) [newsagent](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnewsagent) [nutrition_supplements](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnutrition_supplements) [optician](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doptician) [outdoor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutdoor) [outpost](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutpost) [paint](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpaint) [party](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dparty) [pastry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpastry) [pawnbroker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpawnbroker) [perfumery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dperfumery) [pet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet) [pet_grooming](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet_grooming) [photo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dphoto) [pottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpottery) [printer_ink](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dprinter_ink) [psychic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpsychic) [pyrotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpyrotechnics) [radiotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dradiotechnics) [religion](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dreligion) [rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drental) [repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drepair) [scuba_diving](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dscuba_diving) [seafood](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dseafood) [second_hand](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsecond_hand) [sewing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsewing) [shoe_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoe_repair) [shoes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoes) [spices](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dspices) [sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsports) [stationery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstationery) [storage_rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstorage_rental) [supermarket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsupermarket) [swimming_pool](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dswimming_pool) [tailor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtailor) [tattoo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtattoo) [tea](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtea) [telecommunication](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtelecommunication) [ticket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dticket) [tiles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtiles) [tobacco](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtobacco) [tool_hire](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtool_hire) [toys](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtoys) [trade](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrade) [travel_agency](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtravel_agency) [trophy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrophy) [tyres](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtyres) [vacuum_cleaner](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvacuum_cleaner) [variety_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvariety_store) [video](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo) [video_games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo_games) [watches](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwatches) [water](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater) [water_sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater_sports) [weapons](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dweapons) [wholesale](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwholesale) [wigs](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwigs) [window_blind](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwindow_blind) [wine](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwine) [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -76,6 +60,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -102,184 +105,6 @@ This is rendered with `This shop is called {name}` -### shop_types - - - -The question is *What kind of shop is this?* - -This rendering asks information about the property [shop](https://wiki.openstreetmap.org/wiki/Key:shop) - -This is rendered with `This is a {shop}` - - - - - - - *Farm Supply Shop* corresponds with `shop=agrarian` - - *Liquor Store* corresponds with `shop=alcohol` - - *Anime / Manga Shop* corresponds with `shop=anime` - - *Antiques Shop* corresponds with `shop=antiques` - - *Appliance Store* corresponds with `shop=appliance` - - *Art Store* corresponds with `shop=art` - - *Baby Goods Store* corresponds with `shop=baby_goods` - - *Bag/Luggage Store* corresponds with `shop=bag` - - *Bakery* corresponds with `shop=bakery` - - *Bathroom Furnishing Store* corresponds with `shop=bathroom_furnishing` - - *Beauty Shop* corresponds with `shop=beauty` - - *Bedding/Mattress Store* corresponds with `shop=bed` - - *Beverage Store* corresponds with `shop=beverages` - - *Bicycle Shop* corresponds with `shop=bicycle` - - *Boat Store* corresponds with `shop=boat` - - *Bookmaker* corresponds with `shop=bookmaker` - - *Book Store* corresponds with `shop=books` - - *Brewing Supply Store* corresponds with `shop=brewing_supplies` - - *Butcher* corresponds with `shop=butcher` - - *Camera Equipment Store* corresponds with `shop=camera` - - *Candle Shop* corresponds with `shop=candles` - - *Cannabis Shop* corresponds with `shop=cannabis` - - *Car Dealership* corresponds with `shop=car` - - *Car Parts Store* corresponds with `shop=car_parts` - - *Car Repair Shop* corresponds with `shop=car_repair` - - *RV Dealership* corresponds with `shop=caravan` - - *Carpet Store* corresponds with `shop=carpet` - - *Catalog Shop* corresponds with `shop=catalogue` - - *Charity Store* corresponds with `shop=charity` - - *Cheese Store* corresponds with `shop=cheese` - - *Drugstore* corresponds with `shop=chemist` - - *Chocolate Store* corresponds with `shop=chocolate` - - *Clothing Store* corresponds with `shop=clothes` - - *Coffee Store* corresponds with `shop=coffee` - - *Collectibles Shop* corresponds with `shop=collector` - - *Computer Store* corresponds with `shop=computer` - - *Candy Store* corresponds with `shop=confectionery` - - *Convenience Store* corresponds with `shop=convenience` - - *Copy Store* corresponds with `shop=copyshop` - - *Cosmetics Store* corresponds with `shop=cosmetics` - - *Country Store* corresponds with `shop=country_store` - - *Arts & Crafts Store* corresponds with `shop=craft` - - *Curtain Store* corresponds with `shop=curtain` - - *Dairy Store* corresponds with `shop=dairy` - - *Deli* corresponds with `shop=deli` - - *Department Store* corresponds with `shop=department_store` - - *DIY Store* corresponds with `shop=doityourself` - - *Door Shop* corresponds with `shop=doors` - - *Dry Cleaner* corresponds with `shop=dry_cleaning` - - *E-Cigarette Shop* corresponds with `shop=e-cigarette` - - *Electrical Equipment Store* corresponds with `shop=electrical` - - *Electronics Store* corresponds with `shop=electronics` - - *Erotic Store* corresponds with `shop=erotic` - - *Fabric Store* corresponds with `shop=fabric` - - *Produce Stand* corresponds with `shop=farm` - - *Fashion Accessories Store* corresponds with `shop=fashion_accessories` - - *Fireplace Store* corresponds with `shop=fireplace` - - *Fishing Shop* corresponds with `shop=fishing` - - *Flooring Supply Shop* corresponds with `shop=flooring` - - *Florist* corresponds with `shop=florist` - - *Framing Shop* corresponds with `shop=frame` - - *Frozen Food Store* corresponds with `shop=frozen_food` - - *Fuel Shop* corresponds with `shop=fuel` - - *Funeral Home* corresponds with `shop=funeral_directors` - - *Furniture Store* corresponds with `shop=furniture` - - *Tabletop Game Store* corresponds with `shop=games` - - *Garden Center* corresponds with `shop=garden_centre` - - *Bottled Gas Shop* corresponds with `shop=gas` - - *General Store* corresponds with `shop=general` - - *Gift Shop* corresponds with `shop=gift` - - *Greengrocer* corresponds with `shop=greengrocer` - - *Hairdresser* corresponds with `shop=hairdresser` - - *Hairdresser Supply Store* corresponds with `shop=hairdresser_supply` - - *Hardware Store* corresponds with `shop=hardware` - - *Health Food Shop* corresponds with `shop=health_food` - - *Hearing Aids Store* corresponds with `shop=hearing_aids` - - *Herbalist* corresponds with `shop=herbalist` - - *Hifi Store* corresponds with `shop=hifi` - - *Hobby Shop* corresponds with `shop=hobby` - - *Household Linen Shop* corresponds with `shop=household_linen` - - *Houseware Store* corresponds with `shop=houseware` - - *Hunting Shop* corresponds with `shop=hunting` - - *Interior Decoration Store* corresponds with `shop=interior_decoration` - - *Jewelry Store* corresponds with `shop=jewelry` - - *Kiosk* corresponds with `shop=kiosk` - - *Kitchen Design Store* corresponds with `shop=kitchen` - - *Laundry* corresponds with `shop=laundry` - - *Leather Store* corresponds with `shop=leather` - - *Lighting Store* corresponds with `shop=lighting` - - *Locksmith* corresponds with `shop=locksmith` - - *Lottery Shop* corresponds with `shop=lottery` - - *Mall* corresponds with `shop=mall` - - *Massage Shop* corresponds with `shop=massage` - - *Medical Supply Store* corresponds with `shop=medical_supply` - - *Military Surplus Store* corresponds with `shop=military_surplus` - - *Mobile Phone Store* corresponds with `shop=mobile_phone` - - *Model Shop* corresponds with `shop=model` - - *Money Lender* corresponds with `shop=money_lender` - - *Motorcycle Dealership* corresponds with `shop=motorcycle` - - *Motorcycle Repair Shop* corresponds with `shop=motorcycle_repair` - - *Music Store* corresponds with `shop=music` - - *Musical Instrument Store* corresponds with `shop=musical_instrument` - - *Newspaper/Magazine Shop* corresponds with `shop=newsagent` - - *Nutrition Supplements Store* corresponds with `shop=nutrition_supplements` - - *Optician* corresponds with `shop=optician` - - *Outdoors Store* corresponds with `shop=outdoor` - - *Online Retailer Outpost* corresponds with `shop=outpost` - - *Paint Store* corresponds with `shop=paint` - - *Party Supply Store* corresponds with `shop=party` - - *Pastry Shop* corresponds with `shop=pastry` - - *Pawn Shop* corresponds with `shop=pawnbroker` - - *Perfume Store* corresponds with `shop=perfumery` - - *Pet Store* corresponds with `shop=pet` - - *Pet Grooming Store* corresponds with `shop=pet_grooming` - - *Photography Store* corresponds with `shop=photo` - - *Pottery Store* corresponds with `shop=pottery` - - *Printer Ink Store* corresponds with `shop=printer_ink` - - *Psychic* corresponds with `shop=psychic` - - *Fireworks Store* corresponds with `shop=pyrotechnics` - - *Radio/Electronic Component Store* corresponds with `shop=radiotechnics` - - *Religious Store* corresponds with `shop=religion` - - *Rental Shop* corresponds with `shop=rental` - - *Repair Shop* corresponds with `shop=repair` - - *Scuba Diving Shop* corresponds with `shop=scuba_diving` - - *Seafood Shop* corresponds with `shop=seafood` - - *Consignment/Thrift Store* corresponds with `shop=second_hand` - - *Sewing Supply Shop* corresponds with `shop=sewing` - - *Shoe Repair Shop* corresponds with `shop=shoe_repair` - - *Shoe Store* corresponds with `shop=shoes` - - *Spice Shop* corresponds with `shop=spices` - - *Sporting Goods Store* corresponds with `shop=sports` - - *Stationery Store* corresponds with `shop=stationery` - - *Storage Rental* corresponds with `shop=storage_rental` - - *Supermarket* corresponds with `shop=supermarket` - - *Pool Supply Store* corresponds with `shop=swimming_pool` - - *Tailor* corresponds with `shop=tailor` - - *Tattoo Parlor* corresponds with `shop=tattoo` - - *Tea Store* corresponds with `shop=tea` - - *Telecom Retail Store* corresponds with `shop=telecommunication` - - *Ticket Seller* corresponds with `shop=ticket` - - *Tile Shop* corresponds with `shop=tiles` - - *Tobacco Shop* corresponds with `shop=tobacco` - - *Tool Rental* corresponds with `shop=tool_hire` - - *Toy Store* corresponds with `shop=toys` - - *Trade Shop* corresponds with `shop=trade` - - *Travel Agency* corresponds with `shop=travel_agency` - - *Trophy Shop* corresponds with `shop=trophy` - - *Tire Store* corresponds with `shop=tyres` - - *Vacuum Cleaner Store* corresponds with `shop=vacuum_cleaner` - - *Variety Store* corresponds with `shop=variety_store` - - *Video Store* corresponds with `shop=video` - - *Video Game Store* corresponds with `shop=video_games` - - *Watches Shop* corresponds with `shop=watches` - - *Drinking Water Shop* corresponds with `shop=water` - - *Watersport/Swim Shop* corresponds with `shop=water_sports` - - *Weapon Shop* corresponds with `shop=weapons` - - *Wholesale Store* corresponds with `shop=wholesale` - - *Wig Shop* corresponds with `shop=wigs` - - *Window Blind Store* corresponds with `shop=window_blind` - - *Wine Shop* corresponds with `shop=wine` - - - - ### opening_hours @@ -514,6 +339,8 @@ This tagrendering is only visible in the popup if the following condition is met +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -532,11 +359,11 @@ This tagrendering has no question and is thus read-only -### questions +### minimap -Show the images block at this location +Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only @@ -544,11 +371,43 @@ This tagrendering has no question and is thus read-only -### minimap +### move-button -Shows a small map with the feature. Added by default to every popup +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + This tagrendering has no question and is thus read-only diff --git a/Docs/Layers/named_streets.md b/Docs/Layers/named_streets.md index e569b7b11..4a4838cf8 100644 --- a/Docs/Layers/named_streets.md +++ b/Docs/Layers/named_streets.md @@ -23,22 +23,7 @@ Hidden layer with all streets which have a name. Useful to detect addresses - This layer is needed as dependency for layer [address](#address) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway~.+ - - name~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22name%22%5D%5B%22highway%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap diff --git a/Docs/Layers/nature_reserve.md b/Docs/Layers/nature_reserve.md index 1c85e06b9..ab54b49b6 100644 --- a/Docs/Layers/nature_reserve.md +++ b/Docs/Layers/nature_reserve.md @@ -29,21 +29,7 @@ A nature reserve is an area where nature can take its course - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=nature_reserve|protect_class!=98&boundary=protected_area - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22nature_reserve%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22boundary%22%3D%22protected_area%22%5D%5B%22protect_class%22!%3D%2298%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/access:description#values) [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [Natuurpunt](https://wiki.openstreetmap.org/wiki/Tag:operator%3DNatuurpunt) [Agentschap Natuur en Bos](https://wiki.openstreetmap.org/wiki/Tag:operator%3DAgentschap Natuur en Bos) [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:name%3D) @@ -75,6 +62,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -297,6 +303,52 @@ This is rendered with `{wikipedia():max-height:25rem}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/note.md b/Docs/Layers/note.md new file mode 100644 index 000000000..ddc2d44cc --- /dev/null +++ b/Docs/Layers/note.md @@ -0,0 +1,265 @@ +[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources) + + note +====== + + + + + +This layer shows notes on OpenStreetMap. Having this layer in your theme will trigger the 'add new note' functionality in the 'addNewPoint'-popup (or if your theme has no presets, it'll enable adding notes) + + + + + + + - This layer is shown at zoomlevel **10** and higher + - This layer is loaded from an external source, namely `https://api.openstreetmap.org/api/0.6/notes.json?limit=10000&closed=7&bbox={x_min},{y_min},{x_max},{y_max}` + + + + +#### Themes using this layer + + + + + + - [notes](https://mapcomplete.osm.be/notes) + - [personal](https://mapcomplete.osm.be/personal) + + +This is a special layer - data is not sourced from OpenStreetMap + + + + Supported attributes +---------------------- + + + +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### conversation + + + +This tagrendering has no question and is thus read-only + + + + + +### add_image + + + +This tagrendering has no question and is thus read-only + + + + + +### comment + + + +This tagrendering has no question and is thus read-only + + + + + +### nearby-images + + + +This tagrendering has no question and is thus read-only + + + + + +### report-contributor + + + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_opened_by_anonymous_user=false` + + + +### report-note + + + +This tagrendering has no question and is thus read-only + + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + +#### Filters + + + + + +id | question | osmTags | fields +---- | ---------- | --------- | -------- +search.0 | Should mention {search} in the first comment | | search (string) + + + + +id | question | osmTags | fields +---- | ---------- | --------- | -------- +not.0 | Should not mention {search} in the first comment | | search (string) + + + + +id | question | osmTags | fields +---- | ---------- | --------- | -------- +opened_by.0 | Opened by contributor {search} | | search (string) + + + + +id | question | osmTags | fields +---- | ---------- | --------- | -------- +not_opened_by.0 | Not opened by contributor {search} | | search (string) + + + + +id | question | osmTags | fields +---- | ---------- | --------- | -------- +edited_by.0 | Last edited by contributor {search} | | search (string) + + + + +id | question | osmTags | fields +---- | ---------- | --------- | -------- +not_edited_by.0 | Opened after {search} | | search (string) + + + + +id | question | osmTags | fields +---- | ---------- | --------- | -------- +opened_before.0 | Created before {search} | | search (date) + + + + +id | question | osmTags | fields +---- | ---------- | --------- | -------- +opened_after.0 | Created after {search} | | search (date) + + + + +id | question | osmTags +---- | ---------- | --------- +anonymous.0 | Only show notes opened by an anonymous contributor | _opened_by_anonymous_user=true + + + + +id | question | osmTags +---- | ---------- | --------- +is_open.0 | Only show open notes | + + + + +id | question | osmTags +---- | ---------- | --------- +no_imports.0 | All Notes (default) | +no_imports.1 | Hide import notes | +no_imports.2 | Show only import Notes | _is_import_note~.+ + + +This document is autogenerated from [assets/layers/note/note.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/note/note.json) diff --git a/Docs/Layers/note_import.md b/Docs/Layers/note_import.md deleted file mode 100644 index ac3a9f5f4..000000000 --- a/Docs/Layers/note_import.md +++ /dev/null @@ -1,126 +0,0 @@ - - - note_import -============= - - - - - -Template for note note imports. - - - - - - - - This layer is shown at zoomlevel **10** and higher - - This layer is loaded from an external source, namely `https://api.openstreetmap.org/api/0.6/notes.json?closed=0&bbox={x_min},{y_min},{x_max},{y_max}` - - This layer will automatically load [public_bookcase](./public_bookcase.md) into the layout as it depends on it: a tagrendering needs this layer (import) - - - - -#### Themes using this layer - - - - - - - [personal](https://mapcomplete.osm.be/personal) - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - id~^..*$ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22id%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - - - - Supported attributes ----------------------- - - - - - -### conversation - - - -This tagrendering has no question and is thus read-only - - - - - -### Intro - - - -This tagrendering has no question and is thus read-only - - - - - -### import - - - -This tagrendering has no question and is thus read-only - - - - - -### close_note_ - - - -This tagrendering has no question and is thus read-only - - - - - -### close_note_mapped - - - -This tagrendering has no question and is thus read-only - - - - - -### comment - - - -This tagrendering has no question and is thus read-only - - - - - -### add_image - - - -This tagrendering has no question and is thus read-only - - - -This document is autogenerated from [assets/layers/note_import/note_import.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/note_import/note_import.json) \ No newline at end of file diff --git a/Docs/Layers/observation_tower.md b/Docs/Layers/observation_tower.md index 316e7c2ec..73eabf887 100644 --- a/Docs/Layers/observation_tower.md +++ b/Docs/Layers/observation_tower.md @@ -29,21 +29,7 @@ Towers with a panoramic view - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - tower:type=observation - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22tower%3Atype%22%3D%22observation%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/height#values) [height](https://wiki.openstreetmap.org/wiki/Key:height) | [pfloat](../SpecialInputElements.md#pfloat) | [](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [guided](https://wiki.openstreetmap.org/wiki/Tag:access%3Dguided) @@ -74,6 +61,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -288,6 +294,62 @@ This is rendered with `{wikipedia():max-height:25rem}` - This option cannot be chosen as answer - *No Wikipedia page has been linked yet* corresponds with `` - This option cannot be chosen as answer + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/observation_tower/observation_tower.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/observation_tower/observation_tower.json) diff --git a/Docs/Layers/osm_community_index.md b/Docs/Layers/osm_community_index.md index 96d27a025..6d0ad0c86 100644 --- a/Docs/Layers/osm_community_index.md +++ b/Docs/Layers/osm_community_index.md @@ -30,21 +30,7 @@ A layer showing the OpenStreetMap Communities - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - resources~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22resources%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -53,6 +39,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### country_name @@ -83,6 +99,52 @@ This tagrendering is only visible in the popup if the following condition is met +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/parcel_lockers.md b/Docs/Layers/parcel_lockers.md index 912d77909..9d10ff575 100644 --- a/Docs/Layers/parcel_lockers.md +++ b/Docs/Layers/parcel_lockers.md @@ -29,21 +29,7 @@ Layer showing parcel lockers for collecting and sending parcels. - [postboxes](https://mapcomplete.osm.be/postboxes) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=parcel_locker|amenity=vending_machine&vending=parcel_pickup;parcel_mail_in - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22parcel_locker%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22vending_machine%22%5D%5B%22vending%22%3D%22parcel_pickup%3Bparcel_mail_in%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/brand#values) [brand](https://wiki.openstreetmap.org/wiki/Key:brand) | [string](../SpecialInputElements.md#string) | [Amazon Locker](https://wiki.openstreetmap.org/wiki/Tag:brand%3DAmazon Locker) [DHL Packstation](https://wiki.openstreetmap.org/wiki/Tag:brand%3DDHL Packstation) [Pickup Station](https://wiki.openstreetmap.org/wiki/Tag:brand%3DPickup Station) [PostNL](https://wiki.openstreetmap.org/wiki/Tag:brand%3DPostNL) [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [24/7](https://wiki.openstreetmap.org/wiki/Tag:opening_hours%3D24/7) @@ -70,6 +57,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -187,6 +193,72 @@ This tagrendering is only visible in the popup if the following condition is met +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/parking.md b/Docs/Layers/parking.md index 8f1ca4fda..70275edc7 100644 --- a/Docs/Layers/parking.md +++ b/Docs/Layers/parking.md @@ -31,21 +31,7 @@ A layer showing car parkings - [transit](https://mapcomplete.osm.be/transit) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=parking - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22parking%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,6 +48,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/parking#values) [parking](https://wiki.openstreetmap.org/wiki/Key:parking) | Multiple choice | [surface](https://wiki.openstreetmap.org/wiki/Tag:parking%3Dsurface) [street_side](https://wiki.openstreetmap.org/wiki/Tag:parking%3Dstreet_side) [underground](https://wiki.openstreetmap.org/wiki/Tag:parking%3Dunderground) [multi-storey](https://wiki.openstreetmap.org/wiki/Tag:parking%3Dmulti-storey) [rooftop](https://wiki.openstreetmap.org/wiki/Tag:parking%3Drooftop) [lane](https://wiki.openstreetmap.org/wiki/Tag:parking%3Dlane) [carports](https://wiki.openstreetmap.org/wiki/Tag:parking%3Dcarports) [garage_boxes](https://wiki.openstreetmap.org/wiki/Tag:parking%3Dgarage_boxes) [layby](https://wiki.openstreetmap.org/wiki/Tag:parking%3Dlayby) [sheds](https://wiki.openstreetmap.org/wiki/Tag:parking%3Dsheds) [](https://taginfo.openstreetmap.org/keys/capacity:disabled#values) [capacity:disabled](https://wiki.openstreetmap.org/wiki/Key:capacity:disabled) | [pnat](../SpecialInputElements.md#pnat) | [0](https://wiki.openstreetmap.org/wiki/Tag:capacity:disabled%3D0) @@ -70,6 +57,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -164,6 +170,72 @@ This rendering asks information about the property [capacity](https://wiki.open This is rendered with `There are {capacity} parking spots` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/parking/parking.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/parking/parking.json) diff --git a/Docs/Layers/parking_spaces.md b/Docs/Layers/parking_spaces.md index 368ea9d98..e64347ea3 100644 --- a/Docs/Layers/parking_spaces.md +++ b/Docs/Layers/parking_spaces.md @@ -30,21 +30,7 @@ Layer showing individual parking spaces. - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=parking_space - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22parking_space%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,12 +47,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/parking_space#values) [parking_space](https://wiki.openstreetmap.org/wiki/Key:parking_space) | Multiple choice | [normal](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dnormal) [disabled](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Ddisabled) [private](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dprivate) [charging](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dcharging) [delivery](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Ddelivery) [hgv](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dhgv) [caravan](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dcaravan) [bus](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dbus) [motorcycle](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dmotorcycle) [parent](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dparent) [staff](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dstaff) [taxi](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dtaxi) [trailer](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dtrailer) [car_sharing](https://wiki.openstreetmap.org/wiki/Tag:parking_space%3Dcar_sharing) [](https://taginfo.openstreetmap.org/keys/capacity#values) [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) | Multiple choice | [1](https://wiki.openstreetmap.org/wiki/Tag:capacity%3D1) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -120,6 +126,52 @@ This tagrendering has no question and is thus read-only - *This parking space has 1 space.* corresponds with `capacity=1` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/parking_spaces/parking_spaces.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/parking_spaces/parking_spaces.json) diff --git a/Docs/Layers/parking_ticket_machine.md b/Docs/Layers/parking_ticket_machine.md index 08d29e67e..f2ffe3c09 100644 --- a/Docs/Layers/parking_ticket_machine.md +++ b/Docs/Layers/parking_ticket_machine.md @@ -29,22 +29,7 @@ Layer with parking ticket machines to pay for parking. - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=vending_machine - - vending=parking_tickets - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22vending_machine%22%5D%5B%22vending%22%3D%22parking_tickets%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/payment:coins:denominations#values) [payment:coins:denominations](https://wiki.openstreetmap.org/wiki/Key:payment:coins:denominations) | Multiple choice | [0.01 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.01 EUR) [0.02 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.02 EUR) [0.05 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.05 EUR) [0.10 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.10 EUR) [0.20 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.20 EUR) [0.50 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.50 EUR) [1 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D1 EUR) [2 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D2 EUR) [](https://taginfo.openstreetmap.org/keys/payment:notes:denominations#values) [payment:notes:denominations](https://wiki.openstreetmap.org/wiki/Key:payment:notes:denominations) | Multiple choice | [5 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:notes:denominations%3D5 EUR) [10 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:notes:denominations%3D10 EUR) [20 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:notes:denominations%3D20 EUR) [50 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:notes:denominations%3D50 EUR) [100 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:notes:denominations%3D100 EUR) [200 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:notes:denominations%3D200 EUR) [500 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:notes:denominations%3D500 EUR) [](https://taginfo.openstreetmap.org/keys/ref#values) [ref](https://wiki.openstreetmap.org/wiki/Key:ref) | [string](../SpecialInputElements.md#string) | @@ -68,6 +54,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -172,6 +177,52 @@ This is rendered with `This parking ticket machine has the reference number {re - *This parking ticket machine has no reference number* corresponds with `noref=yes` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/parking_ticket_machine/parking_ticket_machine.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/parking_ticket_machine/parking_ticket_machine.json) diff --git a/Docs/Layers/parks_and_forests_without_etymology.md b/Docs/Layers/parks_and_forests_without_etymology.md index 228a8c9dd..b3c413f35 100644 --- a/Docs/Layers/parks_and_forests_without_etymology.md +++ b/Docs/Layers/parks_and_forests_without_etymology.md @@ -28,22 +28,7 @@ All objects which have an etymology known - [etymology](https://mapcomplete.osm.be/etymology) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - name~.+ - - leisure=park|landuse=forest - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22landuse%22%3D%22forest%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22leisure%22%3D%22park%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +45,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) | [](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### etymology-images-from-wikipedia @@ -125,6 +130,8 @@ This is rendered with `Named after {name:etymology}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -169,6 +176,30 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` +This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) diff --git a/Docs/Layers/pedestrian_path.md b/Docs/Layers/pedestrian_path.md index 4fe6acc64..1eb55f900 100644 --- a/Docs/Layers/pedestrian_path.md +++ b/Docs/Layers/pedestrian_path.md @@ -32,21 +32,7 @@ Pedestrian footpaths, especially used for indoor navigation and snapping entranc - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=footway|highway=path|highway=corridor|highway=steps - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22footway%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22path%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22corridor%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22steps%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap diff --git a/Docs/Layers/pharmacy.md b/Docs/Layers/pharmacy.md index 60849142e..215a6ab48 100644 --- a/Docs/Layers/pharmacy.md +++ b/Docs/Layers/pharmacy.md @@ -31,21 +31,7 @@ A layer showing pharmacies, which (probably) dispense prescription drugs - [shops](https://mapcomplete.osm.be/shops) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=pharmacy - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22pharmacy%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,6 +48,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | @@ -72,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -195,6 +201,72 @@ The question is *Is this pharmacy easy to access on a wheelchair?* +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/physiotherapist.md b/Docs/Layers/physiotherapist.md index 406a93dcd..38cec9a0c 100644 --- a/Docs/Layers/physiotherapist.md +++ b/Docs/Layers/physiotherapist.md @@ -29,21 +29,7 @@ This layer shows physiotherapists - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - healthcare=physiotherapist - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22healthcare%22%3D%22physiotherapist%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | ["by appointment"](https://wiki.openstreetmap.org/wiki/Tag:opening_hours%3D"by appointment") [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | @@ -69,6 +56,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -182,6 +188,72 @@ This tagrendering has labels `contact` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/picnic_table.md b/Docs/Layers/picnic_table.md index 0b85393da..2bbad1f45 100644 --- a/Docs/Layers/picnic_table.md +++ b/Docs/Layers/picnic_table.md @@ -30,21 +30,7 @@ The layer showing picnic tables - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=picnic_table - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22picnic_table%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,12 +47,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/material#values) [material](https://wiki.openstreetmap.org/wiki/Key:material) | [string](../SpecialInputElements.md#string) | [wood](https://wiki.openstreetmap.org/wiki/Tag:material%3Dwood) [concrete](https://wiki.openstreetmap.org/wiki/Tag:material%3Dconcrete) [plastic](https://wiki.openstreetmap.org/wiki/Tag:material%3Dplastic) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -121,6 +127,72 @@ This is rendered with `This picnic table is made of {material}` - *This is a wooden picnic table* corresponds with `material=wood` - *This is a concrete picnic table* corresponds with `material=concrete` - *This picnic table is made from (recycled) plastic* corresponds with `material=plastic` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/picnic_table/picnic_table.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/picnic_table/picnic_table.json) diff --git a/Docs/Layers/play_forest.md b/Docs/Layers/play_forest.md index f9bda4db2..f9d35f96e 100644 --- a/Docs/Layers/play_forest.md +++ b/Docs/Layers/play_forest.md @@ -17,21 +17,7 @@ Een speelbos is een vrij toegankelijke zone in een bos - This layer is shown at zoomlevel **13** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - playground=forest - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22playground%22%3D%22forest%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -48,6 +34,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [Agenstchap Natuur en Bos](https://wiki.openstreetmap.org/wiki/Tag:operator%3DAgenstchap Natuur en Bos) [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | Multiple choice | [08:00-22:00](https://wiki.openstreetmap.org/wiki/Tag:opening_hours%3D08:00-22:00) [Jul-Aug 08:00-22:00](https://wiki.openstreetmap.org/wiki/Tag:opening_hours%3DJul-Aug 08:00-22:00) [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -56,6 +43,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -137,6 +143,8 @@ This is rendered with `De bevoegde dienst kan getelefoneerd worden via {phone}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -149,6 +157,42 @@ This tagrendering has no question and is thus read-only This tagrendering has no question and is thus read-only + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/play_forest/play_forest.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/play_forest/play_forest.json) diff --git a/Docs/Layers/playground.md b/Docs/Layers/playground.md index 150f515ed..f2ccfffd0 100644 --- a/Docs/Layers/playground.md +++ b/Docs/Layers/playground.md @@ -29,22 +29,7 @@ Playgrounds - [playgrounds](https://mapcomplete.osm.be/playgrounds) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=playground - - playground!=forest - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22playground%22%5D%5B%22playground%22!%3D%22forest%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/surface#values) [surface](https://wiki.openstreetmap.org/wiki/Key:surface) | [string](../SpecialInputElements.md#string) | [grass](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dgrass) [sand](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dsand) [woodchips](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dwoodchips) [paving_stones](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dpaving_stones) [asphalt](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dasphalt) [concrete](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dconcrete) [](https://taginfo.openstreetmap.org/keys/lit#values) [lit](https://wiki.openstreetmap.org/wiki/Key:lit) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dno) [](https://taginfo.openstreetmap.org/keys/min_age#values) [min_age](https://wiki.openstreetmap.org/wiki/Key:min_age) | [pnat](../SpecialInputElements.md#pnat) | @@ -75,6 +61,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -291,6 +296,8 @@ This is rendered with `{opening_hours_table(opening_hours)}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -303,6 +310,52 @@ This tagrendering has no question and is thus read-only This tagrendering has no question and is thus read-only + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/playground/playground.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/playground/playground.json) diff --git a/Docs/Layers/postboxes.md b/Docs/Layers/postboxes.md index ef3f20058..1fbe7c0c1 100644 --- a/Docs/Layers/postboxes.md +++ b/Docs/Layers/postboxes.md @@ -29,21 +29,7 @@ The layer showing postboxes. - [postboxes](https://mapcomplete.osm.be/postboxes) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=post_box - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22post_box%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -52,6 +38,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### images @@ -72,6 +88,50 @@ This tagrendering has no question and is thus read-only This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/postboxes/postboxes.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/postboxes/postboxes.json) diff --git a/Docs/Layers/postoffices.md b/Docs/Layers/postoffices.md index 343ce9fca..7f618b5c6 100644 --- a/Docs/Layers/postoffices.md +++ b/Docs/Layers/postoffices.md @@ -29,21 +29,7 @@ A layer showing post offices. - [postboxes](https://mapcomplete.osm.be/postboxes) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=post_office|post_office=post_partner - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22post_office%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22post_office%22%3D%22post_partner%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/post_office#values) [post_office](https://wiki.openstreetmap.org/wiki/Key:post_office) | Multiple choice | [post_partner](https://wiki.openstreetmap.org/wiki/Tag:post_office%3Dpost_partner) [](https://wiki.openstreetmap.org/wiki/Tag:post_office%3D) [](https://taginfo.openstreetmap.org/keys/post_office:brand#values) [post_office:brand](https://wiki.openstreetmap.org/wiki/Key:post_office:brand) | [string](../SpecialInputElements.md#string) | [DHL](https://wiki.openstreetmap.org/wiki/Tag:post_office:brand%3DDHL) [DPD](https://wiki.openstreetmap.org/wiki/Tag:post_office:brand%3DDPD) [GLS](https://wiki.openstreetmap.org/wiki/Tag:post_office:brand%3DGLS) [UPS](https://wiki.openstreetmap.org/wiki/Tag:post_office:brand%3DUPS) [DHL Paketshop](https://wiki.openstreetmap.org/wiki/Tag:post_office:brand%3DDHL Paketshop) [Hermes PaketShop](https://wiki.openstreetmap.org/wiki/Tag:post_office:brand%3DHermes PaketShop) [PostNL](https://wiki.openstreetmap.org/wiki/Tag:post_office:brand%3DPostNL) [bpost](https://wiki.openstreetmap.org/wiki/Tag:post_office:brand%3Dbpost) @@ -72,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -254,6 +260,40 @@ This is rendered with `You can buy stamps from companies: {post_office:stamps}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/public_bookcase.md b/Docs/Layers/public_bookcase.md index 1f1ccf708..b28df90fc 100644 --- a/Docs/Layers/public_bookcase.md +++ b/Docs/Layers/public_bookcase.md @@ -5,7 +5,7 @@ - + A streetside cabinet with books, accessible to anyone @@ -29,21 +29,7 @@ A streetside cabinet with books, accessible to anyone - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=public_bookcase - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22public_bookcase%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:name%3D) [](https://taginfo.openstreetmap.org/keys/capacity#values) [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) | [nat](../SpecialInputElements.md#nat) | [](https://taginfo.openstreetmap.org/keys/books#values) [books](https://wiki.openstreetmap.org/wiki/Key:books) | [string](../SpecialInputElements.md#string) | [children](https://wiki.openstreetmap.org/wiki/Tag:books%3Dchildren) [adults](https://wiki.openstreetmap.org/wiki/Tag:books%3Dadults) @@ -74,6 +61,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -258,6 +264,72 @@ This is rendered with `More info on the web +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/railway_platforms.md b/Docs/Layers/railway_platforms.md index 8a7ff8179..b25ec6734 100644 --- a/Docs/Layers/railway_platforms.md +++ b/Docs/Layers/railway_platforms.md @@ -17,21 +17,7 @@ Find every platform in the station, and the train routes that use them. - This layer is shown at zoomlevel **18** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - railway=platform - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22railway%22%3D%22platform%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -48,12 +34,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/ref#values) [ref](https://wiki.openstreetmap.org/wiki/Key:ref) | [string](../SpecialInputElements.md#string) | [](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) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### ref @@ -89,6 +95,52 @@ This is rendered with `Located on the {level}th floor` - 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` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/railway_platforms/railway_platforms.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/railway_platforms/railway_platforms.json) diff --git a/Docs/Layers/rainbow_crossing_high_zoom.md b/Docs/Layers/rainbow_crossing_high_zoom.md index 42b883275..fe3035c2d 100644 --- a/Docs/Layers/rainbow_crossing_high_zoom.md +++ b/Docs/Layers/rainbow_crossing_high_zoom.md @@ -29,22 +29,7 @@ A layer showing pedestrian crossings with rainbow paintings - [rainbow_crossings](https://mapcomplete.osm.be/rainbow_crossings) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=crossing - - surface:colour=rainbow - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22surface%3Acolour%22%3D%22rainbow%22%5D%5B%22highway%22%3D%22crossing%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -53,6 +38,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### images @@ -83,16 +98,14 @@ The question is *Does this crossing has rainbow paintings?* - This option cannot be chosen as answer -This tagrendering is only visible in the popup if the following condition is met: `highway=crossing` +This tagrendering is only visible in the popup if the following condition is met: `footway=crossing` -### questions +### leftover-questions -Show the images block at this location - This tagrendering has no question and is thus read-only @@ -107,6 +120,30 @@ Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/themes/rainbow_crossings/rainbow_crossings.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/rainbow_crossings/rainbow_crossings.json) diff --git a/Docs/Layers/rainbow_crossings.md b/Docs/Layers/rainbow_crossings.md index 6e2babfd0..d97a333d7 100644 --- a/Docs/Layers/rainbow_crossings.md +++ b/Docs/Layers/rainbow_crossings.md @@ -30,21 +30,7 @@ A layer showing pedestrian crossings with rainbow paintings - [rainbow_crossings](https://mapcomplete.osm.be/rainbow_crossings) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=crossing - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22crossing%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -53,6 +39,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### images @@ -83,6 +99,52 @@ The question is *Does this crossing has rainbow paintings?* - This option cannot be chosen as answer -This tagrendering is only visible in the popup if the following condition is met: `highway=crossing` +This tagrendering is only visible in the popup if the following condition is met: `footway=crossing` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/rainbow_crossings/rainbow_crossings.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/rainbow_crossings/rainbow_crossings.json) diff --git a/Docs/Layers/reception_desk.md b/Docs/Layers/reception_desk.md index 625bb3928..1c080dbab 100644 --- a/Docs/Layers/reception_desk.md +++ b/Docs/Layers/reception_desk.md @@ -29,21 +29,7 @@ A layer showing where the reception desks are and which asks some accessibility - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=reception_desk - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22reception_desk%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/desk:height#values) [desk:height](https://wiki.openstreetmap.org/wiki/Key:desk:height) | [pfloat](../SpecialInputElements.md#pfloat) | [](https://taginfo.openstreetmap.org/keys/hearing_loop#values) [hearing_loop](https://wiki.openstreetmap.org/wiki/Key:hearing_loop) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:hearing_loop%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:hearing_loop%3Dno) @@ -67,6 +54,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -132,6 +138,52 @@ The question is *Does this place have an audio induction loop for people with r - *This place has an audio induction loop* corresponds with `hearing_loop=yes` - *This place does not have an audio induction loop* corresponds with `hearing_loop=no` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/reception_desk/reception_desk.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/reception_desk/reception_desk.json) diff --git a/Docs/Layers/recycling.md b/Docs/Layers/recycling.md index 799331b7e..c81c04ffa 100644 --- a/Docs/Layers/recycling.md +++ b/Docs/Layers/recycling.md @@ -14,7 +14,7 @@ A layer with recycling containers and centres - - This layer is shown at zoomlevel **12** and higher + - This layer is shown at zoomlevel **11** and higher @@ -29,21 +29,7 @@ A layer with recycling containers and centres - [waste](https://mapcomplete.osm.be/waste) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=recycling - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22recycling%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/location#values) [location](https://wiki.openstreetmap.org/wiki/Key:location) | Multiple choice | [underground](https://wiki.openstreetmap.org/wiki/Tag:location%3Dunderground) [indoor](https://wiki.openstreetmap.org/wiki/Tag:location%3Dindoor) [](https://wiki.openstreetmap.org/wiki/Tag:location%3D) [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | @@ -72,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -335,6 +341,72 @@ This is rendered with `This recycling facility can be used by {access}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/school.md b/Docs/Layers/school.md index 9b7660c43..151cee4a4 100644 --- a/Docs/Layers/school.md +++ b/Docs/Layers/school.md @@ -15,8 +15,6 @@ Schools giving primary and secondary education and post-secondary, non-tertiary - 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) @@ -31,21 +29,7 @@ Schools giving primary and secondary education and post-secondary, non-tertiary - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=school - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22school%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/capacity#values) [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) | [pnat](../SpecialInputElements.md#pnat) | [](https://taginfo.openstreetmap.org/keys/school#values) [school](https://wiki.openstreetmap.org/wiki/Key:school) | Multiple choice | [kindergarten](https://wiki.openstreetmap.org/wiki/Tag:school%3Dkindergarten) [primary](https://wiki.openstreetmap.org/wiki/Tag:school%3Dprimary) [secondary](https://wiki.openstreetmap.org/wiki/Tag:school%3Dsecondary) [lower_secondary](https://wiki.openstreetmap.org/wiki/Tag:school%3Dlower_secondary) [middle_secondary](https://wiki.openstreetmap.org/wiki/Tag:school%3Dmiddle_secondary) [upper_secondary](https://wiki.openstreetmap.org/wiki/Tag:school%3Dupper_secondary) [post_secondary](https://wiki.openstreetmap.org/wiki/Tag:school%3Dpost_secondary) @@ -74,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### school-name @@ -245,6 +249,52 @@ This tagrendering has labels `contact` This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/school/school.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/school/school.json) diff --git a/Docs/Layers/shelter.md b/Docs/Layers/shelter.md index 5137638de..5036983b8 100644 --- a/Docs/Layers/shelter.md +++ b/Docs/Layers/shelter.md @@ -29,21 +29,7 @@ Layer showing shelter structures - [transit](https://mapcomplete.osm.be/transit) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=shelter - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22shelter%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,11 +46,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/shelter_type#values) [shelter_type](https://wiki.openstreetmap.org/wiki/Key:shelter_type) | [string](../SpecialInputElements.md#string) | [public_transport](https://wiki.openstreetmap.org/wiki/Tag:shelter_type%3Dpublic_transport) [picnic_shelter](https://wiki.openstreetmap.org/wiki/Tag:shelter_type%3Dpicnic_shelter) [gazebo](https://wiki.openstreetmap.org/wiki/Tag:shelter_type%3Dgazebo) [weather_shelter](https://wiki.openstreetmap.org/wiki/Tag:shelter_type%3Dweather_shelter) [lean_to](https://wiki.openstreetmap.org/wiki/Tag:shelter_type%3Dlean_to) [pavilion](https://wiki.openstreetmap.org/wiki/Tag:shelter_type%3Dpavilion) [basic_hut](https://wiki.openstreetmap.org/wiki/Tag:shelter_type%3Dbasic_hut) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### shelter-type @@ -86,6 +92,52 @@ This is rendered with `Shelter type: {shelter_type}` - *This is a shed with 3 walls, primarily intended for camping.* corresponds with `shelter_type=lean_to` - *This is a pavilion* corresponds with `shelter_type=pavilion` - *This is a basic hut, providing basic shelter and sleeping facilities.* corresponds with `shelter_type=basic_hut` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/shelter/shelter.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/shelter/shelter.json) diff --git a/Docs/Layers/shops.md b/Docs/Layers/shops.md index 035a080fb..2a13b2ebc 100644 --- a/Docs/Layers/shops.md +++ b/Docs/Layers/shops.md @@ -5,7 +5,7 @@ - + A shop @@ -14,7 +14,7 @@ A shop - - This layer is shown at zoomlevel **16** and higher + - This layer is shown at zoomlevel **12** and higher @@ -32,22 +32,7 @@ A shop - [shops](https://mapcomplete.osm.be/shops) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - shop~.+ - - shop!=mall - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22shop%22%5D%5B%22shop%22!%3D%22mall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -64,8 +49,8 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/shop#values) [shop](https://wiki.openstreetmap.org/wiki/Key:shop) | [string](../SpecialInputElements.md#string) | [agrarian](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dagrarian) [alcohol](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dalcohol) [anime](https://wiki.openstreetmap.org/wiki/Tag:shop%3Danime) [antiques](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dantiques) [appliance](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dappliance) [art](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dart) [baby_goods](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbaby_goods) [bag](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbag) [bakery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbakery) [bathroom_furnishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbathroom_furnishing) [beauty](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeauty) [bed](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbed) [beverages](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeverages) [bicycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbicycle) [boat](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dboat) [bookmaker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbookmaker) [books](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbooks) [brewing_supplies](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbrewing_supplies) [butcher](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbutcher) [camera](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcamera) [candles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcandles) [cannabis](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcannabis) [car](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar) [car_parts](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_parts) [car_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_repair) [caravan](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcaravan) [carpet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcarpet) [catalogue](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcatalogue) [charity](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcharity) [cheese](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcheese) [chemist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchemist) [chocolate](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchocolate) [clothes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dclothes) [coffee](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcoffee) [collector](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcollector) [computer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcomputer) [confectionery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconfectionery) [convenience](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconvenience) [copyshop](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcopyshop) [cosmetics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcosmetics) [country_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcountry_store) [craft](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcraft) [curtain](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcurtain) [dairy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddairy) [deli](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddeli) [department_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddepartment_store) [doityourself](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoityourself) [doors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoors) [dry_cleaning](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddry_cleaning) [e-cigarette](https://wiki.openstreetmap.org/wiki/Tag:shop%3De-cigarette) [electrical](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectrical) [electronics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectronics) [erotic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Derotic) [fabric](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfabric) [farm](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfarm) [fashion_accessories](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfashion_accessories) [fireplace](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfireplace) [fishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfishing) [flooring](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflooring) [florist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflorist) [frame](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dframe) [frozen_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfrozen_food) [fuel](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuel) [funeral_directors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuneral_directors) [furniture](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfurniture) [games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgames) [garden_centre](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgarden_centre) [gas](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgas) [general](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgeneral) [gift](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgift) [greengrocer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgreengrocer) [hairdresser](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser) [hairdresser_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser_supply) [hardware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhardware) [health_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhealth_food) [hearing_aids](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhearing_aids) [herbalist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dherbalist) [hifi](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhifi) [hobby](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhobby) [household_linen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhousehold_linen) [houseware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhouseware) [hunting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhunting) [interior_decoration](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dinterior_decoration) [jewelry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Djewelry) [kiosk](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkiosk) [kitchen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkitchen) [laundry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlaundry) [leather](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dleather) [lighting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlighting) [locksmith](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlocksmith) [lottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlottery) [mall](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmall) [massage](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmassage) [medical_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmedical_supply) [military_surplus](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmilitary_surplus) [mobile_phone](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmobile_phone) [model](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmodel) [money_lender](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmoney_lender) [motorcycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle) [motorcycle_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle_repair) [music](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusic) [musical_instrument](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusical_instrument) [newsagent](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnewsagent) [nutrition_supplements](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnutrition_supplements) [optician](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doptician) [outdoor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutdoor) [outpost](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutpost) [paint](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpaint) [party](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dparty) [pastry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpastry) [pawnbroker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpawnbroker) [perfumery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dperfumery) [pet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet) [pet_grooming](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet_grooming) [photo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dphoto) [pottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpottery) [printer_ink](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dprinter_ink) [psychic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpsychic) [pyrotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpyrotechnics) [radiotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dradiotechnics) [religion](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dreligion) [rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drental) [repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drepair) [scuba_diving](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dscuba_diving) [seafood](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dseafood) [second_hand](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsecond_hand) [sewing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsewing) [shoe_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoe_repair) [shoes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoes) [spices](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dspices) [sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsports) [stationery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstationery) [storage_rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstorage_rental) [supermarket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsupermarket) [swimming_pool](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dswimming_pool) [tailor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtailor) [tattoo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtattoo) [tea](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtea) [telecommunication](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtelecommunication) [ticket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dticket) [tiles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtiles) [tobacco](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtobacco) [tool_hire](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtool_hire) [toys](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtoys) [trade](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrade) [travel_agency](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtravel_agency) [trophy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrophy) [tyres](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtyres) [vacuum_cleaner](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvacuum_cleaner) [variety_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvariety_store) [video](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo) [video_games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo_games) [watches](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwatches) [water](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater) [water_sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater_sports) [weapons](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dweapons) [wholesale](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwholesale) [wigs](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwigs) [window_blind](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwindow_blind) [wine](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwine) [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -79,6 +64,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -105,184 +109,6 @@ This is rendered with `This shop is called {name}` -### shop_types - - - -The question is *What kind of shop is this?* - -This rendering asks information about the property [shop](https://wiki.openstreetmap.org/wiki/Key:shop) - -This is rendered with `This is a {shop}` - - - - - - - *Farm Supply Shop* corresponds with `shop=agrarian` - - *Liquor Store* corresponds with `shop=alcohol` - - *Anime / Manga Shop* corresponds with `shop=anime` - - *Antiques Shop* corresponds with `shop=antiques` - - *Appliance Store* corresponds with `shop=appliance` - - *Art Store* corresponds with `shop=art` - - *Baby Goods Store* corresponds with `shop=baby_goods` - - *Bag/Luggage Store* corresponds with `shop=bag` - - *Bakery* corresponds with `shop=bakery` - - *Bathroom Furnishing Store* corresponds with `shop=bathroom_furnishing` - - *Beauty Shop* corresponds with `shop=beauty` - - *Bedding/Mattress Store* corresponds with `shop=bed` - - *Beverage Store* corresponds with `shop=beverages` - - *Bicycle Shop* corresponds with `shop=bicycle` - - *Boat Store* corresponds with `shop=boat` - - *Bookmaker* corresponds with `shop=bookmaker` - - *Book Store* corresponds with `shop=books` - - *Brewing Supply Store* corresponds with `shop=brewing_supplies` - - *Butcher* corresponds with `shop=butcher` - - *Camera Equipment Store* corresponds with `shop=camera` - - *Candle Shop* corresponds with `shop=candles` - - *Cannabis Shop* corresponds with `shop=cannabis` - - *Car Dealership* corresponds with `shop=car` - - *Car Parts Store* corresponds with `shop=car_parts` - - *Car Repair Shop* corresponds with `shop=car_repair` - - *RV Dealership* corresponds with `shop=caravan` - - *Carpet Store* corresponds with `shop=carpet` - - *Catalog Shop* corresponds with `shop=catalogue` - - *Charity Store* corresponds with `shop=charity` - - *Cheese Store* corresponds with `shop=cheese` - - *Drugstore* corresponds with `shop=chemist` - - *Chocolate Store* corresponds with `shop=chocolate` - - *Clothing Store* corresponds with `shop=clothes` - - *Coffee Store* corresponds with `shop=coffee` - - *Collectibles Shop* corresponds with `shop=collector` - - *Computer Store* corresponds with `shop=computer` - - *Candy Store* corresponds with `shop=confectionery` - - *Convenience Store* corresponds with `shop=convenience` - - *Copy Store* corresponds with `shop=copyshop` - - *Cosmetics Store* corresponds with `shop=cosmetics` - - *Country Store* corresponds with `shop=country_store` - - *Arts & Crafts Store* corresponds with `shop=craft` - - *Curtain Store* corresponds with `shop=curtain` - - *Dairy Store* corresponds with `shop=dairy` - - *Deli* corresponds with `shop=deli` - - *Department Store* corresponds with `shop=department_store` - - *DIY Store* corresponds with `shop=doityourself` - - *Door Shop* corresponds with `shop=doors` - - *Dry Cleaner* corresponds with `shop=dry_cleaning` - - *E-Cigarette Shop* corresponds with `shop=e-cigarette` - - *Electrical Equipment Store* corresponds with `shop=electrical` - - *Electronics Store* corresponds with `shop=electronics` - - *Erotic Store* corresponds with `shop=erotic` - - *Fabric Store* corresponds with `shop=fabric` - - *Produce Stand* corresponds with `shop=farm` - - *Fashion Accessories Store* corresponds with `shop=fashion_accessories` - - *Fireplace Store* corresponds with `shop=fireplace` - - *Fishing Shop* corresponds with `shop=fishing` - - *Flooring Supply Shop* corresponds with `shop=flooring` - - *Florist* corresponds with `shop=florist` - - *Framing Shop* corresponds with `shop=frame` - - *Frozen Food Store* corresponds with `shop=frozen_food` - - *Fuel Shop* corresponds with `shop=fuel` - - *Funeral Home* corresponds with `shop=funeral_directors` - - *Furniture Store* corresponds with `shop=furniture` - - *Tabletop Game Store* corresponds with `shop=games` - - *Garden Center* corresponds with `shop=garden_centre` - - *Bottled Gas Shop* corresponds with `shop=gas` - - *General Store* corresponds with `shop=general` - - *Gift Shop* corresponds with `shop=gift` - - *Greengrocer* corresponds with `shop=greengrocer` - - *Hairdresser* corresponds with `shop=hairdresser` - - *Hairdresser Supply Store* corresponds with `shop=hairdresser_supply` - - *Hardware Store* corresponds with `shop=hardware` - - *Health Food Shop* corresponds with `shop=health_food` - - *Hearing Aids Store* corresponds with `shop=hearing_aids` - - *Herbalist* corresponds with `shop=herbalist` - - *Hifi Store* corresponds with `shop=hifi` - - *Hobby Shop* corresponds with `shop=hobby` - - *Household Linen Shop* corresponds with `shop=household_linen` - - *Houseware Store* corresponds with `shop=houseware` - - *Hunting Shop* corresponds with `shop=hunting` - - *Interior Decoration Store* corresponds with `shop=interior_decoration` - - *Jewelry Store* corresponds with `shop=jewelry` - - *Kiosk* corresponds with `shop=kiosk` - - *Kitchen Design Store* corresponds with `shop=kitchen` - - *Laundry* corresponds with `shop=laundry` - - *Leather Store* corresponds with `shop=leather` - - *Lighting Store* corresponds with `shop=lighting` - - *Locksmith* corresponds with `shop=locksmith` - - *Lottery Shop* corresponds with `shop=lottery` - - *Mall* corresponds with `shop=mall` - - *Massage Shop* corresponds with `shop=massage` - - *Medical Supply Store* corresponds with `shop=medical_supply` - - *Military Surplus Store* corresponds with `shop=military_surplus` - - *Mobile Phone Store* corresponds with `shop=mobile_phone` - - *Model Shop* corresponds with `shop=model` - - *Money Lender* corresponds with `shop=money_lender` - - *Motorcycle Dealership* corresponds with `shop=motorcycle` - - *Motorcycle Repair Shop* corresponds with `shop=motorcycle_repair` - - *Music Store* corresponds with `shop=music` - - *Musical Instrument Store* corresponds with `shop=musical_instrument` - - *Newspaper/Magazine Shop* corresponds with `shop=newsagent` - - *Nutrition Supplements Store* corresponds with `shop=nutrition_supplements` - - *Optician* corresponds with `shop=optician` - - *Outdoors Store* corresponds with `shop=outdoor` - - *Online Retailer Outpost* corresponds with `shop=outpost` - - *Paint Store* corresponds with `shop=paint` - - *Party Supply Store* corresponds with `shop=party` - - *Pastry Shop* corresponds with `shop=pastry` - - *Pawn Shop* corresponds with `shop=pawnbroker` - - *Perfume Store* corresponds with `shop=perfumery` - - *Pet Store* corresponds with `shop=pet` - - *Pet Grooming Store* corresponds with `shop=pet_grooming` - - *Photography Store* corresponds with `shop=photo` - - *Pottery Store* corresponds with `shop=pottery` - - *Printer Ink Store* corresponds with `shop=printer_ink` - - *Psychic* corresponds with `shop=psychic` - - *Fireworks Store* corresponds with `shop=pyrotechnics` - - *Radio/Electronic Component Store* corresponds with `shop=radiotechnics` - - *Religious Store* corresponds with `shop=religion` - - *Rental Shop* corresponds with `shop=rental` - - *Repair Shop* corresponds with `shop=repair` - - *Scuba Diving Shop* corresponds with `shop=scuba_diving` - - *Seafood Shop* corresponds with `shop=seafood` - - *Consignment/Thrift Store* corresponds with `shop=second_hand` - - *Sewing Supply Shop* corresponds with `shop=sewing` - - *Shoe Repair Shop* corresponds with `shop=shoe_repair` - - *Shoe Store* corresponds with `shop=shoes` - - *Spice Shop* corresponds with `shop=spices` - - *Sporting Goods Store* corresponds with `shop=sports` - - *Stationery Store* corresponds with `shop=stationery` - - *Storage Rental* corresponds with `shop=storage_rental` - - *Supermarket* corresponds with `shop=supermarket` - - *Pool Supply Store* corresponds with `shop=swimming_pool` - - *Tailor* corresponds with `shop=tailor` - - *Tattoo Parlor* corresponds with `shop=tattoo` - - *Tea Store* corresponds with `shop=tea` - - *Telecom Retail Store* corresponds with `shop=telecommunication` - - *Ticket Seller* corresponds with `shop=ticket` - - *Tile Shop* corresponds with `shop=tiles` - - *Tobacco Shop* corresponds with `shop=tobacco` - - *Tool Rental* corresponds with `shop=tool_hire` - - *Toy Store* corresponds with `shop=toys` - - *Trade Shop* corresponds with `shop=trade` - - *Travel Agency* corresponds with `shop=travel_agency` - - *Trophy Shop* corresponds with `shop=trophy` - - *Tire Store* corresponds with `shop=tyres` - - *Vacuum Cleaner Store* corresponds with `shop=vacuum_cleaner` - - *Variety Store* corresponds with `shop=variety_store` - - *Video Store* corresponds with `shop=video` - - *Video Game Store* corresponds with `shop=video_games` - - *Watches Shop* corresponds with `shop=watches` - - *Drinking Water Shop* corresponds with `shop=water` - - *Watersport/Swim Shop* corresponds with `shop=water_sports` - - *Weapon Shop* corresponds with `shop=weapons` - - *Wholesale Store* corresponds with `shop=wholesale` - - *Wig Shop* corresponds with `shop=wigs` - - *Window Blind Store* corresponds with `shop=window_blind` - - *Wine Shop* corresponds with `shop=wine` - - - - ### opening_hours @@ -517,6 +343,8 @@ This tagrendering is only visible in the popup if the following condition is met +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -535,6 +363,62 @@ This tagrendering has no question and is thus read-only +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/slow_roads.md b/Docs/Layers/slow_roads.md index a926dc6f3..07218bc1d 100644 --- a/Docs/Layers/slow_roads.md +++ b/Docs/Layers/slow_roads.md @@ -17,23 +17,7 @@ All carfree roads - This layer is shown at zoomlevel **16** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=pedestrian|highway=footway|highway=path|highway=bridleway|highway=living_street|highway=track - - access!=no - - access!=private - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22pedestrian%22%5D%5B%22access%22!%3D%22no%22%5D%5B%22access%22!%3D%22private%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22footway%22%5D%5B%22access%22!%3D%22no%22%5D%5B%22access%22!%3D%22private%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22path%22%5D%5B%22access%22!%3D%22no%22%5D%5B%22access%22!%3D%22private%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22bridleway%22%5D%5B%22access%22!%3D%22no%22%5D%5B%22access%22!%3D%22private%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22living_street%22%5D%5B%22access%22!%3D%22no%22%5D%5B%22access%22!%3D%22private%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22highway%22%3D%22track%22%5D%5B%22access%22!%3D%22no%22%5D%5B%22access%22!%3D%22private%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -50,6 +34,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/highway#values) [highway](https://wiki.openstreetmap.org/wiki/Key:highway) | Multiple choice | [living_street](https://wiki.openstreetmap.org/wiki/Tag:highway%3Dliving_street) [pedestrian](https://wiki.openstreetmap.org/wiki/Tag:highway%3Dpedestrian) [footway](https://wiki.openstreetmap.org/wiki/Tag:highway%3Dfootway) [path](https://wiki.openstreetmap.org/wiki/Tag:highway%3Dpath) [bridleway](https://wiki.openstreetmap.org/wiki/Tag:highway%3Dbridleway) [track](https://wiki.openstreetmap.org/wiki/Tag:highway%3Dtrack) [](https://taginfo.openstreetmap.org/keys/surface#values) [surface](https://wiki.openstreetmap.org/wiki/Key:surface) | [string](../SpecialInputElements.md#string) | [grass](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dgrass) [ground](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dground) [sand](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dsand) [paving_stones](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dpaving_stones) [asphalt](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dasphalt) [concrete](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dconcrete) [](https://taginfo.openstreetmap.org/keys/lit#values) [lit](https://wiki.openstreetmap.org/wiki/Key:lit) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:lit%3Dno) @@ -57,6 +42,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -129,6 +133,52 @@ The question is *Is deze weg 's nachts verlicht?* - *'s nachts verlicht* corresponds with `lit=yes` - *Niet verlicht* corresponds with `lit=no` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/slow_roads/slow_roads.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/slow_roads/slow_roads.json) diff --git a/Docs/Layers/speed_camera.md b/Docs/Layers/speed_camera.md index 8d0e617b7..b5bedbc9b 100644 --- a/Docs/Layers/speed_camera.md +++ b/Docs/Layers/speed_camera.md @@ -30,21 +30,7 @@ Layer showing speed cameras - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=speed_camera - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22speed_camera%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,11 +47,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/maxspeed#values) [maxspeed](https://wiki.openstreetmap.org/wiki/Key:maxspeed) | [pnat](../SpecialInputElements.md#pnat) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### maxspeed @@ -88,6 +94,52 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `ref~.+` +This tagrendering is only visible in the popup if the following condition is met: `ref~.+` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/speed_camera/speed_camera.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/speed_camera/speed_camera.json) diff --git a/Docs/Layers/speed_display.md b/Docs/Layers/speed_display.md index f453a3e5d..eca62c7e6 100644 --- a/Docs/Layers/speed_display.md +++ b/Docs/Layers/speed_display.md @@ -29,21 +29,7 @@ Layer showing speed displays that alert drivers of their speed. - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=speed_display - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22speed_display%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +46,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/maxspeed#values) [maxspeed](https://wiki.openstreetmap.org/wiki/Key:maxspeed) | [pnat](../SpecialInputElements.md#pnat) | [](https://taginfo.openstreetmap.org/keys/inscription#values) [inscription](https://wiki.openstreetmap.org/wiki/Key:inscription) | [string](../SpecialInputElements.md#string) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### maxspeed @@ -90,6 +96,52 @@ This rendering asks information about the property [inscription](https://wiki.o This is rendered with `The text on this speed display is {inscription}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/speed_display/speed_display.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/speed_display/speed_display.json) diff --git a/Docs/Layers/sport_pitch.md b/Docs/Layers/sport_pitch.md index d7a5a699c..86931f50e 100644 --- a/Docs/Layers/sport_pitch.md +++ b/Docs/Layers/sport_pitch.md @@ -30,21 +30,7 @@ A sport pitch - [sports](https://mapcomplete.osm.be/sports) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=pitch - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22pitch%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,7 +47,8 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/sport#values) [sport](https://wiki.openstreetmap.org/wiki/Key:sport) | [string](../SpecialInputElements.md#string) | [basketball](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dbasketball) [soccer](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dsoccer) [table_tennis](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dtable_tennis) [tennis](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dtennis) [korfball](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dkorfball) +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | +[](https://taginfo.openstreetmap.org/keys/sport#values) [sport](https://wiki.openstreetmap.org/wiki/Key:sport) | [string](../SpecialInputElements.md#string) | [basketball](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dbasketball) [soccer](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dsoccer) [table_tennis](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dtable_tennis) [tennis](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dtennis) [korfball](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dkorfball) [skateboard](https://wiki.openstreetmap.org/wiki/Tag:sport%3Dskateboard) [](https://taginfo.openstreetmap.org/keys/surface#values) [surface](https://wiki.openstreetmap.org/wiki/Key:surface) | [string](../SpecialInputElements.md#string) | [grass](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dgrass) [sand](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dsand) [paving_stones](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dpaving_stones) [asphalt](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dasphalt) [concrete](https://wiki.openstreetmap.org/wiki/Tag:surface%3Dconcrete) [](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [limited](https://wiki.openstreetmap.org/wiki/Tag:access%3Dlimited) [members](https://wiki.openstreetmap.org/wiki/Tag:access%3Dmembers) [private](https://wiki.openstreetmap.org/wiki/Tag:access%3Dprivate) [](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) @@ -72,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -105,6 +111,7 @@ This is rendered with `{sport} is played here` - *Korfball is played here* corresponds with `sport=korfball` - *Basketball is played here* corresponds with `sport=basket` - This option cannot be chosen as answer + - *This is a skatepark* corresponds with `sport=skateboard` @@ -225,6 +232,8 @@ This tagrendering is only visible in the popup if the following condition is met +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -241,6 +250,42 @@ This tagrendering has no question and is thus read-only +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/sport_places_without_etymology.md b/Docs/Layers/sport_places_without_etymology.md index ea0a3a0b9..f5355b239 100644 --- a/Docs/Layers/sport_places_without_etymology.md +++ b/Docs/Layers/sport_places_without_etymology.md @@ -28,22 +28,7 @@ All objects which have an etymology known - [etymology](https://mapcomplete.osm.be/etymology) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - name~.+ - - leisure=sports_centre|leisure=stadium|leisure=swimming_pool - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22sports_centre%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22leisure%22%3D%22stadium%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22leisure%22%3D%22swimming_pool%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +45,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) | [](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### etymology-images-from-wikipedia @@ -125,6 +130,8 @@ This is rendered with `Named after {name:etymology}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -169,6 +176,30 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` +This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) diff --git a/Docs/Layers/sport_shops.md b/Docs/Layers/sport_shops.md index 544ad665c..e55583789 100644 --- a/Docs/Layers/sport_shops.md +++ b/Docs/Layers/sport_shops.md @@ -28,22 +28,7 @@ A shop - [sports](https://mapcomplete.osm.be/sports) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - shop=sports - - shop!=mall - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22shop%22%3D%22sports%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,8 +45,8 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/shop#values) [shop](https://wiki.openstreetmap.org/wiki/Key:shop) | [string](../SpecialInputElements.md#string) | [agrarian](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dagrarian) [alcohol](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dalcohol) [anime](https://wiki.openstreetmap.org/wiki/Tag:shop%3Danime) [antiques](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dantiques) [appliance](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dappliance) [art](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dart) [baby_goods](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbaby_goods) [bag](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbag) [bakery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbakery) [bathroom_furnishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbathroom_furnishing) [beauty](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeauty) [bed](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbed) [beverages](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbeverages) [bicycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbicycle) [boat](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dboat) [bookmaker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbookmaker) [books](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbooks) [brewing_supplies](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbrewing_supplies) [butcher](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dbutcher) [camera](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcamera) [candles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcandles) [cannabis](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcannabis) [car](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar) [car_parts](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_parts) [car_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcar_repair) [caravan](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcaravan) [carpet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcarpet) [catalogue](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcatalogue) [charity](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcharity) [cheese](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcheese) [chemist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchemist) [chocolate](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dchocolate) [clothes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dclothes) [coffee](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcoffee) [collector](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcollector) [computer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcomputer) [confectionery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconfectionery) [convenience](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dconvenience) [copyshop](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcopyshop) [cosmetics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcosmetics) [country_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcountry_store) [craft](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcraft) [curtain](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dcurtain) [dairy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddairy) [deli](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddeli) [department_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddepartment_store) [doityourself](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoityourself) [doors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddoors) [dry_cleaning](https://wiki.openstreetmap.org/wiki/Tag:shop%3Ddry_cleaning) [e-cigarette](https://wiki.openstreetmap.org/wiki/Tag:shop%3De-cigarette) [electrical](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectrical) [electronics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Delectronics) [erotic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Derotic) [fabric](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfabric) [farm](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfarm) [fashion_accessories](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfashion_accessories) [fireplace](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfireplace) [fishing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfishing) [flooring](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflooring) [florist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dflorist) [frame](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dframe) [frozen_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfrozen_food) [fuel](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuel) [funeral_directors](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfuneral_directors) [furniture](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dfurniture) [games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgames) [garden_centre](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgarden_centre) [gas](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgas) [general](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgeneral) [gift](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgift) [greengrocer](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dgreengrocer) [hairdresser](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser) [hairdresser_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhairdresser_supply) [hardware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhardware) [health_food](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhealth_food) [hearing_aids](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhearing_aids) [herbalist](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dherbalist) [hifi](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhifi) [hobby](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhobby) [household_linen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhousehold_linen) [houseware](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhouseware) [hunting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dhunting) [interior_decoration](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dinterior_decoration) [jewelry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Djewelry) [kiosk](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkiosk) [kitchen](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dkitchen) [laundry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlaundry) [leather](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dleather) [lighting](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlighting) [locksmith](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlocksmith) [lottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dlottery) [mall](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmall) [massage](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmassage) [medical_supply](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmedical_supply) [military_surplus](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmilitary_surplus) [mobile_phone](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmobile_phone) [model](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmodel) [money_lender](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmoney_lender) [motorcycle](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle) [motorcycle_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmotorcycle_repair) [music](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusic) [musical_instrument](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dmusical_instrument) [newsagent](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnewsagent) [nutrition_supplements](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dnutrition_supplements) [optician](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doptician) [outdoor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutdoor) [outpost](https://wiki.openstreetmap.org/wiki/Tag:shop%3Doutpost) [paint](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpaint) [party](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dparty) [pastry](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpastry) [pawnbroker](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpawnbroker) [perfumery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dperfumery) [pet](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet) [pet_grooming](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpet_grooming) [photo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dphoto) [pottery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpottery) [printer_ink](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dprinter_ink) [psychic](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpsychic) [pyrotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dpyrotechnics) [radiotechnics](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dradiotechnics) [religion](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dreligion) [rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drental) [repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Drepair) [scuba_diving](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dscuba_diving) [seafood](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dseafood) [second_hand](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsecond_hand) [sewing](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsewing) [shoe_repair](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoe_repair) [shoes](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dshoes) [spices](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dspices) [sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsports) [stationery](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstationery) [storage_rental](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dstorage_rental) [supermarket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dsupermarket) [swimming_pool](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dswimming_pool) [tailor](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtailor) [tattoo](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtattoo) [tea](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtea) [telecommunication](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtelecommunication) [ticket](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dticket) [tiles](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtiles) [tobacco](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtobacco) [tool_hire](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtool_hire) [toys](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtoys) [trade](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrade) [travel_agency](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtravel_agency) [trophy](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtrophy) [tyres](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dtyres) [vacuum_cleaner](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvacuum_cleaner) [variety_store](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvariety_store) [video](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo) [video_games](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dvideo_games) [watches](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwatches) [water](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater) [water_sports](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwater_sports) [weapons](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dweapons) [wholesale](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwholesale) [wigs](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwigs) [window_blind](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwindow_blind) [wine](https://wiki.openstreetmap.org/wiki/Tag:shop%3Dwine) [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | @@ -75,6 +60,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -101,184 +105,6 @@ This is rendered with `This shop is called {name}` -### shop_types - - - -The question is *What kind of shop is this?* - -This rendering asks information about the property [shop](https://wiki.openstreetmap.org/wiki/Key:shop) - -This is rendered with `This is a {shop}` - - - - - - - *Farm Supply Shop* corresponds with `shop=agrarian` - - *Liquor Store* corresponds with `shop=alcohol` - - *Anime / Manga Shop* corresponds with `shop=anime` - - *Antiques Shop* corresponds with `shop=antiques` - - *Appliance Store* corresponds with `shop=appliance` - - *Art Store* corresponds with `shop=art` - - *Baby Goods Store* corresponds with `shop=baby_goods` - - *Bag/Luggage Store* corresponds with `shop=bag` - - *Bakery* corresponds with `shop=bakery` - - *Bathroom Furnishing Store* corresponds with `shop=bathroom_furnishing` - - *Beauty Shop* corresponds with `shop=beauty` - - *Bedding/Mattress Store* corresponds with `shop=bed` - - *Beverage Store* corresponds with `shop=beverages` - - *Bicycle Shop* corresponds with `shop=bicycle` - - *Boat Store* corresponds with `shop=boat` - - *Bookmaker* corresponds with `shop=bookmaker` - - *Book Store* corresponds with `shop=books` - - *Brewing Supply Store* corresponds with `shop=brewing_supplies` - - *Butcher* corresponds with `shop=butcher` - - *Camera Equipment Store* corresponds with `shop=camera` - - *Candle Shop* corresponds with `shop=candles` - - *Cannabis Shop* corresponds with `shop=cannabis` - - *Car Dealership* corresponds with `shop=car` - - *Car Parts Store* corresponds with `shop=car_parts` - - *Car Repair Shop* corresponds with `shop=car_repair` - - *RV Dealership* corresponds with `shop=caravan` - - *Carpet Store* corresponds with `shop=carpet` - - *Catalog Shop* corresponds with `shop=catalogue` - - *Charity Store* corresponds with `shop=charity` - - *Cheese Store* corresponds with `shop=cheese` - - *Drugstore* corresponds with `shop=chemist` - - *Chocolate Store* corresponds with `shop=chocolate` - - *Clothing Store* corresponds with `shop=clothes` - - *Coffee Store* corresponds with `shop=coffee` - - *Collectibles Shop* corresponds with `shop=collector` - - *Computer Store* corresponds with `shop=computer` - - *Candy Store* corresponds with `shop=confectionery` - - *Convenience Store* corresponds with `shop=convenience` - - *Copy Store* corresponds with `shop=copyshop` - - *Cosmetics Store* corresponds with `shop=cosmetics` - - *Country Store* corresponds with `shop=country_store` - - *Arts & Crafts Store* corresponds with `shop=craft` - - *Curtain Store* corresponds with `shop=curtain` - - *Dairy Store* corresponds with `shop=dairy` - - *Deli* corresponds with `shop=deli` - - *Department Store* corresponds with `shop=department_store` - - *DIY Store* corresponds with `shop=doityourself` - - *Door Shop* corresponds with `shop=doors` - - *Dry Cleaner* corresponds with `shop=dry_cleaning` - - *E-Cigarette Shop* corresponds with `shop=e-cigarette` - - *Electrical Equipment Store* corresponds with `shop=electrical` - - *Electronics Store* corresponds with `shop=electronics` - - *Erotic Store* corresponds with `shop=erotic` - - *Fabric Store* corresponds with `shop=fabric` - - *Produce Stand* corresponds with `shop=farm` - - *Fashion Accessories Store* corresponds with `shop=fashion_accessories` - - *Fireplace Store* corresponds with `shop=fireplace` - - *Fishing Shop* corresponds with `shop=fishing` - - *Flooring Supply Shop* corresponds with `shop=flooring` - - *Florist* corresponds with `shop=florist` - - *Framing Shop* corresponds with `shop=frame` - - *Frozen Food Store* corresponds with `shop=frozen_food` - - *Fuel Shop* corresponds with `shop=fuel` - - *Funeral Home* corresponds with `shop=funeral_directors` - - *Furniture Store* corresponds with `shop=furniture` - - *Tabletop Game Store* corresponds with `shop=games` - - *Garden Center* corresponds with `shop=garden_centre` - - *Bottled Gas Shop* corresponds with `shop=gas` - - *General Store* corresponds with `shop=general` - - *Gift Shop* corresponds with `shop=gift` - - *Greengrocer* corresponds with `shop=greengrocer` - - *Hairdresser* corresponds with `shop=hairdresser` - - *Hairdresser Supply Store* corresponds with `shop=hairdresser_supply` - - *Hardware Store* corresponds with `shop=hardware` - - *Health Food Shop* corresponds with `shop=health_food` - - *Hearing Aids Store* corresponds with `shop=hearing_aids` - - *Herbalist* corresponds with `shop=herbalist` - - *Hifi Store* corresponds with `shop=hifi` - - *Hobby Shop* corresponds with `shop=hobby` - - *Household Linen Shop* corresponds with `shop=household_linen` - - *Houseware Store* corresponds with `shop=houseware` - - *Hunting Shop* corresponds with `shop=hunting` - - *Interior Decoration Store* corresponds with `shop=interior_decoration` - - *Jewelry Store* corresponds with `shop=jewelry` - - *Kiosk* corresponds with `shop=kiosk` - - *Kitchen Design Store* corresponds with `shop=kitchen` - - *Laundry* corresponds with `shop=laundry` - - *Leather Store* corresponds with `shop=leather` - - *Lighting Store* corresponds with `shop=lighting` - - *Locksmith* corresponds with `shop=locksmith` - - *Lottery Shop* corresponds with `shop=lottery` - - *Mall* corresponds with `shop=mall` - - *Massage Shop* corresponds with `shop=massage` - - *Medical Supply Store* corresponds with `shop=medical_supply` - - *Military Surplus Store* corresponds with `shop=military_surplus` - - *Mobile Phone Store* corresponds with `shop=mobile_phone` - - *Model Shop* corresponds with `shop=model` - - *Money Lender* corresponds with `shop=money_lender` - - *Motorcycle Dealership* corresponds with `shop=motorcycle` - - *Motorcycle Repair Shop* corresponds with `shop=motorcycle_repair` - - *Music Store* corresponds with `shop=music` - - *Musical Instrument Store* corresponds with `shop=musical_instrument` - - *Newspaper/Magazine Shop* corresponds with `shop=newsagent` - - *Nutrition Supplements Store* corresponds with `shop=nutrition_supplements` - - *Optician* corresponds with `shop=optician` - - *Outdoors Store* corresponds with `shop=outdoor` - - *Online Retailer Outpost* corresponds with `shop=outpost` - - *Paint Store* corresponds with `shop=paint` - - *Party Supply Store* corresponds with `shop=party` - - *Pastry Shop* corresponds with `shop=pastry` - - *Pawn Shop* corresponds with `shop=pawnbroker` - - *Perfume Store* corresponds with `shop=perfumery` - - *Pet Store* corresponds with `shop=pet` - - *Pet Grooming Store* corresponds with `shop=pet_grooming` - - *Photography Store* corresponds with `shop=photo` - - *Pottery Store* corresponds with `shop=pottery` - - *Printer Ink Store* corresponds with `shop=printer_ink` - - *Psychic* corresponds with `shop=psychic` - - *Fireworks Store* corresponds with `shop=pyrotechnics` - - *Radio/Electronic Component Store* corresponds with `shop=radiotechnics` - - *Religious Store* corresponds with `shop=religion` - - *Rental Shop* corresponds with `shop=rental` - - *Repair Shop* corresponds with `shop=repair` - - *Scuba Diving Shop* corresponds with `shop=scuba_diving` - - *Seafood Shop* corresponds with `shop=seafood` - - *Consignment/Thrift Store* corresponds with `shop=second_hand` - - *Sewing Supply Shop* corresponds with `shop=sewing` - - *Shoe Repair Shop* corresponds with `shop=shoe_repair` - - *Shoe Store* corresponds with `shop=shoes` - - *Spice Shop* corresponds with `shop=spices` - - *Sporting Goods Store* corresponds with `shop=sports` - - *Stationery Store* corresponds with `shop=stationery` - - *Storage Rental* corresponds with `shop=storage_rental` - - *Supermarket* corresponds with `shop=supermarket` - - *Pool Supply Store* corresponds with `shop=swimming_pool` - - *Tailor* corresponds with `shop=tailor` - - *Tattoo Parlor* corresponds with `shop=tattoo` - - *Tea Store* corresponds with `shop=tea` - - *Telecom Retail Store* corresponds with `shop=telecommunication` - - *Ticket Seller* corresponds with `shop=ticket` - - *Tile Shop* corresponds with `shop=tiles` - - *Tobacco Shop* corresponds with `shop=tobacco` - - *Tool Rental* corresponds with `shop=tool_hire` - - *Toy Store* corresponds with `shop=toys` - - *Trade Shop* corresponds with `shop=trade` - - *Travel Agency* corresponds with `shop=travel_agency` - - *Trophy Shop* corresponds with `shop=trophy` - - *Tire Store* corresponds with `shop=tyres` - - *Vacuum Cleaner Store* corresponds with `shop=vacuum_cleaner` - - *Variety Store* corresponds with `shop=variety_store` - - *Video Store* corresponds with `shop=video` - - *Video Game Store* corresponds with `shop=video_games` - - *Watches Shop* corresponds with `shop=watches` - - *Drinking Water Shop* corresponds with `shop=water` - - *Watersport/Swim Shop* corresponds with `shop=water_sports` - - *Weapon Shop* corresponds with `shop=weapons` - - *Wholesale Store* corresponds with `shop=wholesale` - - *Wig Shop* corresponds with `shop=wigs` - - *Window Blind Store* corresponds with `shop=window_blind` - - *Wine Shop* corresponds with `shop=wine` - - - - ### opening_hours @@ -513,6 +339,8 @@ This tagrendering is only visible in the popup if the following condition is met +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -531,11 +359,11 @@ This tagrendering has no question and is thus read-only -### questions +### minimap -Show the images block at this location +Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only @@ -543,11 +371,43 @@ This tagrendering has no question and is thus read-only -### minimap +### move-button -Shows a small map with the feature. Added by default to every popup +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + This tagrendering has no question and is thus read-only diff --git a/Docs/Layers/sports_centre.md b/Docs/Layers/sports_centre.md index 6591e6eda..a3fe7d952 100644 --- a/Docs/Layers/sports_centre.md +++ b/Docs/Layers/sports_centre.md @@ -29,21 +29,7 @@ Indoor and outdoor sports centres can be found on this layer - [sports](https://mapcomplete.osm.be/sports) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - leisure=sports_centre - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22leisure%22%3D%22sports_centre%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | @@ -69,6 +56,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -179,6 +185,62 @@ The question is *Is this place accessible with a wheelchair?* +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/stairs.md b/Docs/Layers/stairs.md index 5a208d727..14b73a16c 100644 --- a/Docs/Layers/stairs.md +++ b/Docs/Layers/stairs.md @@ -30,21 +30,7 @@ Layer showing stairs and escalators - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=steps - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22steps%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/level#values) [level](https://wiki.openstreetmap.org/wiki/Key:level) | [string](../SpecialInputElements.md#string) | [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) [](https://taginfo.openstreetmap.org/keys/handrail#values) [handrail](https://wiki.openstreetmap.org/wiki/Key:handrail) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:handrail%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:handrail%3Dno) [](https://taginfo.openstreetmap.org/keys/tactile_writing#values) [tactile_writing](https://wiki.openstreetmap.org/wiki/Key:tactile_writing) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:tactile_writing%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:tactile_writing%3Dno) @@ -69,6 +56,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -190,6 +196,52 @@ The question is *Is there a ramp at these stairs?* - Unselecting this answer will add ramp:stroller=no - *There is no ramp at these stairs* corresponds with `ramp=no` - Unselecting this answer will add + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/stairs/stairs.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/stairs/stairs.json) diff --git a/Docs/Layers/street_lamps.md b/Docs/Layers/street_lamps.md index ecb3cc3a7..d19060a4a 100644 --- a/Docs/Layers/street_lamps.md +++ b/Docs/Layers/street_lamps.md @@ -29,21 +29,7 @@ A layer showing street lights - [street_lighting](https://mapcomplete.osm.be/street_lighting) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=street_lamp - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22street_lamp%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/ref#values) [ref](https://wiki.openstreetmap.org/wiki/Key:ref) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/support#values) [support](https://wiki.openstreetmap.org/wiki/Key:support) | Multiple choice | [catenary](https://wiki.openstreetmap.org/wiki/Tag:support%3Dcatenary) [ceiling](https://wiki.openstreetmap.org/wiki/Tag:support%3Dceiling) [ground](https://wiki.openstreetmap.org/wiki/Tag:support%3Dground) [pedestal](https://wiki.openstreetmap.org/wiki/Tag:support%3Dpedestal) [pole](https://wiki.openstreetmap.org/wiki/Tag:support%3Dpole) [wall](https://wiki.openstreetmap.org/wiki/Tag:support%3Dwall) [wall_mount](https://wiki.openstreetmap.org/wiki/Tag:support%3Dwall_mount) [](https://taginfo.openstreetmap.org/keys/lamp_mount#values) [lamp_mount](https://wiki.openstreetmap.org/wiki/Key:lamp_mount) | Multiple choice | [straight_mast](https://wiki.openstreetmap.org/wiki/Tag:lamp_mount%3Dstraight_mast) [bent_mast](https://wiki.openstreetmap.org/wiki/Tag:lamp_mount%3Dbent_mast) @@ -72,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -237,6 +243,72 @@ This is rendered with `This lamp points towards {light:direction}` -This tagrendering is only visible in the popup if the following condition is met: `light:count=1` +This tagrendering is only visible in the popup if the following condition is met: `light:count=1` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/street_lamps/street_lamps.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/street_lamps/street_lamps.json) diff --git a/Docs/Layers/streets_without_etymology.md b/Docs/Layers/streets_without_etymology.md index 15c77d4af..662f25e38 100644 --- a/Docs/Layers/streets_without_etymology.md +++ b/Docs/Layers/streets_without_etymology.md @@ -28,23 +28,7 @@ All objects which have an etymology known - [etymology](https://mapcomplete.osm.be/etymology) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - name~.+ - - highway~.+ - - highway!=bus_stop - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22name%22%5D%5B%22highway%22%5D%5B%22highway%22!%3D%22bus_stop%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,12 +45,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) | [](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### etymology-images-from-wikipedia @@ -126,6 +130,8 @@ This is rendered with `Named after {name:etymology}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -170,6 +176,30 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` +This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) diff --git a/Docs/Layers/surveillance_camera.md b/Docs/Layers/surveillance_camera.md index d650e3a6a..db95cef47 100644 --- a/Docs/Layers/surveillance_camera.md +++ b/Docs/Layers/surveillance_camera.md @@ -30,22 +30,7 @@ This layer shows surveillance cameras and allows a contributor to update informa - [surveillance](https://mapcomplete.osm.be/surveillance) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - man_made=surveillance - - surveillance:type=camera|surveillance:type=ALPR|surveillance:type=ANPR - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22man_made%22%3D%22surveillance%22%5D%5B%22surveillance%3Atype%22%3D%22camera%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22man_made%22%3D%22surveillance%22%5D%5B%22surveillance%3Atype%22%3D%22ALPR%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22man_made%22%3D%22surveillance%22%5D%5B%22surveillance%3Atype%22%3D%22ANPR%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/camera:direction#values) [camera:direction](https://wiki.openstreetmap.org/wiki/Key:camera:direction) | [direction](../SpecialInputElements.md#direction) | [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | @@ -74,6 +60,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -233,6 +238,52 @@ This is rendered with `Mounting method: {camera:mount}` - *This camera is placed on the ceiling* corresponds with `camera:mount=ceiling` - *This camera is placed on a street light* corresponds with `camera:mount=street_lamp` - *This camera is placed on a tree* corresponds with `camera:mount=tree` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/surveillance_camera/surveillance_camera.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/surveillance_camera/surveillance_camera.json) diff --git a/Docs/Layers/tertiary_education.md b/Docs/Layers/tertiary_education.md index c9dc230b1..979cbedc2 100644 --- a/Docs/Layers/tertiary_education.md +++ b/Docs/Layers/tertiary_education.md @@ -29,21 +29,7 @@ Layer with all tertiary education institutes (ISCED:2011 levels 6,7 and 8) - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=college|amenity=university|amenity=school&isced:2011:level~^(.*bachelor.*)$|isced:2011:level~^(.*master.*)$ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22college%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22university%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22school%22%5D%5B%22isced%3A2011%3Alevel%22~%22%5E(.*bachelor.*)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22amenity%22%3D%22school%22%5D%5B%22isced%3A2011%3Alevel%22~%22%5E(.*master.*)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,10 +46,9 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [college](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dcollege) [university](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Duniversity) [](https://taginfo.openstreetmap.org/keys/isced:2011:level#values) [isced:2011:level](https://wiki.openstreetmap.org/wiki/Key:isced:2011:level) | Multiple choice | [bachelor](https://wiki.openstreetmap.org/wiki/Tag:isced:2011:level%3Dbachelor) [master](https://wiki.openstreetmap.org/wiki/Tag:isced:2011:level%3Dmaster) [doctorate](https://wiki.openstreetmap.org/wiki/Tag:isced:2011:level%3Ddoctorate) -[](https://taginfo.openstreetmap.org/keys/capacity#values) [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) | [pnat](../SpecialInputElements.md#pnat) | -[](https://taginfo.openstreetmap.org/keys/school:gender#values) [school:gender](https://wiki.openstreetmap.org/wiki/Key:school:gender) | Multiple choice | [mixed](https://wiki.openstreetmap.org/wiki/Tag:school:gender%3Dmixed) [separated](https://wiki.openstreetmap.org/wiki/Tag:school:gender%3Dseparated) [male](https://wiki.openstreetmap.org/wiki/Tag:school:gender%3Dmale) [female](https://wiki.openstreetmap.org/wiki/Tag:school:gender%3Dfemale) [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | @@ -71,6 +56,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### institution-kind @@ -106,38 +110,6 @@ This tagrendering is only visible in the popup if the following condition is met -### capacity - - - -The question is *How much students can at most enroll in this school?* - -This rendering asks information about the property [capacity](https://wiki.openstreetmap.org/wiki/Key:capacity) - -This is rendered with `This school can enroll at most {capacity} students` - - - - - -### gender - - - -The question is *Which genders can enroll at this school?* - - - - - - - *Both boys and girls can enroll here and have classes together* corresponds with `school:gender=mixed` - - *Both boys and girls can enroll here but they are separated (e.g. they have lessons in different classrooms or at different times)* corresponds with `school:gender=separated` - - *This is a boys only-school* corresponds with `school:gender=male` - - *This is a girls-only school* corresponds with `school:gender=female` - - - - ### website @@ -200,6 +172,52 @@ This is rendered with `{phone}` - This option cannot be chosen as answer -This tagrendering has labels `contact` +This tagrendering has labels `contact` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/tertiary_education/tertiary_education.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/tertiary_education/tertiary_education.json) diff --git a/Docs/Layers/ticket_machine.md b/Docs/Layers/ticket_machine.md index 1eb76d910..697ffda89 100644 --- a/Docs/Layers/ticket_machine.md +++ b/Docs/Layers/ticket_machine.md @@ -17,22 +17,7 @@ Find ticket machines for public transport tickets - This layer is shown at zoomlevel **19** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=vending_machine - - vending=public_transport_tickets - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22vending_machine%22%5D%5B%22vending%22%3D%22public_transport_tickets%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -49,6 +34,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [Nederlandse Spoorwegen](https://wiki.openstreetmap.org/wiki/Tag:operator%3DNederlandse Spoorwegen) [](https://taginfo.openstreetmap.org/keys/payment:coins:denominations#values) [payment:coins:denominations](https://wiki.openstreetmap.org/wiki/Key:payment:coins:denominations) | Multiple choice | [0.01 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.01 EUR) [0.02 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.02 EUR) [0.05 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.05 EUR) [0.10 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.10 EUR) [0.20 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.20 EUR) [0.50 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D0.50 EUR) [1 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D1 EUR) [2 EUR](https://wiki.openstreetmap.org/wiki/Tag:payment:coins:denominations%3D2 EUR) @@ -57,6 +43,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -186,6 +191,72 @@ The question is *what notes can you use to pay here?* - *500 euro notes are accepted* corresponds with `payment:notes:denominations=500 EUR` -This tagrendering is only visible in the popup if the following condition is met: `payment:notes=yes|payment:cash=yes&_country=at|_country=be|_country=cy|_country=de|_country=ee|_country=es|_country=fi|_country=fr|_country=gr|_country=hr|_country=ie|_country=it|_country=lt|_country=lu|_country=lv|_country=mt|_country=nl|_country=pt|_country=si|_country=sk` +This tagrendering is only visible in the popup if the following condition is met: `payment:notes=yes|payment:cash=yes&_country=at|_country=be|_country=cy|_country=de|_country=ee|_country=es|_country=fi|_country=fr|_country=gr|_country=hr|_country=ie|_country=it|_country=lt|_country=lu|_country=lv|_country=mt|_country=nl|_country=pt|_country=si|_country=sk` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/ticket_machine/ticket_machine.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/ticket_machine/ticket_machine.json) diff --git a/Docs/Layers/ticket_validator.md b/Docs/Layers/ticket_validator.md index fc82a9a61..f53921236 100644 --- a/Docs/Layers/ticket_validator.md +++ b/Docs/Layers/ticket_validator.md @@ -17,21 +17,7 @@ Find ticket validators to validate public transport tickets - This layer is shown at zoomlevel **19** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=ticket_validator - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22ticket_validator%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -48,6 +34,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/barrier#values) [barrier](https://wiki.openstreetmap.org/wiki/Key:barrier) | Multiple choice | [gate](https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dgate) [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [Nederlandse Spoorwegen](https://wiki.openstreetmap.org/wiki/Tag:operator%3DNederlandse Spoorwegen) @@ -55,6 +42,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -149,6 +155,72 @@ The question is *Which methods of payment are accepted here?* - Unselecting this answer will add payment:OV-Chipkaart=no - *This ticket validator accepts OV-Chipkaart* corresponds with `payment:ov-chipkaart=yes` - Unselecting this answer will add payment:ov-chipkaart=no + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/ticket_validator/ticket_validator.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/ticket_validator/ticket_validator.json) diff --git a/Docs/Layers/toekomstige_fietsstraat.md b/Docs/Layers/toekomstige_fietsstraat.md index a1c17d992..36945fe1f 100644 --- a/Docs/Layers/toekomstige_fietsstraat.md +++ b/Docs/Layers/toekomstige_fietsstraat.md @@ -28,21 +28,7 @@ This street will become a cyclestreet soon - [cyclestreets](https://mapcomplete.osm.be/cyclestreets) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - proposed:cyclestreet=yes|proposed:bicycle_road=yes - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22proposed%3Abicycle_road%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22proposed%3Acyclestreet%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,18 +47,7 @@ attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ [](https://taginfo.openstreetmap.org/keys/traffic_sign#values) [traffic_sign](https://wiki.openstreetmap.org/wiki/Key:traffic_sign) | Multiple choice | [DE:244.1,1020-30](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1020-30) [DE:244.1,1022-12,1024-10](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1022-12,1024-10) [DE:244.1,1022-12](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1022-12) [DE:244.1,1024-10](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1,1024-10) [DE:244.1](https://wiki.openstreetmap.org/wiki/Tag:traffic_sign%3DDE:244.1) [](https://taginfo.openstreetmap.org/keys/cyclestreet:start_date#values) [cyclestreet:start_date](https://wiki.openstreetmap.org/wiki/Key:cyclestreet:start_date) | [date](../SpecialInputElements.md#date) | - - - - -### images - - - -This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` - -This tagrendering has no question and is thus read-only - +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | @@ -136,11 +111,40 @@ This tagrendering is only visible in the popup if the following condition is met -### questions +### just_created -Show the images block at this location +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### images + + + +This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` + +This tagrendering has no question and is thus read-only + + + + + +### leftover-questions + + This tagrendering has no question and is thus read-only @@ -156,6 +160,40 @@ Shows a small map with the feature. Added by default to every popup This tagrendering has no question and is thus read-only + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + +### split-button + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/themes/cyclestreets/cyclestreets.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/cyclestreets/cyclestreets.json) diff --git a/Docs/Layers/toilet.md b/Docs/Layers/toilet.md index 44b6a0a70..354dd6e3b 100644 --- a/Docs/Layers/toilet.md +++ b/Docs/Layers/toilet.md @@ -5,7 +5,7 @@ - + A layer showing (public) toilets @@ -31,21 +31,7 @@ A layer showing (public) toilets - [toilets](https://mapcomplete.osm.be/toilets) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=toilets - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22toilets%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,6 +48,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | [string](../SpecialInputElements.md#string) | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [customers](https://wiki.openstreetmap.org/wiki/Tag:access%3Dcustomers) [no](https://wiki.openstreetmap.org/wiki/Tag:access%3Dno) [key](https://wiki.openstreetmap.org/wiki/Tag:access%3Dkey) [](https://taginfo.openstreetmap.org/keys/fee#values) [fee](https://wiki.openstreetmap.org/wiki/Key:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:fee%3Dno) @@ -79,6 +66,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -360,6 +366,72 @@ This is rendered with `{description}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/toilet_at_amenity.md b/Docs/Layers/toilet_at_amenity.md index 4065379e2..c5523d78d 100644 --- a/Docs/Layers/toilet_at_amenity.md +++ b/Docs/Layers/toilet_at_amenity.md @@ -29,21 +29,7 @@ A layer showing (public) toilets located at different places. - [toilets](https://mapcomplete.osm.be/toilets) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - toilets=yes - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22toilets%22%3D%22yes%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) [](https://taginfo.openstreetmap.org/keys/toilets:access#values) [toilets:access](https://wiki.openstreetmap.org/wiki/Key:toilets:access) | [string](../SpecialInputElements.md#string) | [yes](https://wiki.openstreetmap.org/wiki/Tag:toilets:access%3Dyes) [customers](https://wiki.openstreetmap.org/wiki/Tag:toilets:access%3Dcustomers) [no](https://wiki.openstreetmap.org/wiki/Tag:toilets:access%3Dno) [key](https://wiki.openstreetmap.org/wiki/Tag:toilets:access%3Dkey) [](https://taginfo.openstreetmap.org/keys/toilets:fee#values) [toilets:fee](https://wiki.openstreetmap.org/wiki/Key:toilets:fee) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:toilets:fee%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:toilets:fee%3Dno) @@ -67,16 +54,30 @@ attribute | type | values which are supported by this layer [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | [](https://taginfo.openstreetmap.org/keys/toilets:wheelchair#values) [toilets:wheelchair](https://wiki.openstreetmap.org/wiki/Key:toilets:wheelchair) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:toilets:wheelchair%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:toilets:wheelchair%3Dno) [designated](https://wiki.openstreetmap.org/wiki/Tag:toilets:wheelchair%3Ddesignated) [](https://taginfo.openstreetmap.org/keys/toilets:door:width#values) [toilets:door:width](https://wiki.openstreetmap.org/wiki/Key:toilets:door:width) | [pfloat](../SpecialInputElements.md#pfloat) | -[](https://taginfo.openstreetmap.org/keys/toilets:position#values) [toilets:position](https://wiki.openstreetmap.org/wiki/Key:toilets:position) | Multiple choice | [seated](https://wiki.openstreetmap.org/wiki/Tag:toilets:position%3Dseated) [urinal](https://wiki.openstreetmap.org/wiki/Tag:toilets:position%3Durinal) [squat](https://wiki.openstreetmap.org/wiki/Tag:toilets:position%3Dsquat) [seated;urinal](https://wiki.openstreetmap.org/wiki/Tag:toilets:position%3Dseated;urinal) -[](https://taginfo.openstreetmap.org/keys/changing_table#values) [changing_table](https://wiki.openstreetmap.org/wiki/Key:changing_table) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:changing_table%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:changing_table%3Dno) -[](https://taginfo.openstreetmap.org/keys/changing_table:location#values) [changing_table:location](https://wiki.openstreetmap.org/wiki/Key:changing_table:location) | [string](../SpecialInputElements.md#string) | [female_toilet](https://wiki.openstreetmap.org/wiki/Tag:changing_table:location%3Dfemale_toilet) [male_toilet](https://wiki.openstreetmap.org/wiki/Tag:changing_table:location%3Dmale_toilet) [wheelchair_toilet](https://wiki.openstreetmap.org/wiki/Tag:changing_table:location%3Dwheelchair_toilet) [dedicated_room](https://wiki.openstreetmap.org/wiki/Tag:changing_table:location%3Ddedicated_room) -[](https://taginfo.openstreetmap.org/keys/toilets:handwashing#values) [toilets:handwashing](https://wiki.openstreetmap.org/wiki/Key:toilets:handwashing) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:toilets:handwashing%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:toilets:handwashing%3Dno) -[](https://taginfo.openstreetmap.org/keys/toilets:paper_supplied#values) [toilets:paper_supplied](https://wiki.openstreetmap.org/wiki/Key:toilets:paper_supplied) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:toilets:paper_supplied%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:toilets:paper_supplied%3Dno) [](https://taginfo.openstreetmap.org/keys/toilets:description#values) [toilets:description](https://wiki.openstreetmap.org/wiki/Key:toilets:description) | [string](../SpecialInputElements.md#string) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -217,92 +218,52 @@ This tagrendering is only visible in the popup if the following condition is met -### toilets-type +### toilettoiletstype -The question is *Which kind of toilets are this?* +This tagrendering has no question and is thus read-only - - *There are only seated toilets* corresponds with `toilets:position=seated` - - *There are only urinals here* corresponds with `toilets:position=urinal` - - *There are only squat toilets here* corresponds with `toilets:position=squat` - - *Both seated toilets and urinals are available here* corresponds with `toilets:position=seated;urinal` +### toilettoiletschangingtable - -### toilets-changing-table - - - -The question is *Is a changing table (to change diapers) available?* +This tagrendering has no question and is thus read-only - - *A changing table is available* corresponds with `changing_table=yes` - - *No changing table is available* corresponds with `changing_table=no` +### toilettoiletchangingtablelocation - -### toilet-changing_table:location - - - -The question is *Where is the changing table located?* - -This rendering asks information about the property [changing_table:location](https://wiki.openstreetmap.org/wiki/Key:changing_table:location) - -This is rendered with `The changing table is located at {changing_table:location}` +This tagrendering has no question and is thus read-only - - *The changing table is in the toilet for women. * corresponds with `changing_table:location=female_toilet` - - *The changing table is in the toilet for men. * corresponds with `changing_table:location=male_toilet` - - *The changing table is in the toilet for wheelchair users. * corresponds with `changing_table:location=wheelchair_toilet` - - *The changing table is in a dedicated room. * corresponds with `changing_table:location=dedicated_room` - - -This tagrendering is only visible in the popup if the following condition is met: `changing_table=yes` +### toilettoilethandwashing -### toilet-handwashing - - - -The question is *Do these toilets have a sink to wash your hands?* +This tagrendering has no question and is thus read-only - - *This toilets have a sink to wash your hands* corresponds with `toilets:handwashing=yes` - - *This toilets don't have a sink to wash your hands* corresponds with `toilets:handwashing=no` +### toilettoilethaspaper +This tagrendering has no question and is thus read-only -### toilet-has-paper - - - -The question is *Does one have to bring their own toilet paper to this toilet?* - - - - - - - *This toilet is equipped with toilet paper* corresponds with `toilets:paper_supplied=yes` - - *You have to bring your own toilet paper to this toilet* corresponds with `toilets:paper_supplied=no` @@ -321,6 +282,62 @@ This is rendered with `{toilets:description}` +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters @@ -334,13 +351,6 @@ wheelchair.0 | Wheelchair accessible | toilets:wheelchair=yes\|toilets:wheelchai -id | question | osmTags ----- | ---------- | --------- -changing_table.0 | Has a changing table | changing_table=yes - - - - id | question | osmTags ---- | ---------- | --------- free.0 | Free to use | toilets:fee=no\|toilets:fee=0|toilets:charge=0 diff --git a/Docs/Layers/toursistic_places_without_etymology.md b/Docs/Layers/toursistic_places_without_etymology.md index ac50ea11c..72e80cfb1 100644 --- a/Docs/Layers/toursistic_places_without_etymology.md +++ b/Docs/Layers/toursistic_places_without_etymology.md @@ -28,22 +28,7 @@ All objects which have an etymology known - [etymology](https://mapcomplete.osm.be/etymology) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - name~.+ - - tourism=aquarium|tourism=museum|tourism=theme_park|tourism=zoo - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22tourism%22%3D%22aquarium%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22museum%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22theme_park%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22tourism%22%3D%22zoo%22%5D%5B%22name%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,12 +45,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](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) | [](https://taginfo.openstreetmap.org/keys/name:etymology#values) [name:etymology](https://wiki.openstreetmap.org/wiki/Key:name:etymology) | [string](../SpecialInputElements.md#string) | [unknown](https://wiki.openstreetmap.org/wiki/Tag:name:etymology%3Dunknown) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### etymology-images-from-wikipedia @@ -125,6 +130,8 @@ This is rendered with `Named after {name:etymology}` +Show the images block at this location + This tagrendering has no question and is thus read-only @@ -169,6 +176,30 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` +This tagrendering is only visible in the popup if the following condition is met: `wikidata~.+` + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/themes/etymology/etymology.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/etymology/etymology.json) diff --git a/Docs/Layers/trail.md b/Docs/Layers/trail.md index c3cc2f638..5ddb701d7 100644 --- a/Docs/Layers/trail.md +++ b/Docs/Layers/trail.md @@ -17,21 +17,7 @@ Aangeduide wandeltochten - This layer is shown at zoomlevel **12** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - route~^(.*foot.*)$|route~^(.*hiking.*)$|route~^(.*bycicle.*)$|route~^(.*horse.*)$ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22route%22~%22%5E(.*foot.*)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22route%22~%22%5E(.*hiking.*)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22route%22~%22%5E(.*bycicle.*)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22route%22~%22%5E(.*horse.*)%24%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -48,6 +34,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [Natuurpunt](https://wiki.openstreetmap.org/wiki/Tag:operator%3DNatuurpunt) [](https://taginfo.openstreetmap.org/keys/colour#values) [colour](https://wiki.openstreetmap.org/wiki/Key:colour) | [color](../SpecialInputElements.md#color) | [blue](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dblue) [red](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dred) [green](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dgreen) [yellow](https://wiki.openstreetmap.org/wiki/Tag:colour%3Dyellow) @@ -57,6 +44,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -164,6 +170,52 @@ The question is *Is deze wandeltocht toegankelijk met de buggy?* - *deze wandeltocht is toegankelijk met de buggy* corresponds with `pushchair=yes` - *deze wandeltocht is niet toegankelijk met de buggy* corresponds with `pushchair=no` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/trail/trail.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/trail/trail.json) diff --git a/Docs/Layers/transit_routes.md b/Docs/Layers/transit_routes.md index 2097edc06..bb26d0d75 100644 --- a/Docs/Layers/transit_routes.md +++ b/Docs/Layers/transit_routes.md @@ -30,22 +30,7 @@ Layer showing bus lines - [transit](https://mapcomplete.osm.be/transit) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - type=route - - route=bus - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22route%22%3D%22bus%22%5D%5B%22type%22%3D%22route%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/from#values) [from](https://wiki.openstreetmap.org/wiki/Key:from) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/via#values) [via](https://wiki.openstreetmap.org/wiki/Key:via) | [string](../SpecialInputElements.md#string) | @@ -73,6 +59,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### name @@ -167,6 +172,52 @@ This rendering asks information about the property [operator](https://wiki.open This is rendered with `This bus line is operated by {operator}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/transit_routes/transit_routes.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/transit_routes/transit_routes.json) diff --git a/Docs/Layers/transit_stops.md b/Docs/Layers/transit_stops.md index 38db6b0bb..0ef63ac19 100644 --- a/Docs/Layers/transit_stops.md +++ b/Docs/Layers/transit_stops.md @@ -30,21 +30,7 @@ Layer showing different types of transit stops. - [transit](https://mapcomplete.osm.be/transit) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - highway=bus_stop - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22highway%22%3D%22bus_stop%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -61,6 +47,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/name#values) [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | [](https://wiki.openstreetmap.org/wiki/Tag:name%3D) [](https://taginfo.openstreetmap.org/keys/shelter#values) [shelter](https://wiki.openstreetmap.org/wiki/Key:shelter) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:shelter%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:shelter%3Dno) [](https://taginfo.openstreetmap.org/keys/bench#values) [bench](https://wiki.openstreetmap.org/wiki/Key:bench) | Multiple choice | [yes](https://wiki.openstreetmap.org/wiki/Tag:bench%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:bench%3Dno) @@ -73,6 +60,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### stop_name @@ -242,6 +248,52 @@ This tagrendering is only visible in the popup if the following condition is met +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/tree_node.md b/Docs/Layers/tree_node.md index 3c4ad44b2..0c38205f9 100644 --- a/Docs/Layers/tree_node.md +++ b/Docs/Layers/tree_node.md @@ -29,21 +29,7 @@ A layer showing trees - [trees](https://mapcomplete.osm.be/trees) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - natural=tree - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22natural%22%3D%22tree%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/species:wikidata#values) [species:wikidata](https://wiki.openstreetmap.org/wiki/Key:species:wikidata) | [wikidata](../SpecialInputElements.md#wikidata) | [](https://taginfo.openstreetmap.org/keys/circumference#values) [circumference](https://wiki.openstreetmap.org/wiki/Key:circumference) | [pfloat](../SpecialInputElements.md#pfloat) | [](https://taginfo.openstreetmap.org/keys/height#values) [height](https://wiki.openstreetmap.org/wiki/Key:height) | [pfloat](../SpecialInputElements.md#pfloat) | @@ -74,6 +61,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -277,6 +283,72 @@ This is rendered with `0` - - - - -### translation-thanks - - - -This tagrendering has no question and is thus read-only - - - - - - - *You have contributed to translating MapComplete! That's awesome!* corresponds with `_translation_contributions>0` - - - - -### contributor-thanks - - - -This tagrendering has no question and is thus read-only - - - - - - - *You have contributed code to MapComplete with {_code_contributions} commits! That's awesome!* corresponds with `_code_contributions>0` - - This option cannot be chosen as answer - - - - -### show_debug - - - -The question is *Show user settings debug info?* - - - - - - - *Show debug info* corresponds with `mapcomplete-show_debug=yes` - - *Don't show debug info* corresponds with `mapcomplete-show_debug=no` - - *Don't show debug info* corresponds with `` - - This option cannot be chosen as answer - - - - -### debug - - - -This tagrendering has no question and is thus read-only - - - -This tagrendering is only visible in the popup if the following condition is met: `mapcomplete-show_debug=yes` - -This document is autogenerated from [assets/layers/usersettings/usersettings.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/usersettings/usersettings.json) diff --git a/Docs/Layers/veterinary.md b/Docs/Layers/veterinary.md index c3327b84a..c369115d7 100644 --- a/Docs/Layers/veterinary.md +++ b/Docs/Layers/veterinary.md @@ -29,21 +29,7 @@ A layer showing veterinarians - [pets](https://mapcomplete.osm.be/pets) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=veterinary - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22veterinary%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | [](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) | [](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) | @@ -68,6 +55,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### website @@ -148,6 +154,52 @@ This rendering asks information about the property [name](https://wiki.openstre This is rendered with `The name of this veterinarian is {name}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/veterinary/veterinary.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/veterinary/veterinary.json) diff --git a/Docs/Layers/viewpoint.md b/Docs/Layers/viewpoint.md index 21ae1e143..a362dea40 100644 --- a/Docs/Layers/viewpoint.md +++ b/Docs/Layers/viewpoint.md @@ -17,21 +17,7 @@ A nice viewpoint or nice view. Ideal to add an image if no other category fits - This layer is shown at zoomlevel **14** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - tourism=viewpoint - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22tourism%22%3D%22viewpoint%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -48,11 +34,31 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/description#values) [description](https://wiki.openstreetmap.org/wiki/Key:description) | [string](../SpecialInputElements.md#string) | +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -75,6 +81,52 @@ This rendering asks information about the property [description](https://wiki.o This is rendered with `{description}` + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/viewpoint/viewpoint.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/viewpoint/viewpoint.json) diff --git a/Docs/Layers/village_green.md b/Docs/Layers/village_green.md index f1bb70559..cc619d182 100644 --- a/Docs/Layers/village_green.md +++ b/Docs/Layers/village_green.md @@ -17,21 +17,7 @@ A layer showing village-green (which are communal green areas, but not quite par - This layer is shown at zoomlevel **0** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - landuse=village_green - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22landuse%22%3D%22village_green%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -40,6 +26,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### images @@ -70,6 +86,52 @@ This tagrendering has no question and is thus read-only This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/village_green/village_green.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/village_green/village_green.json) diff --git a/Docs/Layers/visitor_information_centre.md b/Docs/Layers/visitor_information_centre.md index 1fba4d006..6dcb9758d 100644 --- a/Docs/Layers/visitor_information_centre.md +++ b/Docs/Layers/visitor_information_centre.md @@ -17,27 +17,89 @@ A visitor center offers information about a specific attraction or place of inte - This layer is shown at zoomlevel **12** and higher - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - information=visitor_centre|information=office - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22information%22%3D%22visitor_centre%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22information%22%3D%22office%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap Supported attributes ---------------------- + + +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/visitor_information_centre/visitor_information_centre.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/visitor_information_centre/visitor_information_centre.json) diff --git a/Docs/Layers/walls_and_buildings.md b/Docs/Layers/walls_and_buildings.md index bc94001ea..7f2e8389d 100644 --- a/Docs/Layers/walls_and_buildings.md +++ b/Docs/Layers/walls_and_buildings.md @@ -46,21 +46,7 @@ Special builtin layer providing all walls and buildings. This layer is useful in - [surveillance](https://mapcomplete.osm.be/surveillance) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - barrier=wall|building~.+ - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22barrier%22%3D%22wall%22%5D(%7B%7Bbbox%7D%7D)%3B%0A%20%20%20%20nwr%5B%22building%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -69,6 +55,36 @@ Elements must have the all of following tags to be shown on this layer: +Warning: + +this quick overview is incomplete + + + +attribute | type | values which are supported by this layer +----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | + + + + +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + ### entrance_info @@ -95,6 +111,52 @@ This tagrendering has no question and is thus read-only -This tagrendering is only visible in the popup if the following condition is met: `_biggest_width_id~.+` +This tagrendering is only visible in the popup if the following condition is met: `_biggest_width_id~.+` + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + This document is autogenerated from [assets/layers/walls_and_buildings/walls_and_buildings.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/walls_and_buildings/walls_and_buildings.json) diff --git a/Docs/Layers/waste_basket.md b/Docs/Layers/waste_basket.md index 50e050b3f..92d1b780c 100644 --- a/Docs/Layers/waste_basket.md +++ b/Docs/Layers/waste_basket.md @@ -31,21 +31,7 @@ This is a public waste basket, thrash can, where you can throw away your thrash. - [waste_basket](https://mapcomplete.osm.be/waste_basket) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=waste_basket - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22waste_basket%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -62,12 +48,32 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/waste#values) [waste](https://wiki.openstreetmap.org/wiki/Key:waste) | Multiple choice | [trash](https://wiki.openstreetmap.org/wiki/Tag:waste%3Dtrash) [dog_excrement](https://wiki.openstreetmap.org/wiki/Tag:waste%3Ddog_excrement) [cigarettes](https://wiki.openstreetmap.org/wiki/Tag:waste%3Dcigarettes) [drugs](https://wiki.openstreetmap.org/wiki/Tag:waste%3Ddrugs) [sharps](https://wiki.openstreetmap.org/wiki/Tag:waste%3Dsharps) [plastic](https://wiki.openstreetmap.org/wiki/Tag:waste%3Dplastic) [](https://taginfo.openstreetmap.org/keys/vending#values) [vending](https://wiki.openstreetmap.org/wiki/Key:vending) | Multiple choice | [dog_excrement_bag](https://wiki.openstreetmap.org/wiki/Tag:vending%3Ddog_excrement_bag) [](https://wiki.openstreetmap.org/wiki/Tag:vending%3D) +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -120,6 +126,72 @@ The question is *Does this waste basket have a dispenser for dog excrement bags +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/waste_disposal.md b/Docs/Layers/waste_disposal.md index f34e824f8..d2cab62aa 100644 --- a/Docs/Layers/waste_disposal.md +++ b/Docs/Layers/waste_disposal.md @@ -29,21 +29,7 @@ Waste Disposal Bin, medium to large bin for disposal of (household) waste - [waste](https://mapcomplete.osm.be/waste) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - amenity=waste_disposal - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22amenity%22%3D%22waste_disposal%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/amenity#values) [amenity](https://wiki.openstreetmap.org/wiki/Key:amenity) | Multiple choice | [waste_disposal](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dwaste_disposal) [recycling](https://wiki.openstreetmap.org/wiki/Tag:amenity%3Drecycling) [](https://taginfo.openstreetmap.org/keys/access#values) [access](https://wiki.openstreetmap.org/wiki/Key:access) | [string](../SpecialInputElements.md#string) | [yes](https://wiki.openstreetmap.org/wiki/Tag:access%3Dyes) [no](https://wiki.openstreetmap.org/wiki/Tag:access%3Dno) [residents](https://wiki.openstreetmap.org/wiki/Tag:access%3Dresidents) [](https://taginfo.openstreetmap.org/keys/location#values) [location](https://wiki.openstreetmap.org/wiki/Key:location) | Multiple choice | [underground](https://wiki.openstreetmap.org/wiki/Tag:location%3Dunderground) [indoor](https://wiki.openstreetmap.org/wiki/Tag:location%3Dindoor) [](https://wiki.openstreetmap.org/wiki/Tag:location%3D) @@ -67,6 +54,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### images @@ -135,6 +141,72 @@ The question is *Where is this container located?* +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### move-button + + + +This tagrendering has no question and is thus read-only + + + + + +### delete-button + + + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + + + + + #### Filters diff --git a/Docs/Layers/watermill.md b/Docs/Layers/watermill.md deleted file mode 100644 index 12f1ea042..000000000 --- a/Docs/Layers/watermill.md +++ /dev/null @@ -1,112 +0,0 @@ - - - watermill -=========== - - - - - -Watermolens - - - - - - - - This layer is shown at zoomlevel **12** and higher - - - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - man_made=watermill - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22man_made%22%3D%22watermill%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) - - - - Supported attributes ----------------------- - - - -Warning: - -this quick overview is incomplete - - - -attribute | type | values which are supported by this layer ------------ | ------ | ------------------------------------------ -[](https://taginfo.openstreetmap.org/keys/access:description#values) [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) | [string](../SpecialInputElements.md#string) | -[](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [Natuurpunt](https://wiki.openstreetmap.org/wiki/Tag:operator%3DNatuurpunt) - - - - -### images - - - -This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` - -This tagrendering has no question and is thus read-only - - - - - -### Access tag - - - -The question is *Is dit gebied toegankelijk?* - -This rendering asks information about the property [access:description](https://wiki.openstreetmap.org/wiki/Key:access:description) - -This is rendered with `De toegankelijkheid van dit gebied is: {access:description}` - - - - - - - *Vrij toegankelijk* corresponds with `access=yes` - - *Niet toegankelijk* corresponds with `access=no` - - *Niet toegankelijk, want privégebied* corresponds with `access=private` - - *Toegankelijk, ondanks dat het privegebied is* corresponds with `access=permissive` - - *Enkel toegankelijk met een gids of tijdens een activiteit* corresponds with `access=guided` - - *Toegankelijk mits betaling* corresponds with `access=yes&fee=yes` - - - - -### Operator tag - - - -The question is *Wie beheert dit pad?* - -This rendering asks information about the property [operator](https://wiki.openstreetmap.org/wiki/Key:operator) - -This is rendered with `Beheer door {operator}` - - - - - - - *Dit gebied wordt beheerd door Natuurpunt* corresponds with `operator=Natuurpunt` - - *Dit gebied wordt beheerd door {operator}* corresponds with `operator~^((n|N)atuurpunt.*)$` - - This option cannot be chosen as answer - - -This document is autogenerated from [assets/layers/watermill/watermill.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/watermill/watermill.json) \ No newline at end of file diff --git a/Docs/Layers/windturbine.md b/Docs/Layers/windturbine.md index f80b08098..c924936dc 100644 --- a/Docs/Layers/windturbine.md +++ b/Docs/Layers/windturbine.md @@ -29,21 +29,7 @@ Modern windmills generating electricity - [personal](https://mapcomplete.osm.be/personal) - - - Basic tags for this layer ---------------------------- - - - -Elements must have the all of following tags to be shown on this layer: - - - - - generator:source=wind - - -[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B(%20%20%20%20nwr%5B%22generator%3Asource%22%3D%22wind%22%5D(%7B%7Bbbox%7D%7D)%3B%0A)%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B) +This is a special layer - data is not sourced from OpenStreetMap @@ -60,6 +46,7 @@ this quick overview is incomplete attribute | type | values which are supported by this layer ----------- | ------ | ------------------------------------------ +[](https://taginfo.openstreetmap.org/keys/id#values) [id](https://wiki.openstreetmap.org/wiki/Key:id) | Multiple choice | [](https://taginfo.openstreetmap.org/keys/generator:output:electricity#values) [generator:output:electricity](https://wiki.openstreetmap.org/wiki/Key:generator:output:electricity) | [pfloat](../SpecialInputElements.md#pfloat) | [](https://taginfo.openstreetmap.org/keys/operator#values) [operator](https://wiki.openstreetmap.org/wiki/Key:operator) | [string](../SpecialInputElements.md#string) | [](https://taginfo.openstreetmap.org/keys/height#values) [height](https://wiki.openstreetmap.org/wiki/Key:height) | [pfloat](../SpecialInputElements.md#pfloat) | @@ -70,6 +57,25 @@ attribute | type | values which are supported by this layer +### just_created + + + +This element shows a 'thank you' that the contributor has recently created this element + +This tagrendering has no question and is thus read-only + + + + + + - *You just created this element! Thanks for sharing this info with the world and helping people worldwide.* corresponds with `id~.+` + + +This tagrendering is only visible in the popup if the following condition is met: `_backend~.+&_last_edit:passed_time<300&|_version_number=1` + + + ### turbine-output @@ -162,6 +168,52 @@ This block shows the known images which are linked with the `image`-keys, but al This tagrendering has no question and is thus read-only + + + + +### leftover-questions + + + +This tagrendering has no question and is thus read-only + + + + + +### minimap + + + +Shows a small map with the feature. Added by default to every popup + +This tagrendering has no question and is thus read-only + + + + + +### last_edit + + + +Gives some metainfo about the last edit and who did edit it - rendering only + +This tagrendering has no question and is thus read-only + + + +This tagrendering is only visible in the popup if the following condition is met: `_last_edit:contributor~.+&_last_edit:changeset~.+` + + + +### all-tags + + + +This tagrendering has no question and is thus read-only + This document is autogenerated from [assets/layers/windturbine/windturbine.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/layers/windturbine/windturbine.json) diff --git a/Docs/Schemas/DenominationConfigJson.schema.json b/Docs/Schemas/DenominationConfigJson.schema.json index a24185884..cfde14010 100644 --- a/Docs/Schemas/DenominationConfigJson.schema.json +++ b/Docs/Schemas/DenominationConfigJson.schema.json @@ -59,6 +59,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -122,10 +130,6 @@ "canonicalDenomination" ], "additionalProperties": false - }, - "Record": { - "type": "object", - "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/Docs/Schemas/DenominationConfigJsonJSC.ts b/Docs/Schemas/DenominationConfigJsonJSC.ts index 34b627f58..fd7b2494f 100644 --- a/Docs/Schemas/DenominationConfigJsonJSC.ts +++ b/Docs/Schemas/DenominationConfigJsonJSC.ts @@ -57,6 +57,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -119,9 +125,6 @@ export default { "required": [ "canonicalDenomination" ] - }, - "Record": { - "type": "object" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/Docs/Schemas/LayerConfigJson.schema.json b/Docs/Schemas/LayerConfigJson.schema.json index 4f052337c..e7eb813fc 100644 --- a/Docs/Schemas/LayerConfigJson.schema.json +++ b/Docs/Schemas/LayerConfigJson.schema.json @@ -7,90 +7,80 @@ "type": "string" }, "name": { - "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control" - }, - "description": { - "description": "A description for this layer.\nShown in the layer selections and in the personel theme" - }, - "source": { - "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.", + "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control", "anyOf": [ { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "$ref": "#/definitions/TagConfigJson", - "description": "Every source must set which tags have to be present in order to load the given layer." - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "description": { + "description": "A description for this layer.\nShown in the layer selections and in the personel theme", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "source": { + "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.\n\nNote: a source must always be defined. 'special' is only allowed if this is a builtin-layer", + "anyOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "$ref": "#/definitions/TagConfigJson", + "description": "Every source must set which tags have to be present in order to load the given layer." }, - { - "type": "object", - "properties": { - "overpassScript": { - "description": "If set, this custom overpass-script will be used instead of building one by using the OSM-tags.\nSpecifying OSM-tags is still obligatory and will still hide non-matching items and they will be used for the rest of the pipeline.\n_This should be really rare_.\n\nFor example, when you want to fetch all grass-areas in parks and which are marked as publicly accessible:\n```\n\"source\": {\n \"overpassScript\":\n \"way[\\\"leisure\\\"=\\\"park\\\"];node(w);is_in;area._[\\\"leisure\\\"=\\\"park\\\"];(way(area)[\\\"landuse\\\"=\\\"grass\\\"]; node(w); );\",\n \"osmTags\": \"access=yes\"\n}\n```", - "type": "string" - } - } + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" } + }, + "required": [ + "osmTags" ] }, { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "$ref": "#/definitions/TagConfigJson", - "description": "Every source must set which tags have to be present in order to load the given layer." - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] + "type": "object", + "properties": { + "geoJson": { + "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", + "type": "string" }, - { - "type": "object", - "properties": { - "geoJson": { - "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", - "type": "string" - }, - "geoJsonZoomLevel": { - "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", - "type": "number" - }, - "isOsmCache": { - "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", - "type": "boolean" - }, - "mercatorCrs": { - "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", - "type": "boolean" - }, - "idKey": { - "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", - "type": "string" - } - }, - "required": [ - "geoJson" - ] + "geoJsonZoomLevel": { + "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", + "type": "number" + }, + "isOsmCache": { + "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", + "type": "boolean" + }, + "mercatorCrs": { + "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", + "type": "boolean" + }, + "idKey": { + "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", + "type": "string" } + }, + "required": [ + "geoJson" ] + }, + { + "enum": [ + "special", + "special:library" + ], + "type": "string" } ] }, @@ -214,7 +204,15 @@ "type": "object", "properties": { "title": { - "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!" + "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "tags": { "description": "The tags to add. It determines the icon too", @@ -224,7 +222,15 @@ } }, "description": { - "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)" + "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "exampleImages": { "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", @@ -299,6 +305,9 @@ { "type": "object", "properties": { + "id": { + "type": "string" + }, "builtin": { "anyOf": [ { @@ -321,28 +330,6 @@ "override" ] }, - { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "builtin": { - "type": "array", - "items": { - "type": "string" - } - }, - "override": { - "$ref": "#/definitions/Partial" - } - }, - "required": [ - "builtin", - "id", - "override" - ] - }, { "allOf": [ { @@ -507,6 +494,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -571,10 +566,6 @@ ], "additionalProperties": false }, - "Record": { - "type": "object", - "additionalProperties": false - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -583,10 +574,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -594,11 +581,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -616,6 +659,22 @@ } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -640,7 +699,15 @@ "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", @@ -796,7 +863,7 @@ "type": "object", "properties": { "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint.\n'projected_centerpoint' will show an item on the line itself, near the middle of the line. (LineStrings only)", + "description": "All the locations that this point should be rendered at.\nPossible values are:\n- `point`: only renders points at their location\n- `centroid`: show a symbol at the centerpoint of a (multi)Linestring and (multi)polygon. Points will _not_ be rendered with this\n- `projected_centerpoint`: Only on (multi)linestrings: calculate the centerpoint and snap it to the way\n- `start` and `end`: only on linestrings: add a point to the first/last coordinate of the LineString", "type": "array", "items": { "type": "string" @@ -875,7 +942,7 @@ ] }, "css": { - "description": "A snippet of css code", + "description": "A snippet of css code which is applied onto the container of the entire marker", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -886,7 +953,7 @@ ] }, "cssClasses": { - "description": "A snippet of css-classes. They can be space-separated", + "description": "A snippet of css-classes which are applied onto the container of the entire marker. They can be space-separated", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -895,6 +962,58 @@ "type": "string" } ] + }, + "labelCss": { + "description": "Css that is applied onto the label", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "labelCssClasses": { + "description": "Css classes that are applied onto the label; can be space-separated", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "pitchAlignment": { + "description": "If the map is pitched, the marker will stay parallel to the screen.\nSet to 'map' if you want to put it flattened on the map", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] + }, + "rotationAlignment": { + "description": "If the map is rotated, the icon will still point to the north if no rotation was applied", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] } }, "required": [ @@ -1101,7 +1220,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -1128,10 +1247,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -1139,11 +1254,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -1160,6 +1331,22 @@ "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } }, "additionalProperties": false @@ -1216,7 +1403,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -1243,10 +1430,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -1254,11 +1437,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -1275,6 +1514,22 @@ "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } }, "additionalProperties": false diff --git a/Docs/Schemas/LayerConfigJsonJSC.ts b/Docs/Schemas/LayerConfigJsonJSC.ts index b03cc5a5d..4eaf333ef 100644 --- a/Docs/Schemas/LayerConfigJsonJSC.ts +++ b/Docs/Schemas/LayerConfigJsonJSC.ts @@ -7,90 +7,80 @@ export default { "type": "string" }, "name": { - "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control" - }, - "description": { - "description": "A description for this layer.\nShown in the layer selections and in the personel theme" - }, - "source": { - "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.", + "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control", "anyOf": [ { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "$ref": "#/definitions/TagConfigJson", - "description": "Every source must set which tags have to be present in order to load the given layer." - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "description": { + "description": "A description for this layer.\nShown in the layer selections and in the personel theme", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "source": { + "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.\n\nNote: a source must always be defined. 'special' is only allowed if this is a builtin-layer", + "anyOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "$ref": "#/definitions/TagConfigJson", + "description": "Every source must set which tags have to be present in order to load the given layer." }, - { - "type": "object", - "properties": { - "overpassScript": { - "description": "If set, this custom overpass-script will be used instead of building one by using the OSM-tags.\nSpecifying OSM-tags is still obligatory and will still hide non-matching items and they will be used for the rest of the pipeline.\n_This should be really rare_.\n\nFor example, when you want to fetch all grass-areas in parks and which are marked as publicly accessible:\n```\n\"source\": {\n \"overpassScript\":\n \"way[\\\"leisure\\\"=\\\"park\\\"];node(w);is_in;area._[\\\"leisure\\\"=\\\"park\\\"];(way(area)[\\\"landuse\\\"=\\\"grass\\\"]; node(w); );\",\n \"osmTags\": \"access=yes\"\n}\n```", - "type": "string" - } - } + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" } + }, + "required": [ + "osmTags" ] }, { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "$ref": "#/definitions/TagConfigJson", - "description": "Every source must set which tags have to be present in order to load the given layer." - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] + "type": "object", + "properties": { + "geoJson": { + "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", + "type": "string" }, - { - "type": "object", - "properties": { - "geoJson": { - "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", - "type": "string" - }, - "geoJsonZoomLevel": { - "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", - "type": "number" - }, - "isOsmCache": { - "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", - "type": "boolean" - }, - "mercatorCrs": { - "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", - "type": "boolean" - }, - "idKey": { - "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", - "type": "string" - } - }, - "required": [ - "geoJson" - ] + "geoJsonZoomLevel": { + "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", + "type": "number" + }, + "isOsmCache": { + "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", + "type": "boolean" + }, + "mercatorCrs": { + "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", + "type": "boolean" + }, + "idKey": { + "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", + "type": "string" } + }, + "required": [ + "geoJson" ] + }, + { + "enum": [ + "special", + "special:library" + ], + "type": "string" } ] }, @@ -214,7 +204,15 @@ export default { "type": "object", "properties": { "title": { - "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!" + "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "tags": { "description": "The tags to add. It determines the icon too", @@ -224,7 +222,15 @@ export default { } }, "description": { - "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)" + "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "exampleImages": { "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", @@ -299,6 +305,9 @@ export default { { "type": "object", "properties": { + "id": { + "type": "string" + }, "builtin": { "anyOf": [ { @@ -321,28 +330,6 @@ export default { "override" ] }, - { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "builtin": { - "type": "array", - "items": { - "type": "string" - } - }, - "override": { - "$ref": "#/definitions/Partial" - } - }, - "required": [ - "builtin", - "id", - "override" - ] - }, { "allOf": [ { @@ -505,6 +492,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -568,9 +561,6 @@ export default { "canonicalDenomination" ] }, - "Record": { - "type": "object" - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -579,10 +569,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -590,11 +576,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -612,6 +654,22 @@ export default { } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -636,7 +694,15 @@ export default { "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", @@ -788,7 +854,7 @@ export default { "type": "object", "properties": { "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint.\n'projected_centerpoint' will show an item on the line itself, near the middle of the line. (LineStrings only)", + "description": "All the locations that this point should be rendered at.\nPossible values are:\n- `point`: only renders points at their location\n- `centroid`: show a symbol at the centerpoint of a (multi)Linestring and (multi)polygon. Points will _not_ be rendered with this\n- `projected_centerpoint`: Only on (multi)linestrings: calculate the centerpoint and snap it to the way\n- `start` and `end`: only on linestrings: add a point to the first/last coordinate of the LineString", "type": "array", "items": { "type": "string" @@ -867,7 +933,7 @@ export default { ] }, "css": { - "description": "A snippet of css code", + "description": "A snippet of css code which is applied onto the container of the entire marker", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -878,7 +944,7 @@ export default { ] }, "cssClasses": { - "description": "A snippet of css-classes. They can be space-separated", + "description": "A snippet of css-classes which are applied onto the container of the entire marker. They can be space-separated", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -887,6 +953,58 @@ export default { "type": "string" } ] + }, + "labelCss": { + "description": "Css that is applied onto the label", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "labelCssClasses": { + "description": "Css classes that are applied onto the label; can be space-separated", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "pitchAlignment": { + "description": "If the map is pitched, the marker will stay parallel to the screen.\nSet to 'map' if you want to put it flattened on the map", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] + }, + "rotationAlignment": { + "description": "If the map is rotated, the icon will still point to the north if no rotation was applied", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] } }, "required": [ @@ -1090,7 +1208,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -1117,10 +1235,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -1128,11 +1242,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -1149,6 +1319,22 @@ export default { "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } } }, @@ -1204,7 +1390,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -1231,10 +1417,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -1242,11 +1424,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -1263,6 +1501,22 @@ export default { "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } } }, diff --git a/Docs/Schemas/LayoutConfigJson.schema.json b/Docs/Schemas/LayoutConfigJson.schema.json index 76889c941..c004dda31 100644 --- a/Docs/Schemas/LayoutConfigJson.schema.json +++ b/Docs/Schemas/LayoutConfigJson.schema.json @@ -18,16 +18,48 @@ } }, "title": { - "description": "The title, as shown in the welcome message and the more-screen." + "description": "The title, as shown in the welcome message and the more-screen.", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "shortDescription": { - "description": "A short description, showed as social description and in the 'more theme'-buttons.\nNote that if this one is not defined, the first sentence of 'description' is used" + "description": "A short description, showed as social description and in the 'more theme'-buttons.\nNote that if this one is not defined, the first sentence of 'description' is used", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "description": { - "description": "The description, as shown in the welcome message and the more-screen" + "description": "The description, as shown in the welcome message and the more-screen", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "descriptionTail": { - "description": "A part of the description, shown under the login-button." + "description": "A part of the description, shown under the login-button.", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "The icon representing this theme.\nUsed as logo in the more-screen and (for official themes) as favicon, webmanifest logo, ...\nEither a URL or a base64 encoded value (which should include 'data:image/svg+xml;base64)\n\nType: icon", @@ -71,7 +103,19 @@ "description": "Define some (overlay) slippy map tilesources", "type": "array", "items": { - "$ref": "#/definitions/default_6" + "allOf": [ + { + "$ref": "#/definitions/RasterLayerProperties" + }, + { + "type": "object", + "properties": { + "defaultState": { + "type": "boolean" + } + } + } + ] } }, "layers": { @@ -98,7 +142,9 @@ } ] }, - "override": {}, + "override": { + "$ref": "#/definitions/Partial" + }, "hideTagRenderingsWithLabels": { "description": "TagRenderings with any of these labels will be removed from the layer.\nNote that the 'id' and 'group' are considered labels too", "type": "array", @@ -118,30 +164,6 @@ ] } }, - "clustering": { - "description": "If defined, data will be clustered.\nDefaults to {maxZoom: 16, minNeeded: 500}", - "anyOf": [ - { - "type": "object", - "properties": { - "maxZoom": { - "description": "All zoom levels above 'maxzoom' are not clustered anymore.\nDefaults to 18", - "type": "number" - }, - "minNeededElements": { - "description": "The number of elements per tile needed to start clustering\nIf clustering is defined, defaults to 250", - "type": "number" - } - } - }, - { - "enum": [ - false - ], - "type": "boolean" - } - ] - }, "customCss": { "description": "The URL of a custom CSS stylesheet to modify the layout", "type": "string" @@ -266,6 +288,10 @@ "overpassTimeout": { "description": "Set a different timeout for overpass queries - in seconds. Default: 30s", "type": "number" + }, + "enableNodeDatabase": { + "description": "Enables tracking of all nodes when data is loaded.\nThis is useful for the 'ImportWay' and 'ConflateWay'-buttons who need this database.\n\nNote: this flag will be automatically set.", + "type": "boolean" } }, "required": [ @@ -337,6 +363,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -401,10 +435,6 @@ ], "additionalProperties": false }, - "Record": { - "type": "object", - "additionalProperties": false - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -413,10 +443,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -424,11 +450,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -446,6 +528,22 @@ } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -470,7 +568,15 @@ "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", @@ -626,7 +732,7 @@ "type": "object", "properties": { "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint.\n'projected_centerpoint' will show an item on the line itself, near the middle of the line. (LineStrings only)", + "description": "All the locations that this point should be rendered at.\nPossible values are:\n- `point`: only renders points at their location\n- `centroid`: show a symbol at the centerpoint of a (multi)Linestring and (multi)polygon. Points will _not_ be rendered with this\n- `projected_centerpoint`: Only on (multi)linestrings: calculate the centerpoint and snap it to the way\n- `start` and `end`: only on linestrings: add a point to the first/last coordinate of the LineString", "type": "array", "items": { "type": "string" @@ -705,7 +811,7 @@ ] }, "css": { - "description": "A snippet of css code", + "description": "A snippet of css code which is applied onto the container of the entire marker", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -716,7 +822,7 @@ ] }, "cssClasses": { - "description": "A snippet of css-classes. They can be space-separated", + "description": "A snippet of css-classes which are applied onto the container of the entire marker. They can be space-separated", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -725,6 +831,58 @@ "type": "string" } ] + }, + "labelCss": { + "description": "Css that is applied onto the label", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "labelCssClasses": { + "description": "Css classes that are applied onto the label; can be space-separated", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "pitchAlignment": { + "description": "If the map is pitched, the marker will stay parallel to the screen.\nSet to 'map' if you want to put it flattened on the map", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] + }, + "rotationAlignment": { + "description": "If the map is rotated, the icon will still point to the north if no rotation was applied", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] } }, "required": [ @@ -931,7 +1089,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -958,10 +1116,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -969,11 +1123,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -990,6 +1200,22 @@ "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } }, "additionalProperties": false @@ -1046,7 +1272,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -1073,10 +1299,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -1084,11 +1306,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -1105,6 +1383,22 @@ "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } }, "additionalProperties": false @@ -1359,42 +1653,63 @@ "type": "object", "additionalProperties": false }, - "default_6": { - "description": "Configuration for a tilesource config", + "RasterLayerProperties": { "type": "object", "properties": { - "id": { - "description": "Id of this overlay, used in the URL-parameters to set the state", - "type": "string" - }, - "source": { - "description": "The path, where {x}, {y} and {z} will be substituted", - "type": "string" + "name": { + "description": "The name of the imagery source", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "isOverlay": { - "description": "Wether or not this is an overlay. Default: true", "type": "boolean" }, - "name": { - "description": "How this will be shown in the selection menu.\nMake undefined if this may not be toggled" + "id": { + "type": "string" }, - "minZoom": { - "description": "Only visible at this or a higher zoom level", + "url": { + "type": "string" + }, + "category": { + "type": "string" + }, + "attribution": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "text": { + "type": "string" + }, + "html": { + "type": "string" + }, + "required": { + "type": "boolean" + } + } + }, + "min_zoom": { "type": "number" }, - "maxZoom": { - "description": "Only visible at this or a lower zoom level", + "max_zoom": { "type": "number" }, - "defaultState": { - "description": "The default state, set to false to hide by default", + "best": { "type": "boolean" } }, "required": [ - "defaultState", "id", - "source" + "name", + "url" ], "additionalProperties": false }, @@ -1407,90 +1722,80 @@ "type": "string" }, "name": { - "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control" - }, - "description": { - "description": "A description for this layer.\nShown in the layer selections and in the personel theme" - }, - "source": { - "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.", + "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control", "anyOf": [ { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "$ref": "#/definitions/TagConfigJson", - "description": "Every source must set which tags have to be present in order to load the given layer." - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "description": { + "description": "A description for this layer.\nShown in the layer selections and in the personel theme", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "source": { + "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.\n\nNote: a source must always be defined. 'special' is only allowed if this is a builtin-layer", + "anyOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "$ref": "#/definitions/TagConfigJson", + "description": "Every source must set which tags have to be present in order to load the given layer." }, - { - "type": "object", - "properties": { - "overpassScript": { - "description": "If set, this custom overpass-script will be used instead of building one by using the OSM-tags.\nSpecifying OSM-tags is still obligatory and will still hide non-matching items and they will be used for the rest of the pipeline.\n_This should be really rare_.\n\nFor example, when you want to fetch all grass-areas in parks and which are marked as publicly accessible:\n```\n\"source\": {\n \"overpassScript\":\n \"way[\\\"leisure\\\"=\\\"park\\\"];node(w);is_in;area._[\\\"leisure\\\"=\\\"park\\\"];(way(area)[\\\"landuse\\\"=\\\"grass\\\"]; node(w); );\",\n \"osmTags\": \"access=yes\"\n}\n```", - "type": "string" - } - } + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" } + }, + "required": [ + "osmTags" ] }, { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "$ref": "#/definitions/TagConfigJson", - "description": "Every source must set which tags have to be present in order to load the given layer." - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] + "type": "object", + "properties": { + "geoJson": { + "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", + "type": "string" }, - { - "type": "object", - "properties": { - "geoJson": { - "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", - "type": "string" - }, - "geoJsonZoomLevel": { - "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", - "type": "number" - }, - "isOsmCache": { - "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", - "type": "boolean" - }, - "mercatorCrs": { - "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", - "type": "boolean" - }, - "idKey": { - "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", - "type": "string" - } - }, - "required": [ - "geoJson" - ] + "geoJsonZoomLevel": { + "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", + "type": "number" + }, + "isOsmCache": { + "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", + "type": "boolean" + }, + "mercatorCrs": { + "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", + "type": "boolean" + }, + "idKey": { + "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", + "type": "string" } + }, + "required": [ + "geoJson" ] + }, + { + "enum": [ + "special", + "special:library" + ], + "type": "string" } ] }, @@ -1614,7 +1919,15 @@ "type": "object", "properties": { "title": { - "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!" + "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "tags": { "description": "The tags to add. It determines the icon too", @@ -1624,7 +1937,15 @@ } }, "description": { - "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)" + "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "exampleImages": { "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", @@ -1699,6 +2020,9 @@ { "type": "object", "properties": { + "id": { + "type": "string" + }, "builtin": { "anyOf": [ { @@ -1721,28 +2045,6 @@ "override" ] }, - { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "builtin": { - "type": "array", - "items": { - "type": "string" - } - }, - "override": { - "$ref": "#/definitions/Partial" - } - }, - "required": [ - "builtin", - "id", - "override" - ] - }, { "allOf": [ { @@ -1850,6 +2152,439 @@ ], "additionalProperties": false }, + "Partial": { + "type": "object", + "properties": { + "id": { + "description": "The id of this layer.\nThis should be a simple, lowercase, human readable string that is used to identify the layer.", + "type": "string" + }, + "name": { + "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "description": { + "description": "A description for this layer.\nShown in the layer selections and in the personel theme", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "source": { + "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.\n\nNote: a source must always be defined. 'special' is only allowed if this is a builtin-layer", + "anyOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "$ref": "#/definitions/TagConfigJson", + "description": "Every source must set which tags have to be present in order to load the given layer." + }, + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" + } + }, + "required": [ + "osmTags" + ] + }, + { + "type": "object", + "properties": { + "geoJson": { + "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", + "type": "string" + }, + "geoJsonZoomLevel": { + "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", + "type": "number" + }, + "isOsmCache": { + "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", + "type": "boolean" + }, + "mercatorCrs": { + "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", + "type": "boolean" + }, + "idKey": { + "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", + "type": "string" + } + }, + "required": [ + "geoJson" + ] + }, + { + "enum": [ + "special", + "special:library" + ], + "type": "string" + } + ] + }, + "calculatedTags": { + "description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to Docs/CalculatedTags.md for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]", + "type": "array", + "items": { + "type": "string" + } + }, + "doNotDownload": { + "description": "If set, this layer will not query overpass; but it'll still match the tags above which are by chance returned by other layers.\nWorks well together with 'passAllFeatures', to add decoration", + "type": "boolean" + }, + "isShown": { + "description": "If set, only features matching this extra tag will be shown.\nThis is useful to hide certain features from view.\n\nImportant: hiding features does not work dynamically, but is only calculated when the data is first renders.\nThis implies that it is not possible to hide a feature after a tagging change\n\nThe default value is 'yes'", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, + "forceLoad": { + "description": "Advanced option - might be set by the theme compiler\n\nIf true, this data will _always_ be loaded, even if the theme is disabled", + "type": "boolean" + }, + "minzoom": { + "description": "The minimum needed zoomlevel required before loading of the data start\nDefault: 0", + "type": "number" + }, + "shownByDefault": { + "description": "Indicates if this layer is shown by default;\ncan be used to hide a layer from start, or to load the layer but only to show it where appropriate (e.g. for snapping to it)", + "type": "boolean" + }, + "minzoomVisible": { + "description": "The zoom level at which point the data is hidden again\nDefault: 100 (thus: always visible", + "type": "number" + }, + "title": { + "description": "The title shown in a popup for elements of this layer.", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "titleIcons": { + "description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]", + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + { + "type": "array", + "items": [ + { + "type": "string", + "enum": [ + "defaults" + ] + } + ], + "minItems": 1, + "maxItems": 1 + } + ] + }, + "mapRendering": { + "description": "Visualisation of the items on the map", + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/default_4" + }, + { + "$ref": "#/definitions/default_5" + }, + { + "$ref": "#/definitions/default" + } + ] + } + }, + { + "type": "null" + } + ] + }, + "passAllFeatures": { + "description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directionss on cameras", + "type": "boolean" + }, + "presets": { + "description": "Presets for this layer.\nA preset shows up when clicking the map on a without data (or when right-clicking/long-pressing);\nit will prompt the user to add a new point.\n\nThe most important aspect are the tags, which define which tags the new point will have;\nThe title is shown in the dialog, along with the first sentence of the description.\n\nUpon confirmation, the full description is shown beneath the buttons - perfect to add pictures and examples.\n\nNote: the icon of the preset is determined automatically based on the tags and the icon above. Don't worry about that!\nNB: if no presets are defined, the popup to add new points doesn't show up at all", + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "tags": { + "description": "The tags to add. It determines the icon too", + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "exampleImages": { + "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", + "type": "array", + "items": { + "type": "string" + } + }, + "preciseInput": { + "description": "If set, the user will prompted to confirm the location before actually adding the data.\nThis will be with a 'drag crosshair'-method.\n\nIf 'preferredBackgroundCategory' is set, the element will attempt to pick a background layer of that category.", + "anyOf": [ + { + "type": "object", + "properties": { + "preferredBackground": { + "description": "The type of background picture", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "snapToLayer": { + "description": "If specified, these layers will be shown to and the new point will be snapped towards it", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "maxSnapDistance": { + "description": "If specified, a new point will only be snapped if it is within this range.\nDistance in meter\n\nDefault: 10", + "type": "number" + } + } + }, + { + "enum": [ + true + ], + "type": "boolean" + } + ] + } + }, + "required": [ + "tags", + "title" + ] + } + }, + "tagRenderings": { + "description": "All the tag renderings.\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together", + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/QuestionableTagRenderingConfigJson" + }, + { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "builtin": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "override": { + "$ref": "#/definitions/Partial" + } + }, + "required": [ + "builtin", + "override" + ] + }, + { + "allOf": [ + { + "$ref": "#/definitions/default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:Partial;})[]>" + }, + { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ] + } + ] + }, + { + "type": "string" + } + ] + } + }, + "filter": { + "description": "All the extra questions for filtering.\nIf a string is given, mapComplete will search in 'filters.json' for the appropriate filter or will try to parse it as `layername.filterid` and us that one", + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/default_1" + }, + { + "type": "string" + } + ] + } + }, + { + "type": "object", + "properties": { + "sameAs": { + "type": "string" + } + }, + "required": [ + "sameAs" + ] + } + ] + }, + "deletion": { + "description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n The delete dialog\n =================\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted from OSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n#### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.", + "anyOf": [ + { + "$ref": "#/definitions/DeleteConfigJson" + }, + { + "type": "boolean" + } + ] + }, + "allowMove": { + "description": "Indicates if a point can be moved and configures the modalities.\n\nA feature can be moved by MapComplete if:\n\n- It is a point\n- The point is _not_ part of a way or a a relation.\n\nOff by default. Can be enabled by setting this flag or by configuring.", + "anyOf": [ + { + "$ref": "#/definitions/default_3" + }, + { + "type": "boolean" + } + ] + }, + "allowSplit": { + "description": "If set, a 'split this way' button is shown on objects rendered as LineStrings, e.g. highways.\n\nIf the way is part of a relation, MapComplete will attempt to update this relation as well", + "type": "boolean" + }, + "units": { + "type": "array", + "items": { + "$ref": "#/definitions/default_2" + } + }, + "syncSelection": { + "description": "If set, synchronizes whether or not this layer is enabled.\n\nno: Do not sync at all, always revert to default\nlocal: keep selection on local storage\ntheme-only: sync via OSM, but this layer will only be toggled in this theme\nglobal: all layers with this ID will be synced accross all themes", + "enum": [ + "global", + "local", + "no", + "theme-only" + ], + "type": "string" + }, + "#": { + "description": "Used for comments and/or to disable some checks\n\nno-question-hint-check: disables a check in MiscTagRenderingChecks which complains about 'div', 'span' or 'class=subtle'-HTML elements in the tagRendering", + "type": "string" + } + }, + "additionalProperties": false + }, "default": { "type": "object", "properties": { diff --git a/Docs/Schemas/LayoutConfigJsonJSC.ts b/Docs/Schemas/LayoutConfigJsonJSC.ts index 2172da51d..7c396ce1e 100644 --- a/Docs/Schemas/LayoutConfigJsonJSC.ts +++ b/Docs/Schemas/LayoutConfigJsonJSC.ts @@ -18,16 +18,48 @@ export default { } }, "title": { - "description": "The title, as shown in the welcome message and the more-screen." + "description": "The title, as shown in the welcome message and the more-screen.", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "shortDescription": { - "description": "A short description, showed as social description and in the 'more theme'-buttons.\nNote that if this one is not defined, the first sentence of 'description' is used" + "description": "A short description, showed as social description and in the 'more theme'-buttons.\nNote that if this one is not defined, the first sentence of 'description' is used", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "description": { - "description": "The description, as shown in the welcome message and the more-screen" + "description": "The description, as shown in the welcome message and the more-screen", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "descriptionTail": { - "description": "A part of the description, shown under the login-button." + "description": "A part of the description, shown under the login-button.", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "The icon representing this theme.\nUsed as logo in the more-screen and (for official themes) as favicon, webmanifest logo, ...\nEither a URL or a base64 encoded value (which should include 'data:image/svg+xml;base64)\n\nType: icon", @@ -71,7 +103,19 @@ export default { "description": "Define some (overlay) slippy map tilesources", "type": "array", "items": { - "$ref": "#/definitions/default_6" + "allOf": [ + { + "$ref": "#/definitions/RasterLayerProperties" + }, + { + "type": "object", + "properties": { + "defaultState": { + "type": "boolean" + } + } + } + ] } }, "layers": { @@ -98,7 +142,9 @@ export default { } ] }, - "override": {}, + "override": { + "$ref": "#/definitions/Partial" + }, "hideTagRenderingsWithLabels": { "description": "TagRenderings with any of these labels will be removed from the layer.\nNote that the 'id' and 'group' are considered labels too", "type": "array", @@ -118,30 +164,6 @@ export default { ] } }, - "clustering": { - "description": "If defined, data will be clustered.\nDefaults to {maxZoom: 16, minNeeded: 500}", - "anyOf": [ - { - "type": "object", - "properties": { - "maxZoom": { - "description": "All zoom levels above 'maxzoom' are not clustered anymore.\nDefaults to 18", - "type": "number" - }, - "minNeededElements": { - "description": "The number of elements per tile needed to start clustering\nIf clustering is defined, defaults to 250", - "type": "number" - } - } - }, - { - "enum": [ - false - ], - "type": "boolean" - } - ] - }, "customCss": { "description": "The URL of a custom CSS stylesheet to modify the layout", "type": "string" @@ -266,6 +288,10 @@ export default { "overpassTimeout": { "description": "Set a different timeout for overpass queries - in seconds. Default: 30s", "type": "number" + }, + "enableNodeDatabase": { + "description": "Enables tracking of all nodes when data is loaded.\nThis is useful for the 'ImportWay' and 'ConflateWay'-buttons who need this database.\n\nNote: this flag will be automatically set.", + "type": "boolean" } }, "required": [ @@ -335,6 +361,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -398,9 +430,6 @@ export default { "canonicalDenomination" ] }, - "Record": { - "type": "object" - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -409,10 +438,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -420,11 +445,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -442,6 +523,22 @@ export default { } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -466,7 +563,15 @@ export default { "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", @@ -618,7 +723,7 @@ export default { "type": "object", "properties": { "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint.\n'projected_centerpoint' will show an item on the line itself, near the middle of the line. (LineStrings only)", + "description": "All the locations that this point should be rendered at.\nPossible values are:\n- `point`: only renders points at their location\n- `centroid`: show a symbol at the centerpoint of a (multi)Linestring and (multi)polygon. Points will _not_ be rendered with this\n- `projected_centerpoint`: Only on (multi)linestrings: calculate the centerpoint and snap it to the way\n- `start` and `end`: only on linestrings: add a point to the first/last coordinate of the LineString", "type": "array", "items": { "type": "string" @@ -697,7 +802,7 @@ export default { ] }, "css": { - "description": "A snippet of css code", + "description": "A snippet of css code which is applied onto the container of the entire marker", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -708,7 +813,7 @@ export default { ] }, "cssClasses": { - "description": "A snippet of css-classes. They can be space-separated", + "description": "A snippet of css-classes which are applied onto the container of the entire marker. They can be space-separated", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -717,6 +822,58 @@ export default { "type": "string" } ] + }, + "labelCss": { + "description": "Css that is applied onto the label", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "labelCssClasses": { + "description": "Css classes that are applied onto the label; can be space-separated", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "pitchAlignment": { + "description": "If the map is pitched, the marker will stay parallel to the screen.\nSet to 'map' if you want to put it flattened on the map", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] + }, + "rotationAlignment": { + "description": "If the map is rotated, the icon will still point to the north if no rotation was applied", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] } }, "required": [ @@ -920,7 +1077,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -947,10 +1104,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -958,11 +1111,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -979,6 +1188,22 @@ export default { "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } } }, @@ -1034,7 +1259,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -1061,10 +1286,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -1072,11 +1293,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -1093,6 +1370,22 @@ export default { "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } } }, @@ -1340,42 +1633,63 @@ export default { "Partial": { "type": "object" }, - "default_6": { - "description": "Configuration for a tilesource config", + "RasterLayerProperties": { "type": "object", "properties": { - "id": { - "description": "Id of this overlay, used in the URL-parameters to set the state", - "type": "string" - }, - "source": { - "description": "The path, where {x}, {y} and {z} will be substituted", - "type": "string" + "name": { + "description": "The name of the imagery source", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "isOverlay": { - "description": "Wether or not this is an overlay. Default: true", "type": "boolean" }, - "name": { - "description": "How this will be shown in the selection menu.\nMake undefined if this may not be toggled" + "id": { + "type": "string" }, - "minZoom": { - "description": "Only visible at this or a higher zoom level", + "url": { + "type": "string" + }, + "category": { + "type": "string" + }, + "attribution": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "text": { + "type": "string" + }, + "html": { + "type": "string" + }, + "required": { + "type": "boolean" + } + } + }, + "min_zoom": { "type": "number" }, - "maxZoom": { - "description": "Only visible at this or a lower zoom level", + "max_zoom": { "type": "number" }, - "defaultState": { - "description": "The default state, set to false to hide by default", + "best": { "type": "boolean" } }, "required": [ - "defaultState", "id", - "source" + "name", + "url" ] }, "LayerConfigJson": { @@ -1387,90 +1701,80 @@ export default { "type": "string" }, "name": { - "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control" - }, - "description": { - "description": "A description for this layer.\nShown in the layer selections and in the personel theme" - }, - "source": { - "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.", + "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control", "anyOf": [ { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "$ref": "#/definitions/TagConfigJson", - "description": "Every source must set which tags have to be present in order to load the given layer." - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "description": { + "description": "A description for this layer.\nShown in the layer selections and in the personel theme", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "source": { + "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.\n\nNote: a source must always be defined. 'special' is only allowed if this is a builtin-layer", + "anyOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "$ref": "#/definitions/TagConfigJson", + "description": "Every source must set which tags have to be present in order to load the given layer." }, - { - "type": "object", - "properties": { - "overpassScript": { - "description": "If set, this custom overpass-script will be used instead of building one by using the OSM-tags.\nSpecifying OSM-tags is still obligatory and will still hide non-matching items and they will be used for the rest of the pipeline.\n_This should be really rare_.\n\nFor example, when you want to fetch all grass-areas in parks and which are marked as publicly accessible:\n```\n\"source\": {\n \"overpassScript\":\n \"way[\\\"leisure\\\"=\\\"park\\\"];node(w);is_in;area._[\\\"leisure\\\"=\\\"park\\\"];(way(area)[\\\"landuse\\\"=\\\"grass\\\"]; node(w); );\",\n \"osmTags\": \"access=yes\"\n}\n```", - "type": "string" - } - } + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" } + }, + "required": [ + "osmTags" ] }, { - "allOf": [ - { - "type": "object", - "properties": { - "osmTags": { - "$ref": "#/definitions/TagConfigJson", - "description": "Every source must set which tags have to be present in order to load the given layer." - }, - "maxCacheAge": { - "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", - "type": "number" - } - }, - "required": [ - "osmTags" - ] + "type": "object", + "properties": { + "geoJson": { + "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", + "type": "string" }, - { - "type": "object", - "properties": { - "geoJson": { - "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", - "type": "string" - }, - "geoJsonZoomLevel": { - "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", - "type": "number" - }, - "isOsmCache": { - "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", - "type": "boolean" - }, - "mercatorCrs": { - "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", - "type": "boolean" - }, - "idKey": { - "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", - "type": "string" - } - }, - "required": [ - "geoJson" - ] + "geoJsonZoomLevel": { + "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", + "type": "number" + }, + "isOsmCache": { + "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", + "type": "boolean" + }, + "mercatorCrs": { + "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", + "type": "boolean" + }, + "idKey": { + "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", + "type": "string" } + }, + "required": [ + "geoJson" ] + }, + { + "enum": [ + "special", + "special:library" + ], + "type": "string" } ] }, @@ -1594,7 +1898,15 @@ export default { "type": "object", "properties": { "title": { - "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!" + "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "tags": { "description": "The tags to add. It determines the icon too", @@ -1604,7 +1916,15 @@ export default { } }, "description": { - "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)" + "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "exampleImages": { "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", @@ -1679,6 +1999,9 @@ export default { { "type": "object", "properties": { + "id": { + "type": "string" + }, "builtin": { "anyOf": [ { @@ -1701,28 +2024,6 @@ export default { "override" ] }, - { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "builtin": { - "type": "array", - "items": { - "type": "string" - } - }, - "override": { - "$ref": "#/definitions/Partial" - } - }, - "required": [ - "builtin", - "id", - "override" - ] - }, { "allOf": [ { @@ -1829,6 +2130,438 @@ export default { "source" ] }, + "Partial": { + "type": "object", + "properties": { + "id": { + "description": "The id of this layer.\nThis should be a simple, lowercase, human readable string that is used to identify the layer.", + "type": "string" + }, + "name": { + "description": "The name of this layer\nUsed in the layer control panel and the 'Personal theme'.\n\nIf not given, will be hidden (and thus not toggable) in the layer control", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "description": { + "description": "A description for this layer.\nShown in the layer selections and in the personel theme", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "source": { + "description": "This determines where the data for the layer is fetched: from OSM or from an external geojson dataset.\n\nIf no 'geojson' is defined, data will be fetched from overpass and the OSM-API.\n\nEvery source _must_ define which tags _must_ be present in order to be picked up.\n\nNote: a source must always be defined. 'special' is only allowed if this is a builtin-layer", + "anyOf": [ + { + "type": "object", + "properties": { + "osmTags": { + "$ref": "#/definitions/TagConfigJson", + "description": "Every source must set which tags have to be present in order to load the given layer." + }, + "maxCacheAge": { + "description": "The maximum amount of seconds that a tile is allowed to linger in the cache", + "type": "number" + } + }, + "required": [ + "osmTags" + ] + }, + { + "type": "object", + "properties": { + "geoJson": { + "description": "The actual source of the data to load, if loaded via geojson.\n\n# A single geojson-file\nsource: {geoJson: \"https://my.source.net/some-geo-data.geojson\"}\n fetches a geojson from a third party source\n\n# A tiled geojson source\nsource: {geoJson: \"https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson\", geoJsonZoomLevel: 14}\n to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer\n\nSome API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max}", + "type": "string" + }, + "geoJsonZoomLevel": { + "description": "To load a tiled geojson layer, set the zoomlevel of the tiles", + "type": "number" + }, + "isOsmCache": { + "description": "Indicates that the upstream geojson data is OSM-derived.\nUseful for e.g. merging or for scripts generating this cache", + "type": "boolean" + }, + "mercatorCrs": { + "description": "Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this", + "type": "boolean" + }, + "idKey": { + "description": "Some API's have an id-field, but give it a different name.\nSetting this key will rename this field into 'id'", + "type": "string" + } + }, + "required": [ + "geoJson" + ] + }, + { + "enum": [ + "special", + "special:library" + ], + "type": "string" + } + ] + }, + "calculatedTags": { + "description": "A list of extra tags to calculate, specified as \"keyToAssignTo=javascript-expression\".\nThere are a few extra functions available. Refer to Docs/CalculatedTags.md for more information\nThe functions will be run in order, e.g.\n[\n \"_max_overlap_m2=Math.max(...feat.overlapsWith(\"someOtherLayer\").map(o => o.overlap))\n \"_max_overlap_ratio=Number(feat._max_overlap_m2)/feat.area\n]\n\nThe specified tags are evaluated lazily. E.g. if a calculated tag is only used in the popup (e.g. the number of nearby features),\nthe expensive calculation will only be performed then for that feature. This avoids clogging up the contributors PC when all features are loaded.\n\nIf a tag has to be evaluated strictly, use ':=' instead:\n\n[\n\"_some_key:=some_javascript_expression\"\n]", + "type": "array", + "items": { + "type": "string" + } + }, + "doNotDownload": { + "description": "If set, this layer will not query overpass; but it'll still match the tags above which are by chance returned by other layers.\nWorks well together with 'passAllFeatures', to add decoration", + "type": "boolean" + }, + "isShown": { + "description": "If set, only features matching this extra tag will be shown.\nThis is useful to hide certain features from view.\n\nImportant: hiding features does not work dynamically, but is only calculated when the data is first renders.\nThis implies that it is not possible to hide a feature after a tagging change\n\nThe default value is 'yes'", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, + "forceLoad": { + "description": "Advanced option - might be set by the theme compiler\n\nIf true, this data will _always_ be loaded, even if the theme is disabled", + "type": "boolean" + }, + "minzoom": { + "description": "The minimum needed zoomlevel required before loading of the data start\nDefault: 0", + "type": "number" + }, + "shownByDefault": { + "description": "Indicates if this layer is shown by default;\ncan be used to hide a layer from start, or to load the layer but only to show it where appropriate (e.g. for snapping to it)", + "type": "boolean" + }, + "minzoomVisible": { + "description": "The zoom level at which point the data is hidden again\nDefault: 100 (thus: always visible", + "type": "number" + }, + "title": { + "description": "The title shown in a popup for elements of this layer.", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "titleIcons": { + "description": "Small icons shown next to the title.\nIf not specified, the OsmLink and wikipedia links will be used by default.\nUse an empty array to hide them.\nNote that \"defaults\" will insert all the default titleIcons (which are added automatically)\n\nType: icon[]", + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + } + }, + { + "type": "array", + "items": [ + { + "type": "string", + "enum": [ + "defaults" + ] + } + ], + "minItems": 1, + "maxItems": 1 + } + ] + }, + "mapRendering": { + "description": "Visualisation of the items on the map", + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/default_4" + }, + { + "$ref": "#/definitions/default_5" + }, + { + "$ref": "#/definitions/default" + } + ] + } + }, + { + "type": "null" + } + ] + }, + "passAllFeatures": { + "description": "If set, this layer will pass all the features it receives onto the next layer.\nThis is ideal for decoration, e.g. directionss on cameras", + "type": "boolean" + }, + "presets": { + "description": "Presets for this layer.\nA preset shows up when clicking the map on a without data (or when right-clicking/long-pressing);\nit will prompt the user to add a new point.\n\nThe most important aspect are the tags, which define which tags the new point will have;\nThe title is shown in the dialog, along with the first sentence of the description.\n\nUpon confirmation, the full description is shown beneath the buttons - perfect to add pictures and examples.\n\nNote: the icon of the preset is determined automatically based on the tags and the icon above. Don't worry about that!\nNB: if no presets are defined, the popup to add new points doesn't show up at all", + "type": "array", + "items": { + "type": "object", + "properties": { + "title": { + "description": "The title - shown on the 'add-new'-button.\n\nThis should include the article of the noun, e.g. 'a hydrant', 'a bicycle pump'.\nThis text will be inserted into `Add {category} here`, becoming `Add a hydrant here`.\n\nDo _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped!", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "tags": { + "description": "The tags to add. It determines the icon too", + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "description": "The _first sentence_ of the description is shown on the button of the `add` menu.\nThe full description is shown in the confirmation dialog.\n\n(The first sentence is until the first '.'-character in the description)", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] + }, + "exampleImages": { + "description": "Example images, which show real-life pictures of what such a feature might look like\n\nType: image", + "type": "array", + "items": { + "type": "string" + } + }, + "preciseInput": { + "description": "If set, the user will prompted to confirm the location before actually adding the data.\nThis will be with a 'drag crosshair'-method.\n\nIf 'preferredBackgroundCategory' is set, the element will attempt to pick a background layer of that category.", + "anyOf": [ + { + "type": "object", + "properties": { + "preferredBackground": { + "description": "The type of background picture", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "snapToLayer": { + "description": "If specified, these layers will be shown to and the new point will be snapped towards it", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "maxSnapDistance": { + "description": "If specified, a new point will only be snapped if it is within this range.\nDistance in meter\n\nDefault: 10", + "type": "number" + } + } + }, + { + "enum": [ + true + ], + "type": "boolean" + } + ] + } + }, + "required": [ + "tags", + "title" + ] + } + }, + "tagRenderings": { + "description": "All the tag renderings.\nA tag rendering is a block that either shows the known value or asks a question.\n\nRefer to the class `TagRenderingConfigJson` to see the possibilities.\n\nNote that we can also use a string here - where the string refers to a tag rendering defined in `assets/questions/questions.json`,\nwhere a few very general questions are defined e.g. website, phone number, ...\nFurthermore, _all_ the questions of another layer can be reused with `otherlayer.*`\nIf you need only a single of the tagRenderings, use `otherlayer.tagrenderingId`\nIf one or more questions have a 'group' or 'label' set, select all the entries with the corresponding group or label with `otherlayer.*group`\nRemark: if a tagRendering is 'lent' from another layer, the 'source'-tags are copied and added as condition.\nIf they are not wanted, remove them with an override\n\nA special value is 'questions', which indicates the location of the questions box. If not specified, it'll be appended to the bottom of the featureInfobox.\n\nAt last, one can define a group of renderings where parts of all strings will be replaced by multiple other strings.\nThis is mainly create questions for a 'left' and a 'right' side of the road.\nThese will be grouped and questions will be asked together", + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/QuestionableTagRenderingConfigJson" + }, + { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "builtin": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, + "override": { + "$ref": "#/definitions/Partial" + } + }, + "required": [ + "builtin", + "override" + ] + }, + { + "allOf": [ + { + "$ref": "#/definitions/default<(string|QuestionableTagRenderingConfigJson|{builtin:string;override:Partial;})[]>" + }, + { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ] + } + ] + }, + { + "type": "string" + } + ] + } + }, + "filter": { + "description": "All the extra questions for filtering.\nIf a string is given, mapComplete will search in 'filters.json' for the appropriate filter or will try to parse it as `layername.filterid` and us that one", + "anyOf": [ + { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/default_1" + }, + { + "type": "string" + } + ] + } + }, + { + "type": "object", + "properties": { + "sameAs": { + "type": "string" + } + }, + "required": [ + "sameAs" + ] + } + ] + }, + "deletion": { + "description": "This block defines under what circumstances the delete dialog is shown for objects of this layer.\nIf set, a dialog is shown to the user to (soft) delete the point.\nThe dialog is built to be user friendly and to prevent mistakes.\nIf deletion is not possible, the dialog will hide itself and show the reason of non-deletability instead.\n\nTo configure, the following values are possible:\n\n- false: never ever show the delete button\n- true: show the default delete button\n- undefined: use the mapcomplete default to show deletion or not. Currently, this is the same as 'false' but this will change in the future\n- or: a hash with options (see below)\n\n The delete dialog\n =================\n\n\n\n#### Hard deletion if enough experience\n\nA feature can only be deleted from OpenStreetMap by mapcomplete if:\n\n- It is a node\n- No ways or relations use the node\n- The logged-in user has enough experience OR the user is the only one to have edited the point previously\n- The logged-in user has no unread messages (or has a ton of experience)\n- The user did not select one of the 'non-delete-options' (see below)\n\nIn all other cases, a 'soft deletion' is used.\n\n#### Soft deletion\n\nA 'soft deletion' is when the point isn't deleted from OSM but retagged so that it'll won't how up in the mapcomplete theme anymore.\nThis makes it look like it was deleted, without doing damage. A fixme will be added to the point.\n\nNote that a soft deletion is _only_ possible if these tags are provided by the theme creator, as they'll be different for every theme\n\n#### No-delete options\n\nIn some cases, the contributor might want to delete something for the wrong reason (e.g. someone who wants to have a path removed \"because the path is on their private property\").\nHowever, the path exists in reality and should thus be on OSM - otherwise the next contributor will pass by and notice \"hey, there is a path missing here! Let me redraw it in OSM!)\n\nThe correct approach is to retag the feature in such a way that it is semantically correct *and* that it doesn't show up on the theme anymore.\nA no-delete option is offered as 'reason to delete it', but secretly retags.", + "anyOf": [ + { + "$ref": "#/definitions/DeleteConfigJson" + }, + { + "type": "boolean" + } + ] + }, + "allowMove": { + "description": "Indicates if a point can be moved and configures the modalities.\n\nA feature can be moved by MapComplete if:\n\n- It is a point\n- The point is _not_ part of a way or a a relation.\n\nOff by default. Can be enabled by setting this flag or by configuring.", + "anyOf": [ + { + "$ref": "#/definitions/default_3" + }, + { + "type": "boolean" + } + ] + }, + "allowSplit": { + "description": "If set, a 'split this way' button is shown on objects rendered as LineStrings, e.g. highways.\n\nIf the way is part of a relation, MapComplete will attempt to update this relation as well", + "type": "boolean" + }, + "units": { + "type": "array", + "items": { + "$ref": "#/definitions/default_2" + } + }, + "syncSelection": { + "description": "If set, synchronizes whether or not this layer is enabled.\n\nno: Do not sync at all, always revert to default\nlocal: keep selection on local storage\ntheme-only: sync via OSM, but this layer will only be toggled in this theme\nglobal: all layers with this ID will be synced accross all themes", + "enum": [ + "global", + "local", + "no", + "theme-only" + ], + "type": "string" + }, + "#": { + "description": "Used for comments and/or to disable some checks\n\nno-question-hint-check: disables a check in MiscTagRenderingChecks which complains about 'div', 'span' or 'class=subtle'-HTML elements in the tagRendering", + "type": "string" + } + } + }, "default": { "type": "object", "properties": { diff --git a/Docs/Schemas/LineRenderingConfigJson.schema.json b/Docs/Schemas/LineRenderingConfigJson.schema.json index c76fd695f..744b13d2b 100644 --- a/Docs/Schemas/LineRenderingConfigJson.schema.json +++ b/Docs/Schemas/LineRenderingConfigJson.schema.json @@ -146,6 +146,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -210,10 +218,6 @@ ], "additionalProperties": false }, - "Record": { - "type": "object", - "additionalProperties": false - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -222,10 +226,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -233,11 +233,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -255,6 +311,22 @@ } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -279,7 +351,15 @@ "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/LineRenderingConfigJsonJSC.ts b/Docs/Schemas/LineRenderingConfigJsonJSC.ts index ba475b1ce..db7177b6f 100644 --- a/Docs/Schemas/LineRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/LineRenderingConfigJsonJSC.ts @@ -144,6 +144,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -207,9 +213,6 @@ export default { "canonicalDenomination" ] }, - "Record": { - "type": "object" - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -218,10 +221,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -229,11 +228,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -251,6 +306,22 @@ export default { } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -275,7 +346,15 @@ export default { "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/MappingConfigJson.schema.json b/Docs/Schemas/MappingConfigJson.schema.json index 2a33419bb..2b5926dd8 100644 --- a/Docs/Schemas/MappingConfigJson.schema.json +++ b/Docs/Schemas/MappingConfigJson.schema.json @@ -162,6 +162,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -226,10 +234,6 @@ ], "additionalProperties": false }, - "Record": { - "type": "object", - "additionalProperties": false - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -238,10 +242,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -249,11 +249,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -271,6 +327,22 @@ } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -295,7 +367,15 @@ "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/MappingConfigJsonJSC.ts b/Docs/Schemas/MappingConfigJsonJSC.ts index d7ae48b03..b53c9837b 100644 --- a/Docs/Schemas/MappingConfigJsonJSC.ts +++ b/Docs/Schemas/MappingConfigJsonJSC.ts @@ -160,6 +160,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -223,9 +229,6 @@ export default { "canonicalDenomination" ] }, - "Record": { - "type": "object" - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -234,10 +237,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -245,11 +244,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -267,6 +322,22 @@ export default { } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -291,7 +362,15 @@ export default { "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/MoveConfigJson.schema.json b/Docs/Schemas/MoveConfigJson.schema.json index b851d9fbb..33c89a5ba 100644 --- a/Docs/Schemas/MoveConfigJson.schema.json +++ b/Docs/Schemas/MoveConfigJson.schema.json @@ -69,6 +69,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -132,10 +140,6 @@ "canonicalDenomination" ], "additionalProperties": false - }, - "Record": { - "type": "object", - "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/Docs/Schemas/MoveConfigJsonJSC.ts b/Docs/Schemas/MoveConfigJsonJSC.ts index f963559b9..2d2565825 100644 --- a/Docs/Schemas/MoveConfigJsonJSC.ts +++ b/Docs/Schemas/MoveConfigJsonJSC.ts @@ -67,6 +67,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -129,9 +135,6 @@ export default { "required": [ "canonicalDenomination" ] - }, - "Record": { - "type": "object" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/Docs/Schemas/PointRenderingConfigJson.schema.json b/Docs/Schemas/PointRenderingConfigJson.schema.json index cb5fbcbf2..a8c0069fd 100644 --- a/Docs/Schemas/PointRenderingConfigJson.schema.json +++ b/Docs/Schemas/PointRenderingConfigJson.schema.json @@ -3,7 +3,7 @@ "type": "object", "properties": { "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint.\n'projected_centerpoint' will show an item on the line itself, near the middle of the line. (LineStrings only)", + "description": "All the locations that this point should be rendered at.\nPossible values are:\n- `point`: only renders points at their location\n- `centroid`: show a symbol at the centerpoint of a (multi)Linestring and (multi)polygon. Points will _not_ be rendered with this\n- `projected_centerpoint`: Only on (multi)linestrings: calculate the centerpoint and snap it to the way\n- `start` and `end`: only on linestrings: add a point to the first/last coordinate of the LineString", "type": "array", "items": { "type": "string" @@ -82,7 +82,7 @@ ] }, "css": { - "description": "A snippet of css code", + "description": "A snippet of css code which is applied onto the container of the entire marker", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -93,7 +93,7 @@ ] }, "cssClasses": { - "description": "A snippet of css-classes. They can be space-separated", + "description": "A snippet of css-classes which are applied onto the container of the entire marker. They can be space-separated", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -102,6 +102,58 @@ "type": "string" } ] + }, + "labelCss": { + "description": "Css that is applied onto the label", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "labelCssClasses": { + "description": "Css classes that are applied onto the label; can be space-separated", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "pitchAlignment": { + "description": "If the map is pitched, the marker will stay parallel to the screen.\nSet to 'map' if you want to put it flattened on the map", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] + }, + "rotationAlignment": { + "description": "If the map is rotated, the icon will still point to the north if no rotation was applied", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] } }, "required": [ @@ -166,6 +218,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -230,10 +290,6 @@ ], "additionalProperties": false }, - "Record": { - "type": "object", - "additionalProperties": false - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -242,10 +298,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -253,11 +305,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -275,6 +383,22 @@ } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -299,7 +423,15 @@ "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/PointRenderingConfigJsonJSC.ts b/Docs/Schemas/PointRenderingConfigJsonJSC.ts index 0a63aafea..974a1735f 100644 --- a/Docs/Schemas/PointRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/PointRenderingConfigJsonJSC.ts @@ -3,7 +3,7 @@ export default { "type": "object", "properties": { "location": { - "description": "All the locations that this point should be rendered at.\nUsing `location: [\"point\", \"centroid\"] will always render centerpoint.\n'projected_centerpoint' will show an item on the line itself, near the middle of the line. (LineStrings only)", + "description": "All the locations that this point should be rendered at.\nPossible values are:\n- `point`: only renders points at their location\n- `centroid`: show a symbol at the centerpoint of a (multi)Linestring and (multi)polygon. Points will _not_ be rendered with this\n- `projected_centerpoint`: Only on (multi)linestrings: calculate the centerpoint and snap it to the way\n- `start` and `end`: only on linestrings: add a point to the first/last coordinate of the LineString", "type": "array", "items": { "type": "string" @@ -82,7 +82,7 @@ export default { ] }, "css": { - "description": "A snippet of css code", + "description": "A snippet of css code which is applied onto the container of the entire marker", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -93,7 +93,7 @@ export default { ] }, "cssClasses": { - "description": "A snippet of css-classes. They can be space-separated", + "description": "A snippet of css-classes which are applied onto the container of the entire marker. They can be space-separated", "anyOf": [ { "$ref": "#/definitions/TagRenderingConfigJson" @@ -102,6 +102,58 @@ export default { "type": "string" } ] + }, + "labelCss": { + "description": "Css that is applied onto the label", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "labelCssClasses": { + "description": "Css classes that are applied onto the label; can be space-separated", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "type": "string" + } + ] + }, + "pitchAlignment": { + "description": "If the map is pitched, the marker will stay parallel to the screen.\nSet to 'map' if you want to put it flattened on the map", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] + }, + "rotationAlignment": { + "description": "If the map is rotated, the icon will still point to the north if no rotation was applied", + "anyOf": [ + { + "$ref": "#/definitions/TagRenderingConfigJson" + }, + { + "enum": [ + "canvas", + "map" + ], + "type": "string" + } + ] } }, "required": [ @@ -164,6 +216,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -227,9 +285,6 @@ export default { "canonicalDenomination" ] }, - "Record": { - "type": "object" - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -238,10 +293,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -249,11 +300,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -271,6 +378,22 @@ export default { } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -295,7 +418,15 @@ export default { "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/QuestionableTagRenderingConfigJson.schema.json b/Docs/Schemas/QuestionableTagRenderingConfigJson.schema.json index f7529d6d2..2eabe2ca6 100644 --- a/Docs/Schemas/QuestionableTagRenderingConfigJson.schema.json +++ b/Docs/Schemas/QuestionableTagRenderingConfigJson.schema.json @@ -51,7 +51,7 @@ } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -78,10 +78,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -89,11 +85,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -110,6 +162,22 @@ "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } }, "definitions": { @@ -171,6 +239,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -235,10 +311,6 @@ ], "additionalProperties": false }, - "Record": { - "type": "object", - "additionalProperties": false - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -247,10 +319,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -258,11 +326,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -280,6 +404,22 @@ } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -304,7 +444,15 @@ "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts b/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts index 8db0039d6..b0b2b1689 100644 --- a/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/QuestionableTagRenderingConfigJsonJSC.ts @@ -51,7 +51,7 @@ export default { } }, "inline": { - "description": "When set, influences the way a question is asked.\nInstead of showing a full-widht text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.", + "description": "When set, influences the way a question is asked.\nInstead of showing a full-width text field, the text field will be shown within the rendering of the question.\n\nThis combines badly with special input elements, as it'll distort the layout.\nNote that this will be set automatically if no special elements are present.", "type": "boolean" }, "default": { @@ -78,10 +78,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -89,11 +85,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -110,6 +162,22 @@ export default { "type": "string" } ] + }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] } }, "definitions": { @@ -169,6 +237,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -232,9 +306,6 @@ export default { "canonicalDenomination" ] }, - "Record": { - "type": "object" - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -243,10 +314,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -254,11 +321,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -276,6 +399,22 @@ export default { } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -300,7 +439,15 @@ export default { "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/RewritableConfigJson.schema.json b/Docs/Schemas/RewritableConfigJson.schema.json index 477a3f981..01dbd836f 100644 --- a/Docs/Schemas/RewritableConfigJson.schema.json +++ b/Docs/Schemas/RewritableConfigJson.schema.json @@ -91,6 +91,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -155,10 +163,6 @@ ], "additionalProperties": false }, - "Record": { - "type": "object", - "additionalProperties": false - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -167,10 +171,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -178,11 +178,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -200,6 +256,22 @@ } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -224,7 +296,15 @@ "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/RewritableConfigJsonJSC.ts b/Docs/Schemas/RewritableConfigJsonJSC.ts index 6c1e7fac5..b173395d5 100644 --- a/Docs/Schemas/RewritableConfigJsonJSC.ts +++ b/Docs/Schemas/RewritableConfigJsonJSC.ts @@ -89,6 +89,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -152,9 +158,6 @@ export default { "canonicalDenomination" ] }, - "Record": { - "type": "object" - }, "TagRenderingConfigJson": { "description": "A TagRenderingConfigJson is a single piece of code which converts one ore more tags into a HTML-snippet.\nFor an _editable_ tagRendering, use 'QuestionableTagRenderingConfigJson' instead, which extends this one", "type": "object", @@ -163,10 +166,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -174,11 +173,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -196,6 +251,22 @@ export default { } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -220,7 +291,15 @@ export default { "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", diff --git a/Docs/Schemas/TagRenderingConfigJson.schema.json b/Docs/Schemas/TagRenderingConfigJson.schema.json index 1f09125f4..3453db4de 100644 --- a/Docs/Schemas/TagRenderingConfigJson.schema.json +++ b/Docs/Schemas/TagRenderingConfigJson.schema.json @@ -6,10 +6,6 @@ "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -17,11 +13,67 @@ "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -39,6 +91,22 @@ } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -63,7 +131,15 @@ "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", @@ -155,6 +231,14 @@ "or" ], "additionalProperties": false + }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/Docs/Schemas/TagRenderingConfigJsonJSC.ts b/Docs/Schemas/TagRenderingConfigJsonJSC.ts index f3823873a..c2bdd5fe0 100644 --- a/Docs/Schemas/TagRenderingConfigJsonJSC.ts +++ b/Docs/Schemas/TagRenderingConfigJsonJSC.ts @@ -6,10 +6,6 @@ export default { "description": "The id of the tagrendering, should be an unique string.\nUsed to keep the translations in sync. Only used in the tagRenderings-array of a layerConfig, not requered otherwise.\n\nUse 'questions' to trigger the question box of this group (if a group is defined)", "type": "string" }, - "group": { - "description": "If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well.\nThe first tagRendering of a group will always be a sticky element.", - "type": "string" - }, "labels": { "description": "A list of labels. These are strings that are used for various purposes, e.g. to filter them away", "type": "array", @@ -17,11 +13,67 @@ export default { "type": "string" } }, + "classes": { + "description": "A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question).\nThis is only for advanced users", + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + }, "description": { - "description": "A human-readable text explaining what this tagRendering does" + "description": "A human-readable text explaining what this tagRendering does", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "render": { - "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered" + "description": "Renders this value. Note that \"{key}\"-parts are substituted by the corresponding values of the element.\nIf neither 'textFieldQuestion' nor 'mappings' are defined, this text is simply shown as default value.\n\nNote that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
`\ntype: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "object", + "properties": { + "special": { + "allOf": [ + { + "$ref": "#/definitions/Record>" + }, + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ] + } + ] + } + }, + "required": [ + "special" + ] + }, + { + "type": "string" + } + ] }, "condition": { "description": "Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`.\n\nThis is useful to ask a follow-up question.\nFor example, within toilets, asking _where_ the diaper changing table is is only useful _if_ there is one.\nThis can be done by adding `\"condition\": \"changing_table=yes\"`\n\nA full example would be:\n```json\n {\n \"question\": \"Where is the changing table located?\",\n \"render\": \"The changing table is located at {changing_table:location}\",\n \"condition\": \"changing_table=yes\",\n \"freeform\": {\n \"key\": \"changing_table:location\",\n \"inline\": true\n },\n \"mappings\": [\n {\n \"then\": \"The changing table is in the toilet for women.\",\n \"if\": \"changing_table:location=female_toilet\"\n },\n {\n \"then\": \"The changing table is in the toilet for men.\",\n \"if\": \"changing_table:location=male_toilet\"\n },\n {\n \"if\": \"changing_table:location=wheelchair_toilet\",\n \"then\": \"The changing table is in the toilet for wheelchair users.\",\n },\n {\n \"if\": \"changing_table:location=dedicated_room\",\n \"then\": \"The changing table is in a dedicated room. \",\n }\n ],\n \"id\": \"toilet-changing_table:location\"\n },\n```", @@ -39,6 +91,22 @@ export default { } ] }, + "metacondition": { + "description": "If set, this tag will be evaluated agains the _usersettings/application state_ table.\nEnable 'show debug info' in user settings to see available options.\nNote that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_", + "anyOf": [ + { + "$ref": "#/definitions/AndTagConfigJson", + "description": "Chain many tags, to match, a single of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "$ref": "#/definitions/OrTagConfigJson", + "description": "Chain many tags, to match, all of these should be true\nSee https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md for documentation" + }, + { + "type": "string" + } + ] + }, "freeform": { "description": "Allow freeform text input from the user", "type": "object", @@ -63,7 +131,15 @@ export default { "description": "If this condition is met, then the text under `then` will be shown.\nIf no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.\n\nFor example: {'if': 'diet:vegetarion=yes', 'then':'A vegetarian option is offered here'}\n\nThis can be an substituting-tag as well, e.g. {'if': 'addr:street:={_calculated_nearby_streetname}', 'then': '{_calculated_nearby_streetname}'}" }, "then": { - "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered" + "description": "If the condition `if` is met, the text `then` will be rendered.\nIf not known yet, the user will be presented with `then` as an option\nType: rendered", + "anyOf": [ + { + "$ref": "#/definitions/Record" + }, + { + "type": "string" + } + ] }, "icon": { "description": "An icon supporting this mapping; typically shown pretty small\nType: icon", @@ -153,6 +229,12 @@ export default { "required": [ "or" ] + }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/Docs/Schemas/UnitConfigJson.schema.json b/Docs/Schemas/UnitConfigJson.schema.json index 6d885363b..624997222 100644 --- a/Docs/Schemas/UnitConfigJson.schema.json +++ b/Docs/Schemas/UnitConfigJson.schema.json @@ -88,6 +88,14 @@ ], "additionalProperties": false }, + "Record": { + "type": "object", + "additionalProperties": false + }, + "Record>": { + "type": "object", + "additionalProperties": false + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -151,10 +159,6 @@ "canonicalDenomination" ], "additionalProperties": false - }, - "Record": { - "type": "object", - "additionalProperties": false } }, "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/Docs/Schemas/UnitConfigJsonJSC.ts b/Docs/Schemas/UnitConfigJsonJSC.ts index b4b06c469..857c15586 100644 --- a/Docs/Schemas/UnitConfigJsonJSC.ts +++ b/Docs/Schemas/UnitConfigJsonJSC.ts @@ -86,6 +86,12 @@ export default { "or" ] }, + "Record": { + "type": "object" + }, + "Record>": { + "type": "object" + }, "DenominationConfigJson": { "type": "object", "properties": { @@ -148,9 +154,6 @@ export default { "required": [ "canonicalDenomination" ] - }, - "Record": { - "type": "object" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/Docs/SpecialInputElements.md b/Docs/SpecialInputElements.md index ed4c9b0f4..f9c1aa643 100644 --- a/Docs/SpecialInputElements.md +++ b/Docs/SpecialInputElements.md @@ -59,7 +59,7 @@ A date with date picker -A positive number or zero +A whole, positive number or zero @@ -67,7 +67,7 @@ A positive number or zero -A number +A whole number, either positive, negative or zero @@ -83,7 +83,11 @@ A geographical distance in meters (rounded at two points). Will give an extra mi -A geographical direction, in degrees. 0° is north, 90° is east, ... Will return a value between 0 (incl) and 360 (excl) +A geographical direction, in degrees. 0° is north, 90° is east, ... Will return a value between 0 (incl) and 360 (excl). + +### Input helper + +This element has an input helper showing a map and 'viewport' indicating the direction. By default, this map is zoomed to zoomlevel 17, but this can be changed with the first argument @@ -170,7 +174,7 @@ A strict positive number -A decimal +A decimal number @@ -178,7 +182,7 @@ A decimal -A positive decimal (inclusive zero) +A positive decimal number or zero @@ -194,7 +198,7 @@ An email adress -The validatedTextField will format URLs to always be valid and have a https://-header (even though the 'https'-part will be hidden from the user +The validatedTextField will format URLs to always be valid and have a https://-header (even though the 'https'-part will be hidden from the user. Furthermore, some tracking parameters will be removed @@ -255,4 +259,4 @@ postfix | Piece of text that will always be added to the end of the generated op Shows a color picker -This document is autogenerated from [UI/Input/ValidatedTextField.ts](https://github.com/pietervdvn/MapComplete/blob/develop/UI/Input/ValidatedTextField.ts) +This document is autogenerated from [UI/InputElement/Validators.ts](https://github.com/pietervdvn/MapComplete/blob/develop/UI/InputElement/Validators.ts) diff --git a/Docs/SpecialRenderings.md b/Docs/SpecialRenderings.md index 29b377775..e512a9559 100644 --- a/Docs/SpecialRenderings.md +++ b/Docs/SpecialRenderings.md @@ -48,38 +48,58 @@ In other words: use `{ "before": ..., "after": ..., "special": {"type": ..., "ar 1. [Special tag renderings](#special-tag-renderings) * [Using expanded syntax](#using-expanded-syntax) + + [questions](#questions) + * [Example usage of questions](#example-usage-of-questions) + + [add_new_point](#add_new_point) + * [Example usage of add_new_point](#example-usage-of-add_new_point) + + [user_profile](#user_profile) + * [Example usage of user_profile](#example-usage-of-user_profile) + + [language_picker](#language_picker) + * [Example usage of language_picker](#example-usage-of-language_picker) + + [logout](#logout) + * [Example usage of logout](#example-usage-of-logout) + [histogram](#histogram) * [Example usage of histogram](#example-usage-of-histogram) + [steal](#steal) * [Example usage of steal](#example-usage-of-steal) + [minimap](#minimap) * [Example usage of minimap](#example-usage-of-minimap) - + [sided_minimap](#sided_minimap) - * [Example usage of sided_minimap](#example-usage-of-sided_minimap) + + [split_button](#split_button) + * [Example usage of split_button](#example-usage-of-split_button) + + [move_button](#move_button) + * [Example usage of move_button](#example-usage-of-move_button) + + [delete_button](#delete_button) + * [Example usage of delete_button](#example-usage-of-delete_button) + [share_link](#share_link) * [Example usage of share_link](#example-usage-of-share_link) + + [export_as_gpx](#export_as_gpx) + * [Example usage of export_as_gpx](#example-usage-of-export_as_gpx) + [upload_to_osm](#upload_to_osm) * [Example usage of upload_to_osm](#example-usage-of-upload_to_osm) + [multi_apply](#multi_apply) * [Example usage of multi_apply](#example-usage-of-multi_apply) - + [export_as_gpx](#export_as_gpx) - * [Example usage of export_as_gpx](#example-usage-of-export_as_gpx) + [add_note_comment](#add_note_comment) * [Example usage of add_note_comment](#example-usage-of-add_note_comment) + + [open_note](#open_note) + * [Example usage of open_note](#example-usage-of-open_note) + + [close_note](#close_note) + * [Example usage of close_note](#example-usage-of-close_note) + [plantnet_detection](#plantnet_detection) * [Example usage of plantnet_detection](#example-usage-of-plantnet_detection) + + [tag_apply](#tag_apply) + * [Example usage of tag_apply](#example-usage-of-tag_apply) + [import_button](#import_button) * [Example usage of import_button](#example-usage-of-import_button) + [import_way_button](#import_way_button) * [Example usage of import_way_button](#example-usage-of-import_way_button) + [conflate_button](#conflate_button) * [Example usage of conflate_button](#example-usage-of-conflate_button) - + [tag_apply](#tag_apply) - * [Example usage of tag_apply](#example-usage-of-tag_apply) - + [close_note](#close_note) - * [Example usage of close_note](#example-usage-of-close_note) + [nearby_images](#nearby_images) * [Example usage of nearby_images](#example-usage-of-nearby_images) + + [wikipedia](#wikipedia) + * [Example usage of wikipedia](#example-usage-of-wikipedia) + + [wikidata_label](#wikidata_label) + * [Example usage of wikidata_label](#example-usage-of-wikidata_label) + [mapillary_link](#mapillary_link) * [Example usage of mapillary_link](#example-usage-of-mapillary_link) + [language_chooser](#language_chooser) @@ -90,10 +110,6 @@ In other words: use `{ "before": ..., "after": ..., "special": {"type": ..., "ar * [Example usage of image_carousel](#example-usage-of-image_carousel) + [image_upload](#image_upload) * [Example usage of image_upload](#example-usage-of-image_upload) - + [wikipedia](#wikipedia) - * [Example usage of wikipedia](#example-usage-of-wikipedia) - + [wikidata_label](#wikidata_label) - * [Example usage of wikidata_label](#example-usage-of-wikidata_label) + [reviews](#reviews) * [Example usage of reviews](#example-usage-of-reviews) + [opening_hours_table](#opening_hours_table) @@ -124,6 +140,8 @@ In other words: use `{ "before": ..., "after": ..., "special": {"type": ..., "ar * [Example usage of statistics](#example-usage-of-statistics) + [send_email](#send_email) * [Example usage of send_email](#example-usage-of-send_email) + + [link](#link) + * [Example usage of link](#example-usage-of-link) + [multi](#multi) * [Example usage of multi](#example-usage-of-multi) + [auto_apply](#auto_apply) @@ -133,6 +151,62 @@ In other words: use `{ "before": ..., "after": ..., "special": {"type": ..., "ar +### questions + + The special element which shows the questions which are unkown. Added by default if not yet there + +name | default | description +------ | --------- | ------------- +labels | _undefined_ | One or more ';'-separated labels. If these are given, only questions with these labels will be given. Use `unlabeled` for all questions that don't have an explicit label. If none given, all questions will be shown +blacklisted-labels | _undefined_ | One or more ';'-separated labels of questions which should _not_ be included + + +#### Example usage of questions + + `{questions(,)}` + + + +### add_new_point + + An element which allows to add a new point on the 'last_click'-location. Only makes sense in the layer `last_click` + +#### Example usage of add_new_point + + `{add_new_point()}` + + + +### user_profile + + A component showing information about the currently logged in user (username, profile description, profile picture + link to edit them). Mostly meant to be used in the 'user-settings' + +#### Example usage of user_profile + + `{user_profile()}` + + + +### language_picker + + A component to set the language of the user interface + +#### Example usage of language_picker + + `{language_picker()}` + + + +### logout + + Shows a button where the user can log out + +#### Example usage of logout + + `{logout()}` + + + ### histogram Create a histogram for a list of given values, read from the properties. @@ -147,7 +221,7 @@ colors* | _undefined_ | (Matches all resting arguments - optional) Matches a reg #### Example usage of histogram - `{histogram('some_key')}` with properties being `{some_key: ['a','b','a','c']} to create a histogram + `{histogram('some_key')}` with properties being `{some_key: ["a","b","a","c"]} to create a histogram @@ -183,18 +257,33 @@ idKey | id | (Matches all resting arguments) This argument should be the key of -### sided_minimap +### split_button - A small map showing _only one side_ the selected feature. *This features requires to have linerenderings with offset* as only linerenderings with a postive or negative offset will be shown. Note: in most cases, this map will be automatically introduced + Adds a button which allows to split a way -name | default | description ------- | --------- | ------------- -side | _undefined_ | The side to show, either `left` or `right` - +#### Example usage of split_button -#### Example usage of sided_minimap + `{split_button()}` - `{sided_minimap(left)}` + + +### move_button + + Adds a button which allows to move the object to another location. The config will be read from the layer config + +#### Example usage of move_button + + `{move_button()}` + + + +### delete_button + + Adds a button which allows to delete the object at this location. The config will be read from the layer config + +#### Example usage of delete_button + + `{delete_button()}` @@ -213,6 +302,16 @@ url | _undefined_ | The url to share (default: current URL) +### export_as_gpx + + Exports the selected feature as GPX-file + +#### Example usage of export_as_gpx + + `{export_as_gpx()}` + + + ### upload_to_osm Uploads the GPS-history as GPX to OpenStreetMap.org; clears the history afterwards. The actual feature is ignored. @@ -242,16 +341,6 @@ overwrite | _undefined_ | If set to 'true', the tags on the other objects will a -### export_as_gpx - - Exports the selected feature as GPX-file - -#### Example usage of export_as_gpx - - `{export_as_gpx()}` - - - ### add_note_comment A textfield to add a comment to a node (with the option to close the note). @@ -267,6 +356,36 @@ Id-key | id | The property name where the ID of the note to close can be found +### open_note + + Creates a new map note on the given location. This options is placed in the 'last_click'-popup automatically if the 'notes'-layer is enabled + +#### Example usage of open_note + + `{open_note()}` + + + +### close_note + + Button to close a note. A predifined text can be defined to close the note with. If the note is already closed, will show a small text. + +name | default | description +------ | --------- | ------------- +text | _undefined_ | Text to show on this button +icon | checkmark.svg | Icon to show +idkey | id | The property name where the ID of the note to close can be found +comment | _undefined_ | Text to add onto the note when closing +minZoom | _undefined_ | If set, only show the closenote button if zoomed in enough +zoomButton | _undefined_ | Text to show if not zoomed in enough + + +#### Example usage of close_note + + `{close_note(,checkmark.svg,id,,,)}` + + + ### plantnet_detection Sends the images linked to the current object to plantnet.org and asks it what plant species is shown on it. The user can then select the correct species; the corresponding wikidata-identifier will then be added to the object (together with `source:species:wikidata=plantnet.org AI`). @@ -282,16 +401,49 @@ image_key | image,mapillary,image,wikidata,wikimedia_commons,image,image | The k +### tag_apply + + Shows a big button; clicking this button will apply certain tags onto the feature. + +The first argument takes a specification of which tags to add. +These can either be a tag to add, such as `amenity=fast_food` or can use a substitution, e.g. `addr:housenumber=$number`. +This new point will then have the tags `amenity=fast_food` and `addr:housenumber` with the value that was saved in `number` in the original feature. + +If a value to substitute is undefined, empty string will be used instead. + +This supports multiple values, e.g. `ref=$source:geometry:type/$source:geometry:ref` + +Remark that the syntax is slightly different then expected; it uses '$' to note a value to copy, followed by a name (matched with `[a-zA-Z0-9_:]*`). Sadly, delimiting with `{}` as these already mark the boundaries of the special rendering... + +Note that these values can be prepare with javascript in the theme by using a [calculatedTag](calculatedTags.md#calculating-tags-with-javascript) + + +name | default | description +------ | --------- | ------------- +tags_to_apply | _undefined_ | A specification of the tags to apply. This is either hardcoded in the layer or the `$name` of a property containing the tags to apply. If redirected and the value of the linked property starts with `{`, the other property will be interpreted as a json object +message | _undefined_ | The text to show to the contributor +image | _undefined_ | An image to show to the contributor on the button +id_of_object_to_apply_this_one | _undefined_ | If specified, applies the the tags onto _another_ object. The id will be read from properties[id_of_object_to_apply_this_one] of the selected object. The tags are still calculated based on the tags of the _selected_ element +maproulette_task_id | _undefined_ | If specified, this maproulette-challenge will be closed when the tags are applied + + +#### Example usage of tag_apply + + `{tag_apply(survey_date=$_now:date, Surveyed today!)}`, `{tag_apply(addr:street=$addr:street, Apply the address, apply_icon.svg, _closest_osm_id) + + + ### import_button This button will copy the point from an external dataset into OpenStreetMap + Note that the contributor must zoom to at least zoomlevel 18 to be able to use this functionality. -It is only functional in official themes, but can be tested in unoffical themes. + It is only functional in official themes, but can be tested in unoffical themes. #### Specifying which tags to copy or add -The argument `tags` of the import button takes a `;`-seperated list of tags to add (or the name of a property which contains a JSON-list of properties). + The argument `tags` of the import button takes a `;`-seperated list of tags to add (or the name of a property which contains a JSON-list of properties). These can either be a tag to add, such as `amenity=fast_food` or can use a substitution, e.g. `addr:housenumber=$number`. This new point will then have the tags `amenity=fast_food` and `addr:housenumber` with the value that was saved in `number` in the original feature. @@ -338,26 +490,26 @@ icon | ./assets/svg/addSmall.svg | A nice icon to show in the button snap_onto_layers | _undefined_ | If a way of the given layer(s) is closeby, will snap the new point onto this way (similar as preset might snap). To show multiple layers to snap onto, use a `;`-seperated list max_snap_distance | 5 | The maximum distance that the imported point will be moved to snap onto a way in an already existing layer (in meters). This is previewed to the contributor, similar to the 'add new point'-action of MapComplete note_id | _undefined_ | If given, this key will be read. The corresponding note on OSM will be closed, stating 'imported' -location_picker | photo | Chooses the background for the precise location picker, options are 'map', 'photo' or 'osmbasedmap' or 'none' if the precise input picker should be disabled maproulette_id | _undefined_ | The property name of the maproulette_id - this is probably `mr_taskId`. If given, the maproulette challenge will be marked as fixed. Only use this if part of a maproulette-layer. #### Example usage of import_button - `{import_button(,,Import this data into OpenStreetMap,./assets/svg/addSmall.svg,,5,,photo,)}` + `{import_button(,,Import this data into OpenStreetMap,./assets/svg/addSmall.svg,,5,,)}` ### import_way_button - This button will copy the data from an external dataset into OpenStreetMap + This button will copy the data from an external dataset into OpenStreetMap, copying the geometry and adding it as a 'line' + Note that the contributor must zoom to at least zoomlevel 18 to be able to use this functionality. -It is only functional in official themes, but can be tested in unoffical themes. + It is only functional in official themes, but can be tested in unoffical themes. #### Specifying which tags to copy or add -The argument `tags` of the import button takes a `;`-seperated list of tags to add (or the name of a property which contains a JSON-list of properties). + The argument `tags` of the import button takes a `;`-seperated list of tags to add (or the name of a property which contains a JSON-list of properties). These can either be a tag to add, such as `amenity=fast_food` or can use a substitution, e.g. `addr:housenumber=$number`. This new point will then have the tags `amenity=fast_food` and `addr:housenumber` with the value that was saved in `number` in the original feature. @@ -419,12 +571,13 @@ snap_to_layer_max_distance | 0.1 | Distance to distort the geometry to snap to t This button will modify the geometry of an existing OSM way to match the specified geometry. This can conflate OSM-ways with LineStrings and Polygons (only simple polygons with one single ring). An attempt is made to move points with special values to a decent new location (e.g. entrances) + Note that the contributor must zoom to at least zoomlevel 18 to be able to use this functionality. -It is only functional in official themes, but can be tested in unoffical themes. + It is only functional in official themes, but can be tested in unoffical themes. #### Specifying which tags to copy or add -The argument `tags` of the import button takes a `;`-seperated list of tags to add (or the name of a property which contains a JSON-list of properties). + The argument `tags` of the import button takes a `;`-seperated list of tags to add (or the name of a property which contains a JSON-list of properties). These can either be a tag to add, such as `amenity=fast_food` or can use a substitution, e.g. `addr:housenumber=$number`. This new point will then have the tags `amenity=fast_food` and `addr:housenumber` with the value that was saved in `number` in the original feature. @@ -477,57 +630,6 @@ way_to_conflate | _undefined_ | The key, of which the corresponding value is the -### tag_apply - - Shows a big button; clicking this button will apply certain tags onto the feature. - -The first argument takes a specification of which tags to add. -These can either be a tag to add, such as `amenity=fast_food` or can use a substitution, e.g. `addr:housenumber=$number`. -This new point will then have the tags `amenity=fast_food` and `addr:housenumber` with the value that was saved in `number` in the original feature. - -If a value to substitute is undefined, empty string will be used instead. - -This supports multiple values, e.g. `ref=$source:geometry:type/$source:geometry:ref` - -Remark that the syntax is slightly different then expected; it uses '$' to note a value to copy, followed by a name (matched with `[a-zA-Z0-9_:]*`). Sadly, delimiting with `{}` as these already mark the boundaries of the special rendering... - -Note that these values can be prepare with javascript in the theme by using a [calculatedTag](calculatedTags.md#calculating-tags-with-javascript) - - -name | default | description ------- | --------- | ------------- -tags_to_apply | _undefined_ | A specification of the tags to apply -message | _undefined_ | The text to show to the contributor -image | _undefined_ | An image to show to the contributor on the button -id_of_object_to_apply_this_one | _undefined_ | If specified, applies the the tags onto _another_ object. The id will be read from properties[id_of_object_to_apply_this_one] of the selected object. The tags are still calculated based on the tags of the _selected_ element - - -#### Example usage of tag_apply - - `{tag_apply(survey_date=$_now:date, Surveyed today!)}`, `{tag_apply(addr:street=$addr:street, Apply the address, apply_icon.svg, _closest_osm_id) - - - -### close_note - - Button to close a note. A predifined text can be defined to close the note with. If the note is already closed, will show a small text. - -name | default | description ------- | --------- | ------------- -text | _undefined_ | Text to show on this button -icon | checkmark.svg | Icon to show -idkey | id | The property name where the ID of the note to close can be found -comment | _undefined_ | Text to add onto the note when closing -minZoom | _undefined_ | If set, only show the closenote button if zoomed in enough -zoomButton | _undefined_ | Text to show if not zoomed in enough - - -#### Example usage of close_note - - `{close_note(,checkmark.svg,id,,,)}` - - - ### nearby_images A component showing nearby images loaded from various online services such as Mapillary. In edit mode and when used on a feature, the user can select an image to add to the feature @@ -548,6 +650,36 @@ mapillary | true | If 'true', includes a link to mapillary on this location. +### wikipedia + + A box showing the corresponding wikipedia article(s) - based on the **wikidata** tag. + +name | default | description +------ | --------- | ------------- +keyToShowWikipediaFor | wikidata;wikipedia | Use the wikidata entry from this key to show the wikipedia article for. Multiple keys can be given (separated by ';'), in which case the first matching value is used + + +#### Example usage of wikipedia + + `{wikipedia()}` is a basic example, `{wikipedia(name:etymology:wikidata)}` to show the wikipedia page of whom the feature was named after. Also remember that these can be styled, e.g. `{wikipedia():max-height: 10rem}` to limit the height + + + +### wikidata_label + + Shows the label of the corresponding wikidata-item + +name | default | description +------ | --------- | ------------- +keyToShowWikidataFor | wikidata | Use the wikidata entry from this key to show the label + + +#### Example usage of wikidata_label + + `{wikidata_label()}` is a basic example, `{wikipedia(name:etymology:wikidata)}` to show the label itself + + + ### mapillary_link Adds a button to open mapillary on the specified location @@ -625,36 +757,6 @@ label | Add image | The text to show on the button -### wikipedia - - A box showing the corresponding wikipedia article - based on the wikidata tag - -name | default | description ------- | --------- | ------------- -keyToShowWikipediaFor | wikidata;wikipedia | Use the wikidata entry from this key to show the wikipedia article for. Multiple keys can be given (separated by ';'), in which case the first matching value is used - - -#### Example usage of wikipedia - - `{wikipedia()}` is a basic example, `{wikipedia(name:etymology:wikidata)}` to show the wikipedia page of whom the feature was named after. Also remember that these can be styled, e.g. `{wikipedia():max-height: 10rem}` to limit the height - - - -### wikidata_label - - Shows the label of the corresponding wikidata-item - -name | default | description ------- | --------- | ------------- -keyToShowWikidataFor | wikidata | Use the wikidata entry from this key to show the label - - -#### Example usage of wikidata_label - - `{wikidata_label()}` is a basic example, `{wikipedia(name:etymology:wikidata)}` to show the label itself - - - ### 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 @@ -787,23 +889,7 @@ Id-key | id | The property name where the ID of the note to close can be found #### Example usage of add_image_to_note - The following example sets the status to '2' (false positive) - -```json -{ - "id": "mark_duplicate", - "render": { - "special": { - "type": "maproulette_set_status", - "message": { - "en": "Mark as not found or false positive" - }, - "status": "2", - "image": "close" - } - } -} -``` + `{add_image_to_note(id)}` @@ -844,7 +930,23 @@ maproulette_id | mr_taskId | The property name containing the maproulette id #### Example usage of maproulette_set_status - `{maproulette_set_status(,confirm,,1,mr_taskId)}` + The following example sets the status to '2' (false positive) + +```json +{ + "id": "mark_duplicate", + "render": { + "special": { + "type": "maproulette_set_status", + "message": { + "en": "Mark as not found or false positive" + }, + "status": "2", + "image": "close" + } + } +} +``` @@ -876,6 +978,23 @@ button_text | _undefined_ | The text shown on the button in the UI +### link + + Construct a link. By using the 'special' visualisation notation, translation should be easier + +name | default | description +------ | --------- | ------------- +text | _undefined_ | Text to be shown +href | _undefined_ | The URL to link to +class | _undefined_ | CSS-classes to add to the element + + +#### Example usage of link + + `{link(,,)}` + + + ### multi Given an embedded tagRendering (read only) and a key, will read the keyname as a JSON-list. Every element of this list will be considered as tags and rendered with the tagRendering @@ -908,7 +1027,7 @@ tagrendering | _undefined_ | An entire tagRenderingConfig A button to run many actions for many features at once. To effectively use this button, you'll need some ingredients: - - A target layer with features for which an action is defined in a tag rendering. The following special visualisations support an autoAction: import_way_button, tag_apply + - A target layer with features for which an action is defined in a tag rendering. The following special visualisations support an autoAction: tag_apply, import_way_button, conflate_button - A host feature to place the auto-action on. This can be a big outline (such as a city). Another good option for this is the layer - [current_view](./BuiltinLayers.md#current_view) - Then, use a calculated tag on the host feature to determine the overlapping object ids diff --git a/Docs/TagInfo/mapcomplete_advertising.json b/Docs/TagInfo/mapcomplete_advertising.json index 408eb448f..7567fbaad 100644 --- a/Docs/TagInfo/mapcomplete_advertising.json +++ b/Docs/TagInfo/mapcomplete_advertising.json @@ -14,6 +14,10 @@ "key": "advertising", "description": "The MapComplete theme Open Advertising Map has a layer Advertise showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Advertise' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Advertising Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Advertise 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" diff --git a/Docs/TagInfo/mapcomplete_aed.json b/Docs/TagInfo/mapcomplete_aed.json index 13a98aa2a..99bd6beeb 100644 --- a/Docs/TagInfo/mapcomplete_aed.json +++ b/Docs/TagInfo/mapcomplete_aed.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Open AED Map has a layer Defibrillators showing features with this tag", "value": "defibrillator" }, + { + "key": "id", + "description": "Layer 'Defibrillators' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open AED Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Defibrillators 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" diff --git a/Docs/TagInfo/mapcomplete_artwork.json b/Docs/TagInfo/mapcomplete_artwork.json index e2f0fd52d..2b3483a32 100644 --- a/Docs/TagInfo/mapcomplete_artwork.json +++ b/Docs/TagInfo/mapcomplete_artwork.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Open Artwork Map has a layer Artworks showing features with this tag", "value": "artwork" }, + { + "key": "id", + "description": "Layer 'Artworks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Artworks allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" @@ -138,155 +142,6 @@ "key": "amenity", "description": "Layer 'Artworks' shows with a fixed text, namely 'This artwork does not serve as a bench' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') Picking this answer will delete the key amenity.", "value": "" - }, - { - "key": "backrest", - "description": "Layer 'Artworks' shows backrest=yes&two_sided=yes with a fixed text, namely 'This bench is two-sided and shares the backrest' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "yes" - }, - { - "key": "two_sided", - "description": "Layer 'Artworks' shows backrest=yes&two_sided=yes with a fixed text, namely 'This bench is two-sided and shares the backrest' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "yes" - }, - { - "key": "backrest", - "description": "Layer 'Artworks' shows backrest=yes with a fixed text, namely 'Does have a backrest' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "yes" - }, - { - "key": "backrest", - "description": "Layer 'Artworks' shows backrest=no with a fixed text, namely 'Does not have a backrest' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "no" - }, - { - "key": "seats", - "description": "Layer 'Artworks' shows and asks freeform values for key 'seats' (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)" - }, - { - "key": "seats:separated", - "description": "Layer 'Artworks' shows seats:separated=no with a fixed text, namely 'This bench does not have separated seats' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "no" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows and asks freeform values for key 'material' (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=wood with a fixed text, namely 'The seating is made from wood' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "wood" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=metal with a fixed text, namely 'The seating is made from metal' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "metal" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=stone with a fixed text, namely 'The seating is made from stone' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "stone" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=concrete with a fixed text, namely 'The seating is made from concrete' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "concrete" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=plastic with a fixed text, namely 'The seating is made from plastic' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "plastic" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=steel with a fixed text, namely 'The seating is made from steel' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "steel" - }, - { - "key": "direction", - "description": "Layer 'Artworks' shows and asks freeform values for key 'direction' (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows and asks freeform values for key 'colour' (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=brown with a fixed text, namely 'Colour: brown' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "brown" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=green with a fixed text, namely 'Colour: green' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "green" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=gray with a fixed text, namely 'Colour: gray' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "gray" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=white with a fixed text, namely 'Colour: white' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "white" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=red with a fixed text, namely 'Colour: red' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "red" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=black with a fixed text, namely 'Colour: black' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "black" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=blue with a fixed text, namely 'Colour: blue' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "blue" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=yellow with a fixed text, namely 'Colour: yellow' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "yellow" - }, - { - "key": "survey:date", - "description": "Layer 'Artworks' shows and asks freeform values for key 'survey:date' (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)" - }, - { - "key": "survey:date", - "description": "Layer 'Artworks' shows survey:date= with a fixed text, namely 'Surveyed today!' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') Picking this answer will delete the key survey:date. (This is only shown if amenity=bench)", - "value": "" - }, - { - "key": "inscription", - "description": "Layer 'Artworks' shows and asks freeform values for key 'inscription' (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)" - }, - { - "key": "not:inscription", - "description": "Layer 'Artworks' shows not:inscription=yes with a fixed text, namely 'This bench does not have an inscription' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "yes" - }, - { - "key": "inscription", - "description": "Layer 'Artworks' shows with a fixed text, namely 'This bench does (probably) not have an inscription' (in the MapComplete.osm.be theme 'Open Artwork Map') Picking this answer will delete the key inscription. (This is only shown if amenity=bench)", - "value": "" - }, - { - "key": "historic", - "description": "Layer 'Artworks' shows historic=memorial with a fixed text, namely 'This bench is a memorial for someone or something' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "memorial" - }, - { - "key": "historic", - "description": "Layer 'Artworks' shows not:historic=memorial with a fixed text, namely 'This bench is a not a memorial for someone or something' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') Picking this answer will delete the key historic. (This is only shown if amenity=bench)", - "value": "" - }, - { - "key": "not:historic", - "description": "Layer 'Artworks' shows not:historic=memorial with a fixed text, namely 'This bench is a not a memorial for someone or something' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Artwork Map') (This is only shown if amenity=bench)", - "value": "memorial" } ] } \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_atm.json b/Docs/TagInfo/mapcomplete_atm.json index 53a4915ac..a52912aba 100644 --- a/Docs/TagInfo/mapcomplete_atm.json +++ b/Docs/TagInfo/mapcomplete_atm.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme ATM Machines has a layer ATMs showing features with this tag", "value": "atm" }, + { + "key": "id", + "description": "Layer 'ATMs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'ATM Machines') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'ATMs 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" @@ -123,6 +127,10 @@ "description": "The MapComplete theme ATM Machines has a layer Banks showing features with this tag", "value": "bank" }, + { + "key": "id", + "description": "Layer 'Banks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'ATM Machines') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "atm", "description": "Layer 'Banks' shows atm=yes with a fixed text, namely 'This bank has an ATM' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'ATM Machines')", diff --git a/Docs/TagInfo/mapcomplete_benches.json b/Docs/TagInfo/mapcomplete_benches.json index 7fcf858cd..e977d3fce 100644 --- a/Docs/TagInfo/mapcomplete_benches.json +++ b/Docs/TagInfo/mapcomplete_benches.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Benches has a layer Picnic tables showing features with this tag", "value": "picnic_table" }, + { + "key": "id", + "description": "Layer 'Picnic tables' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Benches') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Picnic tables 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" @@ -84,6 +88,10 @@ "description": "The MapComplete theme Benches has a layer Benches showing features with this tag", "value": "bench" }, + { + "key": "id", + "description": "Layer 'Benches' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Benches') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Benches 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" @@ -259,91 +267,6 @@ "description": "Layer 'Benches' shows not:historic=memorial with a fixed text, namely 'This bench is a not a memorial for someone or something' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if historic=memorial|inscription~.+|memorial=bench|tourism=artwork)", "value": "memorial" }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows and asks freeform values for key 'artwork_type' (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=architecture with a fixed text, namely 'Architecture' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "architecture" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=mural with a fixed text, namely 'Mural' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "mural" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=painting with a fixed text, namely 'Painting' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "painting" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=sculpture with a fixed text, namely 'Sculpture' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "sculpture" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=statue with a fixed text, namely 'Statue' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "statue" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=bust with a fixed text, namely 'Bust' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "bust" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=stone with a fixed text, namely 'Stone' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "stone" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=installation with a fixed text, namely 'Installation' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "installation" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=graffiti with a fixed text, namely 'Graffiti' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "graffiti" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=relief with a fixed text, namely 'Relief' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "relief" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=azulejo with a fixed text, namely 'Azulejo (Spanish decorative tilework)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "azulejo" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=tilework with a fixed text, namely 'Tilework' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "tilework" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=woodcarving with a fixed text, namely 'Woodcarving' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)", - "value": "woodcarving" - }, - { - "key": "artist:wikidata", - "description": "Layer 'Benches' shows and asks freeform values for key 'artist:wikidata' (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)" - }, - { - "key": "artist_name", - "description": "Layer 'Benches' shows and asks freeform values for key 'artist_name' (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)" - }, - { - "key": "website", - "description": "Layer 'Benches' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)" - }, - { - "key": "subject:wikidata", - "description": "Layer 'Benches' shows and asks freeform values for key 'subject:wikidata' (in the MapComplete.osm.be theme 'Benches') (This is only shown if tourism=artwork)" - }, { "key": "highway", "description": "The MapComplete theme Benches has a layer Benches at public transport stops showing features with this tag", @@ -359,6 +282,10 @@ "description": "The MapComplete theme Benches has a layer Benches at public transport stops showing features with this tag", "value": "stand_up_bench" }, + { + "key": "id", + "description": "Layer 'Benches at public transport stops' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Benches') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Benches at public transport stops 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" diff --git a/Docs/TagInfo/mapcomplete_bicycle_rental.json b/Docs/TagInfo/mapcomplete_bicycle_rental.json index 5d60bff58..50d043696 100644 --- a/Docs/TagInfo/mapcomplete_bicycle_rental.json +++ b/Docs/TagInfo/mapcomplete_bicycle_rental.json @@ -28,6 +28,10 @@ "key": "rental", "description": "The MapComplete theme Bicycle rental has a layer Bicycle rental showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Bicycle rental' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bicycle rental') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle rental 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" diff --git a/Docs/TagInfo/mapcomplete_bicyclelib.json b/Docs/TagInfo/mapcomplete_bicyclelib.json index b5f2c837b..a82636b0f 100644 --- a/Docs/TagInfo/mapcomplete_bicyclelib.json +++ b/Docs/TagInfo/mapcomplete_bicyclelib.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Bicycle libraries has a layer Bicycle library showing features with this tag", "value": "bicycle_library" }, + { + "key": "id", + "description": "Layer 'Bicycle library' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bicycle libraries') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle library 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" diff --git a/Docs/TagInfo/mapcomplete_binoculars.json b/Docs/TagInfo/mapcomplete_binoculars.json index c047427bf..889ab25d8 100644 --- a/Docs/TagInfo/mapcomplete_binoculars.json +++ b/Docs/TagInfo/mapcomplete_binoculars.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Binoculars has a layer Binoculars showing features with this tag", "value": "binoculars" }, + { + "key": "id", + "description": "Layer 'Binoculars' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Binoculars') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Binoculars 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" diff --git a/Docs/TagInfo/mapcomplete_blind_osm.json b/Docs/TagInfo/mapcomplete_blind_osm.json index 8c2f5e3dd..cddf6e6d5 100644 --- a/Docs/TagInfo/mapcomplete_blind_osm.json +++ b/Docs/TagInfo/mapcomplete_blind_osm.json @@ -105,6 +105,10 @@ "description": "The MapComplete theme OSM for the blind has a layer Cycleways and roads showing features with this tag", "value": "designated" }, + { + "key": "id", + "description": "Layer 'Cycleways and roads' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OSM for the blind') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "cycleway", "description": "Layer 'Cycleways and roads' shows cycleway=shared_lane with a fixed text, namely 'There is a shared lane' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OSM for the blind') (This is only shown if highway!=cycleway&highway!=path&highway!=footway)", @@ -573,6 +577,10 @@ "description": "The MapComplete theme OSM for the blind has a layer Crossings showing features with this tag", "value": "crossing" }, + { + "key": "id", + "description": "Layer 'Crossings' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OSM for the blind') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Crossings 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" @@ -739,6 +747,10 @@ "description": "The MapComplete theme OSM for the blind has a layer Kerbs showing features with this tag", "value": "kerb" }, + { + "key": "id", + "description": "Layer 'Kerbs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OSM for the blind') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Kerbs 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" @@ -809,6 +821,10 @@ "description": "The MapComplete theme OSM for the blind has a layer Transit Stops showing features with this tag", "value": "bus_stop" }, + { + "key": "id", + "description": "Layer 'Transit Stops' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OSM for the blind') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Transit Stops' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'OSM for the blind')" @@ -959,6 +975,10 @@ "description": "The MapComplete theme OSM for the blind has a layer Elevator showing features with this tag", "value": "elevator" }, + { + "key": "id", + "description": "Layer 'Elevator' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OSM for the blind') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Elevator 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" @@ -1051,6 +1071,10 @@ "description": "The MapComplete theme OSM for the blind has a layer Stairs showing features with this tag", "value": "steps" }, + { + "key": "id", + "description": "Layer 'Stairs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OSM for the blind') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Stairs 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" diff --git a/Docs/TagInfo/mapcomplete_bookcases.json b/Docs/TagInfo/mapcomplete_bookcases.json index 1f949274c..5d84974c5 100644 --- a/Docs/TagInfo/mapcomplete_bookcases.json +++ b/Docs/TagInfo/mapcomplete_bookcases.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Open Bookcase Map has a layer Bookcases showing features with this tag", "value": "public_bookcase" }, + { + "key": "id", + "description": "Layer 'Bookcases' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Bookcase Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bookcases 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" diff --git a/Docs/TagInfo/mapcomplete_cafes_and_pubs.json b/Docs/TagInfo/mapcomplete_cafes_and_pubs.json index 3e2d14548..6e039a5e8 100644 --- a/Docs/TagInfo/mapcomplete_cafes_and_pubs.json +++ b/Docs/TagInfo/mapcomplete_cafes_and_pubs.json @@ -35,6 +35,10 @@ "description": "The MapComplete theme Cafés and pubs has a layer Cafés and pubs showing features with this tag", "value": "nightclub" }, + { + "key": "id", + "description": "Layer 'Cafés and pubs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cafés and pubs') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Cafés and pubs 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" diff --git a/Docs/TagInfo/mapcomplete_campersite.json b/Docs/TagInfo/mapcomplete_campersite.json index a0bc07a19..4117d21d9 100644 --- a/Docs/TagInfo/mapcomplete_campersite.json +++ b/Docs/TagInfo/mapcomplete_campersite.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Campersites has a layer Camper sites showing features with this tag", "value": "caravan_site" }, + { + "key": "id", + "description": "Layer 'Camper sites' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Campersites') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Camper sites 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" @@ -150,6 +154,10 @@ "description": "The MapComplete theme Campersites has a layer Sanitary dump stations showing features with this tag", "value": "sanitary_dump_station" }, + { + "key": "id", + "description": "Layer 'Sanitary dump stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Campersites') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Sanitary dump stations 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" diff --git a/Docs/TagInfo/mapcomplete_charging_stations.json b/Docs/TagInfo/mapcomplete_charging_stations.json index 55e853bfc..b7ea6f926 100644 --- a/Docs/TagInfo/mapcomplete_charging_stations.json +++ b/Docs/TagInfo/mapcomplete_charging_stations.json @@ -30,6 +30,10 @@ "description": "The MapComplete theme Charging stations has a layer Charging stations showing features with this tag", "value": "charging_station" }, + { + "key": "id", + "description": "Layer 'Charging stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Charging stations') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Charging stations 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" diff --git a/Docs/TagInfo/mapcomplete_climbing.json b/Docs/TagInfo/mapcomplete_climbing.json index 027815bec..4807e3857 100644 --- a/Docs/TagInfo/mapcomplete_climbing.json +++ b/Docs/TagInfo/mapcomplete_climbing.json @@ -28,6 +28,10 @@ "key": "club", "description": "The MapComplete theme Open Climbing Map has a layer Climbing club showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Climbing club' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Climbing club' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Open Climbing Map')" @@ -99,6 +103,10 @@ "description": "The MapComplete theme Open Climbing Map has a layer Climbing gyms showing features with this tag", "value": "sports_centre" }, + { + "key": "id", + "description": "Layer 'Climbing gyms' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Climbing gyms 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" @@ -144,23 +152,19 @@ "description": "Layer 'Climbing gyms' shows contact:email~.+ with a fixed text, namely '{contact:email}' (in the MapComplete.osm.be theme 'Open Climbing Map')" }, { - "key": "charge", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'charge' (in the MapComplete.osm.be theme 'Open Climbing Map')" - }, - { - "key": "fee", - "description": "Layer 'Climbing gyms' shows fee=no with a fixed text, namely 'Climbing here is free of charge' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "no" - }, - { - "key": "fee", - "description": "Layer 'Climbing gyms' shows fee=yes with a fixed text, namely 'Paying a fee is required to climb here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", + "key": "payment:cash", + "description": "Layer 'Climbing gyms' shows payment:cash=yes with a fixed text, namely 'Cash is accepted here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", "value": "yes" }, { - "key": "charge", - "description": "Layer 'Climbing gyms' shows fee=yes with a fixed text, namely 'Paying a fee is required to climb here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map') Picking this answer will delete the key charge.", - "value": "" + "key": "payment:cards", + "description": "Layer 'Climbing gyms' shows payment:cards=yes with a fixed text, namely 'Payment cards are accepted here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", + "value": "yes" + }, + { + "key": "payment:qr_code", + "description": "Layer 'Climbing gyms' 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.osm.be theme 'Open Climbing Map')", + "value": "yes" }, { "key": "opening_hours", @@ -187,68 +191,15 @@ "value": "no" }, { - "key": "climbing:toprope", - "description": "Layer 'Climbing gyms' shows climbing:toprope=yes with a fixed text, namely 'Toprope climbing is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", + "key": "service:rental:climbing_rope", + "description": "Layer 'Climbing gyms' shows service:rental:climbing_rope=yes with a fixed text, namely 'A climbing rope can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", "value": "yes" }, { - "key": "climbing:toprope", - "description": "Layer 'Climbing gyms' shows climbing:toprope=no with a fixed text, namely 'Toprope climbing is not possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", + "key": "service:rental:climbing_rope", + "description": "Layer 'Climbing gyms' shows service:rental:climbing_rope=no with a fixed text, namely 'A climbing rope can not be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", "value": "no" }, - { - "key": "climbing:toprope", - "description": "Layer 'Climbing gyms' shows climbing:toprope~.+ with a fixed text, namely 'There are {climbing:toprope} toprope routes' (in the MapComplete.osm.be theme 'Open Climbing Map')" - }, - { - "key": "climbing:length", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'climbing:length' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if climbing:toprope!=no)" - }, - { - "key": "climbing:grade:french:min", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'climbing:grade:french:min' (in the MapComplete.osm.be theme 'Open Climbing Map')" - }, - { - "key": "climbing:grade:french:max", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'climbing:grade:french:max' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if climbing!~^(route)$&climbing:sport=yes|sport=climbing)" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing gyms' shows climbing:boulder=yes with a fixed text, namely 'Bouldering is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "yes" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing gyms' shows climbing:boulder=no with a fixed text, namely 'Bouldering is not possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "no" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing gyms' shows climbing:boulder=limited with a fixed text, namely 'Bouldering is possible, allthough there are only a few routes' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "limited" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing gyms' shows climbing:boulder~.+ with a fixed text, namely 'There are {climbing:boulder} boulder routes' (in the MapComplete.osm.be theme 'Open Climbing Map')" - }, - { - "key": "climbing:sport", - "description": "Layer 'Climbing gyms' shows climbing:sport=yes with a fixed text, namely 'Sport climbing is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "yes" - }, - { - "key": "climbing:sport", - "description": "Layer 'Climbing gyms' shows climbing:sport=no with a fixed text, namely 'Sport climbing is not possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "no" - }, - { - "key": "climbing:sport", - "description": "Layer 'Climbing gyms' shows climbing:sport~.+ with a fixed text, namely 'There are {climbing:sport} sport climbing routes' (in the MapComplete.osm.be theme 'Open Climbing Map')" - }, - { - "key": "climbing:bolts:max", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'climbing:bolts:max' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if climbing:sport=yes)" - }, { "key": "climbing:speed", "description": "Layer 'Climbing gyms' shows climbing:speed=yes with a fixed text, namely 'There is a speed climbing wall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", @@ -263,6 +214,55 @@ "key": "climbing:speed", "description": "Layer 'Climbing gyms' shows climbing:speed~.+ with a fixed text, namely 'There are {climbing:speed} speed climbing walls' (in the MapComplete.osm.be theme 'Open Climbing Map')" }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=wlan with a fixed text, namely 'This place offers wireless internet access' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", + "value": "wlan" + }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=no with a fixed text, namely 'This place does not offer internet access' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", + "value": "no" + }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=yes with a fixed text, namely 'This place offers internet access' (in the MapComplete.osm.be theme 'Open Climbing Map')", + "value": "yes" + }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=terminal with a fixed text, namely 'This place offers internet access via a terminal or computer' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", + "value": "terminal" + }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=wired with a fixed text, namely 'This place offers wired internet access' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", + "value": "wired" + }, + { + "key": "internet_access:fee", + "description": "Layer 'Climbing gyms' shows internet_access:fee=yes with a fixed text, namely 'There is a fee for the internet access at this place' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if internet_access!=no&internet_access~.+)", + "value": "yes" + }, + { + "key": "internet_access:fee", + "description": "Layer 'Climbing gyms' shows internet_access:fee=no with a fixed text, namely 'Internet access is free at this place' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if internet_access!=no&internet_access~.+)", + "value": "no" + }, + { + "key": "internet_access:fee", + "description": "Layer 'Climbing gyms' shows internet_access:fee=customers with a fixed text, namely 'Internet access is free at this place, for customers only' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if internet_access!=no&internet_access~.+)", + "value": "customers" + }, + { + "key": "internet_access:ssid", + "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'internet_access:ssid' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if internet_access=wlan)" + }, + { + "key": "internet_access:ssid", + "description": "Layer 'Climbing gyms' shows internet_access:ssid=Telekom with a fixed text, namely 'Telekom' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if internet_access=wlan)", + "value": "Telekom" + }, { "key": "access", "description": "Layer 'Climbing gyms' shows access=yes with a fixed text, namely 'Publicly accessible to anyone' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if access~.+|)", @@ -297,6 +297,10 @@ "description": "The MapComplete theme Open Climbing Map has a layer Climbing routes showing features with this tag", "value": "route" }, + { + "key": "id", + "description": "Layer 'Climbing routes' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Climbing routes 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" @@ -382,6 +386,10 @@ "description": "The MapComplete theme Open Climbing Map has a layer Climbing opportunities showing features with this tag", "value": "climbing" }, + { + "key": "id", + "description": "Layer 'Climbing opportunities' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Climbing opportunities 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" @@ -436,48 +444,6 @@ "description": "Layer 'Climbing opportunities' shows rock=limestone with a fixed text, namely 'Limestone' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if climbing=crag|natural=cliff|natural=bare_rock)", "value": "limestone" }, - { - "key": "url", - "description": "Layer 'Climbing opportunities' shows and asks freeform values for key 'url' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if leisure!~^(sports_centre)$&sport=climbing)" - }, - { - "key": "charge", - "description": "Layer 'Climbing opportunities' shows and asks freeform values for key 'charge' (in the MapComplete.osm.be theme 'Open Climbing Map')" - }, - { - "key": "fee", - "description": "Layer 'Climbing opportunities' shows fee=no with a fixed text, namely 'Climbing here is free of charge' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "no" - }, - { - "key": "fee", - "description": "Layer 'Climbing opportunities' shows fee=yes with a fixed text, namely 'Paying a fee is required to climb here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "yes" - }, - { - "key": "charge", - "description": "Layer 'Climbing opportunities' shows fee=yes with a fixed text, namely 'Paying a fee is required to climb here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map') Picking this answer will delete the key charge.", - "value": "" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing opportunities' shows climbing:boulder=yes with a fixed text, namely 'Bouldering is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "yes" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing opportunities' shows climbing:boulder=no with a fixed text, namely 'Bouldering is not possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "no" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing opportunities' shows climbing:boulder=limited with a fixed text, namely 'Bouldering is possible, allthough there are only a few routes' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", - "value": "limited" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing opportunities' shows climbing:boulder~.+ with a fixed text, namely 'There are {climbing:boulder} boulder routes' (in the MapComplete.osm.be theme 'Open Climbing Map')" - }, { "key": "access", "description": "Layer 'Climbing opportunities' shows access=yes with a fixed text, namely 'Publicly accessible to anyone' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if access~.+|)", @@ -542,6 +508,10 @@ "description": "The MapComplete theme Open Climbing Map has a layer Climbing opportunities? showing features with this tag", "value": "" }, + { + "key": "id", + "description": "Layer 'Climbing opportunities?' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Climbing Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "sport", "description": "Layer 'Climbing opportunities?' shows sport=climbing with a fixed text, namely 'Climbing is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Climbing Map')", diff --git a/Docs/TagInfo/mapcomplete_clock.json b/Docs/TagInfo/mapcomplete_clock.json index ea84da5d8..ed03605f9 100644 --- a/Docs/TagInfo/mapcomplete_clock.json +++ b/Docs/TagInfo/mapcomplete_clock.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Clocks has a layer Clocks showing features with this tag", "value": "clock" }, + { + "key": "id", + "description": "Layer 'Clocks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Clocks') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Clocks 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" diff --git a/Docs/TagInfo/mapcomplete_cycle_infra.json b/Docs/TagInfo/mapcomplete_cycle_infra.json index 29a12cf98..787785489 100644 --- a/Docs/TagInfo/mapcomplete_cycle_infra.json +++ b/Docs/TagInfo/mapcomplete_cycle_infra.json @@ -105,6 +105,10 @@ "description": "The MapComplete theme Bicycle infrastructure has a layer Cycleways and roads showing features with this tag", "value": "designated" }, + { + "key": "id", + "description": "Layer 'Cycleways and roads' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bicycle infrastructure') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "cycleway", "description": "Layer 'Cycleways and roads' shows cycleway=shared_lane with a fixed text, namely 'There is a shared lane' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Bicycle infrastructure') (This is only shown if highway!=cycleway&highway!=path&highway!=footway)", @@ -573,6 +577,10 @@ "description": "The MapComplete theme Bicycle infrastructure has a layer Barriers showing features with this tag", "value": "cycle_barrier" }, + { + "key": "id", + "description": "Layer 'Barriers' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bicycle infrastructure') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Barriers 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" @@ -680,6 +688,10 @@ "description": "The MapComplete theme Bicycle infrastructure has a layer Crossings showing features with this tag", "value": "crossing" }, + { + "key": "id", + "description": "Layer 'Crossings' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bicycle infrastructure') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Crossings 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" diff --git a/Docs/TagInfo/mapcomplete_cyclestreets.json b/Docs/TagInfo/mapcomplete_cyclestreets.json index 05bb9704e..0cb744f0b 100644 --- a/Docs/TagInfo/mapcomplete_cyclestreets.json +++ b/Docs/TagInfo/mapcomplete_cyclestreets.json @@ -20,22 +20,6 @@ "description": "The MapComplete theme Cyclestreets has a layer Cyclestreets showing features with this tag", "value": "yes" }, - { - "key": "image", - "description": "The layer 'Cyclestreets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "mapillary", - "description": "The layer 'Cyclestreets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikidata", - "description": "The layer 'Cyclestreets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikipedia", - "description": "The layer 'Cyclestreets 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": "cyclestreet", "description": "Layer 'Cyclestreets' shows cyclestreet=yes&maxspeed=30&overtaking:motor_vehicle=no with a fixed text, namely 'This street is a cyclestreet (and has a speed limit of 30 km/h)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclestreets')", @@ -175,6 +159,26 @@ "key": "cyclestreet:start_date", "description": "Layer 'Cyclestreets' shows and asks freeform values for key 'cyclestreet:start_date' (in the MapComplete.osm.be theme 'Cyclestreets') (This is only shown if proposed:cyclestreet=yes)" }, + { + "key": "id", + "description": "Layer 'Cyclestreets' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclestreets') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, + { + "key": "image", + "description": "The layer 'Cyclestreets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" + }, + { + "key": "mapillary", + "description": "The layer 'Cyclestreets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" + }, + { + "key": "wikidata", + "description": "The layer 'Cyclestreets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" + }, + { + "key": "wikipedia", + "description": "The layer 'Cyclestreets 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": "proposed:cyclestreet", "description": "The MapComplete theme Cyclestreets has a layer Future cyclestreet showing features with this tag", @@ -185,22 +189,6 @@ "description": "The MapComplete theme Cyclestreets has a layer Future cyclestreet showing features with this tag", "value": "yes" }, - { - "key": "image", - "description": "The layer 'Future cyclestreet allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "mapillary", - "description": "The layer 'Future cyclestreet allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikidata", - "description": "The layer 'Future cyclestreet allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikipedia", - "description": "The layer 'Future cyclestreet 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": "cyclestreet", "description": "Layer 'Future cyclestreet' shows cyclestreet=yes&maxspeed=30&overtaking:motor_vehicle=no with a fixed text, namely 'This street is a cyclestreet (and has a speed limit of 30 km/h)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclestreets')", @@ -340,6 +328,26 @@ "key": "cyclestreet:start_date", "description": "Layer 'Future cyclestreet' shows and asks freeform values for key 'cyclestreet:start_date' (in the MapComplete.osm.be theme 'Cyclestreets') (This is only shown if proposed:cyclestreet=yes)" }, + { + "key": "id", + "description": "Layer 'Future cyclestreet' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclestreets') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, + { + "key": "image", + "description": "The layer 'Future cyclestreet allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" + }, + { + "key": "mapillary", + "description": "The layer 'Future cyclestreet allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" + }, + { + "key": "wikidata", + "description": "The layer 'Future cyclestreet allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" + }, + { + "key": "wikipedia", + "description": "The layer 'Future cyclestreet 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": "highway", "description": "The MapComplete theme Cyclestreets has a layer All streets showing features with this tag", @@ -355,22 +363,6 @@ "description": "The MapComplete theme Cyclestreets has a layer All streets showing features with this tag", "value": "unclassified" }, - { - "key": "image", - "description": "The layer 'All streets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "mapillary", - "description": "The layer 'All streets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikidata", - "description": "The layer 'All streets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikipedia", - "description": "The layer 'All streets 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": "cyclestreet", "description": "Layer 'All streets' shows cyclestreet=yes&maxspeed=30&overtaking:motor_vehicle=no with a fixed text, namely 'This street is a cyclestreet (and has a speed limit of 30 km/h)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclestreets')", @@ -509,6 +501,26 @@ { "key": "cyclestreet:start_date", "description": "Layer 'All streets' shows and asks freeform values for key 'cyclestreet:start_date' (in the MapComplete.osm.be theme 'Cyclestreets') (This is only shown if proposed:cyclestreet=yes)" + }, + { + "key": "id", + "description": "Layer 'All streets' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclestreets') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, + { + "key": "image", + "description": "The layer 'All streets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" + }, + { + "key": "mapillary", + "description": "The layer 'All streets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" + }, + { + "key": "wikidata", + "description": "The layer 'All streets allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" + }, + { + "key": "wikipedia", + "description": "The layer 'All streets 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" } ] } \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_cyclofix.json b/Docs/TagInfo/mapcomplete_cyclofix.json index 3f838fa58..cf96ef07a 100644 --- a/Docs/TagInfo/mapcomplete_cyclofix.json +++ b/Docs/TagInfo/mapcomplete_cyclofix.json @@ -50,6 +50,10 @@ "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Bike cafe showing features with this tag", "value": "bicycle" }, + { + "key": "id", + "description": "Layer 'Bike cafe' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike cafe 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" @@ -153,6 +157,10 @@ "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Bike repair/shop showing features with this tag", "value": "" }, + { + "key": "id", + "description": "Layer 'Bike repair/shop' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike repair/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" @@ -250,78 +258,6 @@ "description": "Layer 'Bike repair/shop' shows service:bicycle:rental=no with a fixed text, namely 'This shop doesn't rent out bikes' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists')", "value": "no" }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'rental' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if service:bicycle:rental=yes)" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=city_bike with a fixed text, namely 'Normal city bikes can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if service:bicycle:rental=yes)", - "value": "city_bike" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=ebike with a fixed text, namely 'Electrical bikes can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if service:bicycle:rental=yes)", - "value": "ebike" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=bmx with a fixed text, namely 'BMX bikes can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if service:bicycle:rental=yes)", - "value": "bmx" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=mtb with a fixed text, namely 'Mountainbikes can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if service:bicycle:rental=yes)", - "value": "mtb" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=kid_bike with a fixed text, namely 'Bikes for children can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if service:bicycle:rental=yes)", - "value": "kid_bike" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=tandem with a fixed text, namely 'Tandem bicycles can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if service:bicycle:rental=yes)", - "value": "tandem" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=racebike with a fixed text, namely 'Race bicycles can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if service:bicycle:rental=yes)", - "value": "racebike" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=bike_helmet with a fixed text, namely 'Bike helmets can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if service:bicycle:rental=yes)", - "value": "bike_helmet" - }, - { - "key": "capacity:city_bike", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:city_bike' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if rental~^(.*city_bike.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:ebike", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:ebike' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if rental~^(.*ebike.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:kid_bike", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:kid_bike' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if rental~^(.*kid_bike.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:bmx", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:bmx' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if rental~^(.*bmx.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:mtb", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:mtb' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if rental~^(.*mtb.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:bicycle_pannier", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:bicycle_pannier' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if rental~^(.*bicycle_pannier.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:tandem_bicycle", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:tandem_bicycle' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if rental~^(.*tandem_bicycle.*)$&service:bicycle:rental=yes)" - }, { "key": "service:bicycle:second_hand", "description": "Layer 'Bike repair/shop' shows service:bicycle:second_hand=yes with a fixed text, namely 'This shop sells second-hand bikes' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists')", @@ -382,25 +318,6 @@ "description": "Layer 'Bike repair/shop' shows service:bicycle:cleaning=no with a fixed text, namely 'This shop doesn't offer bicycle cleaning' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists')", "value": "no" }, - { - "key": "service:bicycle:cleaning:charge", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'service:bicycle:cleaning:charge' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if amenity!=bike_wash&amenity!=bicycle_wash)" - }, - { - "key": "service:bicycle:cleaning:fee", - "description": "Layer 'Bike repair/shop' shows service:bicycle:cleaning:fee=no with a fixed text, namely 'The cleaning service is free to use' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if amenity!=bike_wash&amenity!=bicycle_wash)", - "value": "no" - }, - { - "key": "service:bicycle:cleaning:fee", - "description": "Layer 'Bike repair/shop' shows service:bicycle:cleaning:fee=yes with a fixed text, namely 'Free to use' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if amenity!=bike_wash&amenity!=bicycle_wash)", - "value": "yes" - }, - { - "key": "service:bicycle:cleaning:charge", - "description": "Layer 'Bike repair/shop' shows service:bicycle:cleaning:fee=yes with a fixed text, namely 'Free to use' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') Picking this answer will delete the key service:bicycle:cleaning:charge. (This is only shown if amenity!=bike_wash&amenity!=bicycle_wash)", - "value": "" - }, { "key": "description", "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'description' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists')" @@ -423,6 +340,10 @@ "key": "rental", "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Bicycle rental showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Bicycle rental' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle rental 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" @@ -624,6 +545,10 @@ "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Bicycle library showing features with this tag", "value": "bicycle_library" }, + { + "key": "id", + "description": "Layer 'Bicycle library' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle library 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" @@ -720,6 +645,10 @@ "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Bicycle pump and repair showing features with this tag", "value": "bicycle_repair_station" }, + { + "key": "id", + "description": "Layer 'Bicycle pump and repair' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle pump and repair 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" @@ -924,6 +853,10 @@ "key": "vending", "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Bicycle tube vending machine showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Bicycle tube vending machine' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle tube vending machine 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" @@ -1041,6 +974,10 @@ "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Drinking water showing features with this tag", "value": "yes" }, + { + "key": "id", + "description": "Layer 'Drinking water' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Drinking water 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" @@ -1131,6 +1068,10 @@ "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Bike-related object showing features with this tag", "value": "cycling" }, + { + "key": "id", + "description": "Layer 'Bike-related object' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike-related object 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" @@ -1199,6 +1140,10 @@ "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Bike cleaning service showing features with this tag", "value": "bike_wash" }, + { + "key": "id", + "description": "Layer 'Bike cleaning service' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike cleaning service 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" @@ -1253,6 +1198,10 @@ "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Bike parking showing features with this tag", "value": "bicycle_parking" }, + { + "key": "id", + "description": "Layer 'Bike parking' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike parking 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" @@ -1410,6 +1359,10 @@ "description": "The MapComplete theme Cyclofix - an open map for cyclists has a layer Charging stations showing features with this tag", "value": "yes" }, + { + "key": "id", + "description": "Layer 'Charging stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Cyclofix - an open map for cyclists') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Charging stations 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" diff --git a/Docs/TagInfo/mapcomplete_drinking_water.json b/Docs/TagInfo/mapcomplete_drinking_water.json index 4f79f86c3..501bcee64 100644 --- a/Docs/TagInfo/mapcomplete_drinking_water.json +++ b/Docs/TagInfo/mapcomplete_drinking_water.json @@ -20,6 +20,10 @@ "description": "The MapComplete theme Drinking Water has a layer Drinking water showing features with this tag", "value": "yes" }, + { + "key": "id", + "description": "Layer 'Drinking water' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Drinking Water') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Drinking water 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" diff --git a/Docs/TagInfo/mapcomplete_education.json b/Docs/TagInfo/mapcomplete_education.json index 510ba3474..861b383c7 100644 --- a/Docs/TagInfo/mapcomplete_education.json +++ b/Docs/TagInfo/mapcomplete_education.json @@ -33,6 +33,10 @@ "key": "isced:2011:level", "description": "The MapComplete theme Education has a layer Colleges and universities showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Colleges and universities' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Education') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "amenity", "description": "Layer 'Colleges and universities' shows amenity=college with a fixed text, namely 'This is an institution of post-secondary, non-tertiary education. One has to have completed secondary education to enroll here, but no bachelor (or higher) degrees are awarded here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Education')", @@ -58,30 +62,6 @@ "description": "Layer 'Colleges and universities' shows isced:2011:level=doctorate with a fixed text, namely 'Doctorate degrees are awarded here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Education') (This is only shown if amenity=university)", "value": "doctorate" }, - { - "key": "capacity", - "description": "Layer 'Colleges and universities' shows and asks freeform values for key 'capacity' (in the MapComplete.osm.be theme 'Education')" - }, - { - "key": "school:gender", - "description": "Layer 'Colleges and universities' shows school:gender=mixed with a fixed text, namely 'Both boys and girls can enroll here and have classes together' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Education')", - "value": "mixed" - }, - { - "key": "school:gender", - "description": "Layer 'Colleges and universities' shows school:gender=separated with a fixed text, namely 'Both boys and girls can enroll here but they are separated (e.g. they have lessons in different classrooms or at different times)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Education')", - "value": "separated" - }, - { - "key": "school:gender", - "description": "Layer 'Colleges and universities' shows school:gender=male with a fixed text, namely 'This is a boys only-school' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Education')", - "value": "male" - }, - { - "key": "school:gender", - "description": "Layer 'Colleges and universities' shows school:gender=female with a fixed text, namely 'This is a girls-only school' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Education')", - "value": "female" - }, { "key": "website", "description": "Layer 'Colleges and universities' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Education')" @@ -111,6 +91,10 @@ "description": "The MapComplete theme Education has a layer Primary and secondary schools showing features with this tag", "value": "school" }, + { + "key": "id", + "description": "Layer 'Primary and secondary schools' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Education') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Primary and secondary schools' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Education')" @@ -262,6 +246,10 @@ "description": "The MapComplete theme Education has a layer Kindergartens and childcare showing features with this tag", "value": "early_childhood" }, + { + "key": "id", + "description": "Layer 'Kindergartens and childcare' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Education') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "amenity", "description": "Layer 'Kindergartens and childcare' shows amenity=kindergarten with a fixed text, namely 'This is a kindergarten (also known as preschool) where small kids receive early education.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Education')", diff --git a/Docs/TagInfo/mapcomplete_entrances.json b/Docs/TagInfo/mapcomplete_entrances.json deleted file mode 100644 index 87bfd16ab..000000000 --- a/Docs/TagInfo/mapcomplete_entrances.json +++ /dev/null @@ -1,265 +0,0 @@ -{ - "data_format": 1, - "project": { - "name": "MapComplete Entrances", - "description": "Survey entrances to help wheelchair routing", - "project_url": "https://mapcomplete.osm.be/entrances", - "doc_url": "https://github.com/pietervdvn/MapComplete/tree/master/assets/themes/", - "icon_url": "https://mapcomplete.osm.be/assets/layers/entrance/door.svg", - "contact_name": "Pieter Vander Vennet, MapComplete", - "contact_email": "pietervdvn@posteo.net" - }, - "tags": [ - { - "key": "highway", - "description": "The MapComplete theme Entrances has a layer Pedestrian paths showing features with this tag", - "value": "footway" - }, - { - "key": "highway", - "description": "The MapComplete theme Entrances has a layer Pedestrian paths showing features with this tag", - "value": "path" - }, - { - "key": "highway", - "description": "The MapComplete theme Entrances has a layer Pedestrian paths showing features with this tag", - "value": "corridor" - }, - { - "key": "highway", - "description": "The MapComplete theme Entrances has a layer Pedestrian paths showing features with this tag", - "value": "steps" - }, - { - "key": "entrance", - "description": "The MapComplete theme Entrances has a layer Entrance showing features with this tag" - }, - { - "key": "indoor", - "description": "The MapComplete theme Entrances has a layer Entrance showing features with this tag", - "value": "door" - }, - { - "key": "door", - "description": "The MapComplete theme Entrances has a layer Entrance showing features with this tag" - }, - { - "key": "image", - "description": "The layer 'Entrance allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "mapillary", - "description": "The layer 'Entrance allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikidata", - "description": "The layer 'Entrance allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikipedia", - "description": "The layer 'Entrance 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 'Entrance' shows and asks freeform values for key 'level' (in the MapComplete.osm.be theme 'Entrances')" - }, - { - "key": "location", - "description": "Layer 'Entrance' shows location=underground with a fixed text, namely 'Located underground' (in the MapComplete.osm.be theme 'Entrances')", - "value": "underground" - }, - { - "key": "level", - "description": "Layer 'Entrance' 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.osm.be theme 'Entrances')", - "value": "0" - }, - { - "key": "level", - "description": "Layer 'Entrance' shows with a fixed text, namely 'Located on the ground floor' (in the MapComplete.osm.be theme 'Entrances') Picking this answer will delete the key level.", - "value": "" - }, - { - "key": "level", - "description": "Layer 'Entrance' 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.osm.be theme 'Entrances')", - "value": "1" - }, - { - "key": "level", - "description": "Layer 'Entrance' 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.osm.be theme 'Entrances')", - "value": "-1" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=yes with a fixed text, namely 'No specific entrance type is known' (in the MapComplete.osm.be theme 'Entrances')", - "value": "yes" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows indoor=door with a fixed text, namely 'This is an indoor door, separating a room or a corridor within a single building' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances') Picking this answer will delete the key entrance.", - "value": "" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows indoor=door with a fixed text, namely 'This is an indoor door, separating a room or a corridor within a single building' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "door" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=main with a fixed text, namely 'This is the main entrance' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=main with a fixed text, namely 'This is the main entrance' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "main" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=secondary with a fixed text, namely 'This is a secondary entrance' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=secondary with a fixed text, namely 'This is a secondary entrance' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "secondary" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=service with a fixed text, namely 'This is a service entrance - normally only used for employees, delivery, …' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=service with a fixed text, namely 'This is a service entrance - normally only used for employees, delivery, …' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "service" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=exit with a fixed text, namely 'This is an exit where one can not enter' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=exit with a fixed text, namely 'This is an exit where one can not enter' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "exit" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=entrance with a fixed text, namely 'This is an entrance where one can only enter (but not exit)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=entrance with a fixed text, namely 'This is an entrance where one can only enter (but not exit)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "entrance" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=emergency with a fixed text, namely 'This is emergency exit' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=emergency with a fixed text, namely 'This is emergency exit' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "emergency" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=home with a fixed text, namely 'This is the entrance to a private home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=home with a fixed text, namely 'This is the entrance to a private home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "home" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=yes with a fixed text, namely 'The door type is not known' (in the MapComplete.osm.be theme 'Entrances')", - "value": "yes" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=hinged with a fixed text, namely 'A classical, hinged door supported by joints' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "hinged" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=revolving with a fixed text, namely 'A revolving door which hangs on a central shaft, rotating within a cylindrical enclosure' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "revolving" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=sliding with a fixed text, namely 'A sliding door where the door slides sidewards, typically parallel with a wall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "sliding" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=overhead with a fixed text, namely 'A door which rolls from overhead, typically seen for garages' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "overhead" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=no with a fixed text, namely 'This is an entrance without a physical door' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "no" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=yes with a fixed text, namely 'This is an automatic door' (in the MapComplete.osm.be theme 'Entrances')", - "value": "yes" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=no with a fixed text, namely 'This door is not automated' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "no" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=motion with a fixed text, namely 'This door will open automatically when motion is detected' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "motion" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=floor with a fixed text, namely 'This door will open automatically when a sensor in the floor is triggered' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "floor" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=button with a fixed text, namely 'This door will open automatically when a button is pressed' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "button" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=slowdown_button with a fixed text, namely 'This door revolves automatically all the time, but has a button to slow it down, e.g. for wheelchair users' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "slowdown_button" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=continuous with a fixed text, namely 'This door revolves automatically all the time' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "continuous" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=serviced_on_button_press with a fixed text, namely 'This door will be opened by staff when requested by pressing a button' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "serviced_on_button_press" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=serviced_on_request with a fixed text, namely 'This door will be opened by staff when requested' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "serviced_on_request" - }, - { - "key": "width", - "description": "Layer 'Entrance' shows and asks freeform values for key 'width' (in the MapComplete.osm.be theme 'Entrances')" - }, - { - "key": "kerb:height", - "description": "Layer 'Entrance' shows and asks freeform values for key 'kerb:height' (in the MapComplete.osm.be theme 'Entrances')" - }, - { - "key": "kerb:height", - "description": "Layer 'Entrance' shows kerb:height=0 with a fixed text, namely 'This door does not have a kerb' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Entrances')", - "value": "0" - } - ] -} \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_etymology.json b/Docs/TagInfo/mapcomplete_etymology.json index 1c0b0f737..1ce82ce12 100644 --- a/Docs/TagInfo/mapcomplete_etymology.json +++ b/Docs/TagInfo/mapcomplete_etymology.json @@ -18,6 +18,10 @@ "key": "name:etymology", "description": "The MapComplete theme Open Etymology Map has a layer Has etymology showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Has etymology' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Etymology Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Has etymology shows images based on the keys image, image:0, image:1,... and wikidata, wikipedia, wikimedia_commons and mapillary" @@ -71,6 +75,10 @@ "key": "highway", "description": "The MapComplete theme Open Etymology Map has a layer Streets without etymology information showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Streets without etymology information' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Etymology Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Streets without etymology information shows images based on the keys image, image:0, image:1,... and wikidata, wikipedia, wikimedia_commons and mapillary" @@ -130,6 +138,10 @@ "description": "The MapComplete theme Open Etymology Map has a layer Parks and forests without etymology information showing features with this tag", "value": "forest" }, + { + "key": "id", + "description": "Layer 'Parks and forests without etymology information' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Etymology Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parks and forests without etymology information shows images based on the keys image, image:0, image:1,... and wikidata, wikipedia, wikimedia_commons and mapillary" @@ -204,6 +216,10 @@ "description": "The MapComplete theme Open Etymology Map has a layer Education institutions without etymology information showing features with this tag", "value": "education" }, + { + "key": "id", + "description": "Layer 'Education institutions without etymology information' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Etymology Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Education institutions without etymology information shows images based on the keys image, image:0, image:1,... and wikidata, wikipedia, wikimedia_commons and mapillary" @@ -278,6 +294,10 @@ "description": "The MapComplete theme Open Etymology Map has a layer Cultural places without etymology information showing features with this tag", "value": "theatre" }, + { + "key": "id", + "description": "Layer 'Cultural places without etymology information' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Etymology Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Cultural places without etymology information shows images based on the keys image, image:0, image:1,... and wikidata, wikipedia, wikimedia_commons and mapillary" @@ -347,6 +367,10 @@ "description": "The MapComplete theme Open Etymology Map has a layer Toursistic places without etymology information showing features with this tag", "value": "zoo" }, + { + "key": "id", + "description": "Layer 'Toursistic places without etymology information' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Etymology Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Toursistic places without etymology information shows images based on the keys image, image:0, image:1,... and wikidata, wikipedia, wikimedia_commons and mapillary" @@ -411,6 +435,10 @@ "description": "The MapComplete theme Open Etymology Map has a layer Health and social places without etymology information showing features with this tag", "value": "social_facility" }, + { + "key": "id", + "description": "Layer 'Health and social places without etymology information' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Etymology Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Health and social places without etymology information shows images based on the keys image, image:0, image:1,... and wikidata, wikipedia, wikimedia_commons and mapillary" @@ -475,6 +503,10 @@ "description": "The MapComplete theme Open Etymology Map has a layer Sport places without etymology information showing features with this tag", "value": "swimming_pool" }, + { + "key": "id", + "description": "Layer 'Sport places without etymology information' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Etymology Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Sport places without etymology information shows images based on the keys image, image:0, image:1,... and wikidata, wikipedia, wikimedia_commons and mapillary" diff --git a/Docs/TagInfo/mapcomplete_facadegardens.json b/Docs/TagInfo/mapcomplete_facadegardens.json index 55f6c2b8e..bf745b6ee 100644 --- a/Docs/TagInfo/mapcomplete_facadegardens.json +++ b/Docs/TagInfo/mapcomplete_facadegardens.json @@ -20,6 +20,10 @@ "description": "The MapComplete theme Facade gardens has a layer Facade gardens showing features with this tag", "value": "facade_garden" }, + { + "key": "id", + "description": "Layer 'Facade gardens' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Facade gardens') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Facade gardens 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" diff --git a/Docs/TagInfo/mapcomplete_food.json b/Docs/TagInfo/mapcomplete_food.json index 43fb67e07..ab94e36cd 100644 --- a/Docs/TagInfo/mapcomplete_food.json +++ b/Docs/TagInfo/mapcomplete_food.json @@ -20,6 +20,10 @@ "description": "The MapComplete theme Restaurants and fast food has a layer Restaurants and fast food showing features with this tag", "value": "restaurant" }, + { + "key": "id", + "description": "Layer 'Restaurants and fast food' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Restaurants and fast food') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "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" diff --git a/Docs/TagInfo/mapcomplete_fritures.json b/Docs/TagInfo/mapcomplete_fritures.json index 12a9b48ef..ad47bd615 100644 --- a/Docs/TagInfo/mapcomplete_fritures.json +++ b/Docs/TagInfo/mapcomplete_fritures.json @@ -24,6 +24,10 @@ "description": "The MapComplete theme Fries shops has a layer Fries shop showing features with this tag", "value": "restaurant" }, + { + "key": "id", + "description": "Layer 'Fries shop' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Fries shops') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "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" diff --git a/Docs/TagInfo/mapcomplete_ghostbikes.json b/Docs/TagInfo/mapcomplete_ghostbikes.json index b7f1fa4eb..2f8f730fc 100644 --- a/Docs/TagInfo/mapcomplete_ghostbikes.json +++ b/Docs/TagInfo/mapcomplete_ghostbikes.json @@ -2,7 +2,7 @@ "data_format": 1, "project": { "name": "MapComplete Ghost bikes", - "description": "A ghost bike is a memorial for a cyclist who died in a traffic accident, in the form of a white bicycle placed permanently near the accident location", + "description": "A ", "project_url": "https://mapcomplete.osm.be/ghostbikes", "doc_url": "https://github.com/pietervdvn/MapComplete/tree/master/assets/themes/", "icon_url": "https://mapcomplete.osm.be/assets/themes/ghostbikes/logo.svg", @@ -15,6 +15,10 @@ "description": "The MapComplete theme Ghost bikes has a layer Ghost bikes showing features with this tag", "value": "ghost_bike" }, + { + "key": "id", + "description": "Layer 'Ghost bikes' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Ghost bikes') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Ghost bikes 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" diff --git a/Docs/TagInfo/mapcomplete_governments.json b/Docs/TagInfo/mapcomplete_governments.json deleted file mode 100644 index a120d9068..000000000 --- a/Docs/TagInfo/mapcomplete_governments.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "data_format": 1, - "project": { - "name": "MapComplete Governmental Offices", - "description": "On this map, Governmental offices are shown and can be easily added", - "project_url": "https://mapcomplete.osm.be/governments", - "doc_url": "https://github.com/pietervdvn/MapComplete/tree/master/assets/themes/", - "icon_url": "https://mapcomplete.osm.be/assets/themes/onwheels/crest.svg", - "contact_name": "Pieter Vander Vennet, MapComplete", - "contact_email": "pietervdvn@posteo.net" - }, - "tags": [ - { - "key": "office", - "description": "The MapComplete theme Governmental Offices has a layer governments showing features with this tag", - "value": "government" - }, - { - "key": "image", - "description": "The layer 'governments allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "mapillary", - "description": "The layer 'governments allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikidata", - "description": "The layer 'governments allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikipedia", - "description": "The layer 'governments 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": "phone", - "description": "Layer 'governments' shows and asks freeform values for key 'phone' (in the MapComplete.osm.be theme 'Governmental Offices')" - }, - { - "key": "contact:phone", - "description": "Layer 'governments' shows contact:phone~^..*$ with a fixed text, namely '{contact:phone}' (in the MapComplete.osm.be theme 'Governmental Offices')" - }, - { - "key": "email", - "description": "Layer 'governments' shows and asks freeform values for key 'email' (in the MapComplete.osm.be theme 'Governmental Offices')" - }, - { - "key": "contact:email", - "description": "Layer 'governments' shows contact:email~^..*$ with a fixed text, namely '{contact:email}' (in the MapComplete.osm.be theme 'Governmental Offices')" - }, - { - "key": "website", - "description": "Layer 'governments' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Governmental Offices')" - }, - { - "key": "contact:website", - "description": "Layer 'governments' shows contact:website~^..*$ with a fixed text, namely '{contact:website}' (in the MapComplete.osm.be theme 'Governmental Offices')" - }, - { - "key": "name", - "description": "Layer 'governments' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Governmental Offices')" - } - ] -} \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_hackerspaces.json b/Docs/TagInfo/mapcomplete_hackerspaces.json index 81288314a..72464a888 100644 --- a/Docs/TagInfo/mapcomplete_hackerspaces.json +++ b/Docs/TagInfo/mapcomplete_hackerspaces.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Hackerspaces has a layer Hackerspace showing features with this tag", "value": "hackerspace" }, + { + "key": "id", + "description": "Layer 'Hackerspace' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Hackerspaces') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Hackerspace 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" diff --git a/Docs/TagInfo/mapcomplete_hailhydrant.json b/Docs/TagInfo/mapcomplete_hailhydrant.json index 4785c5fdf..63ecea27a 100644 --- a/Docs/TagInfo/mapcomplete_hailhydrant.json +++ b/Docs/TagInfo/mapcomplete_hailhydrant.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations has a layer Map of hydrants showing features with this tag", "value": "fire_hydrant" }, + { + "key": "id", + "description": "Layer 'Map of hydrants' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "colour", "description": "Layer 'Map of hydrants' shows and asks freeform values for key 'colour' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" @@ -130,6 +134,10 @@ "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations has a layer Map of fire extinguishers showing features with this tag", "value": "fire_extinguisher" }, + { + "key": "id", + "description": "Layer 'Map of fire extinguishers' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "location", "description": "Layer 'Map of fire extinguishers' shows and asks freeform values for key 'location' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" @@ -165,6 +173,10 @@ "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations has a layer Map of fire stations showing features with this tag", "value": "fire_station" }, + { + "key": "id", + "description": "Layer 'Map of fire stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" @@ -236,6 +248,10 @@ "description": "The MapComplete theme Hydrants, Extinguishers, Fire stations, and Ambulance stations has a layer Map of ambulance stations showing features with this tag", "value": "ambulance_station" }, + { + "key": "id", + "description": "Layer 'Map of ambulance stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Hydrants, Extinguishers, Fire stations, and Ambulance stations')" diff --git a/Docs/TagInfo/mapcomplete_healthcare.json b/Docs/TagInfo/mapcomplete_healthcare.json index 83b2f69cb..dfe7b8ca8 100644 --- a/Docs/TagInfo/mapcomplete_healthcare.json +++ b/Docs/TagInfo/mapcomplete_healthcare.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Healthcare has a layer Doctors showing features with this tag", "value": "doctors" }, + { + "key": "id", + "description": "Layer 'Doctors' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Healthcare') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Doctors 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" @@ -101,6 +105,10 @@ "description": "The MapComplete theme Healthcare has a layer Physiotherapist showing features with this tag", "value": "physiotherapist" }, + { + "key": "id", + "description": "Layer 'Physiotherapist' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Healthcare') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Physiotherapist 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" @@ -163,6 +171,10 @@ "description": "The MapComplete theme Healthcare has a layer Dentist showing features with this tag", "value": "dentist" }, + { + "key": "id", + "description": "Layer 'Dentist' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Healthcare') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Dentist 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" @@ -221,6 +233,10 @@ "description": "The MapComplete theme Healthcare has a layer Hospitals showing features with this tag", "value": "clinic" }, + { + "key": "id", + "description": "Layer 'Hospitals' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Healthcare') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Hospitals' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Healthcare')" @@ -268,6 +284,10 @@ "description": "The MapComplete theme Healthcare has a layer Pharmacies showing features with this tag", "value": "pharmacy" }, + { + "key": "id", + "description": "Layer 'Pharmacies' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Healthcare') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Pharmacies 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" @@ -350,6 +370,10 @@ "description": "The MapComplete theme Healthcare has a layer Shop showing features with this tag", "value": "optician" }, + { + "key": "id", + "description": "Layer 'Shop' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Healthcare') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer '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" @@ -370,810 +394,6 @@ "key": "name", "description": "Layer 'Shop' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Healthcare')" }, - { - "key": "shop", - "description": "Layer 'Shop' shows and asks freeform values for key 'shop' (in the MapComplete.osm.be theme 'Healthcare')" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=agrarian with a fixed text, namely 'Farm Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "agrarian" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=alcohol with a fixed text, namely 'Liquor Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "alcohol" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=anime with a fixed text, namely 'Anime / Manga Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "anime" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=antiques with a fixed text, namely 'Antiques Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "antiques" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=appliance with a fixed text, namely 'Appliance Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "appliance" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=art with a fixed text, namely 'Art Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "art" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=baby_goods with a fixed text, namely 'Baby Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "baby_goods" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bag with a fixed text, namely 'Bag/Luggage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bag" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bakery with a fixed text, namely 'Bakery' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bakery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bathroom_furnishing with a fixed text, namely 'Bathroom Furnishing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bathroom_furnishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beauty with a fixed text, namely 'Beauty Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "beauty" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bed with a fixed text, namely 'Bedding/Mattress Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bed" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beverages with a fixed text, namely 'Beverage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "beverages" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bicycle with a fixed text, namely 'Bicycle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bicycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=boat with a fixed text, namely 'Boat Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "boat" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bookmaker with a fixed text, namely 'Bookmaker' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bookmaker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=books with a fixed text, namely 'Book Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "books" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=brewing_supplies with a fixed text, namely 'Brewing Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "brewing_supplies" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=butcher with a fixed text, namely 'Butcher' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "butcher" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=camera with a fixed text, namely 'Camera Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "camera" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=candles with a fixed text, namely 'Candle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "candles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cannabis with a fixed text, namely 'Cannabis Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "cannabis" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car with a fixed text, namely 'Car Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "car" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_parts with a fixed text, namely 'Car Parts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "car_parts" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_repair with a fixed text, namely 'Car Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "car_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=caravan with a fixed text, namely 'RV Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "caravan" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=carpet with a fixed text, namely 'Carpet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "carpet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=catalogue with a fixed text, namely 'Catalog Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "catalogue" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=charity with a fixed text, namely 'Charity Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "charity" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cheese with a fixed text, namely 'Cheese Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "cheese" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chemist with a fixed text, namely 'Drugstore' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "chemist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chocolate with a fixed text, namely 'Chocolate Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "chocolate" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=clothes with a fixed text, namely 'Clothing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "clothes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=coffee with a fixed text, namely 'Coffee Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "coffee" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=collector with a fixed text, namely 'Collectibles Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "collector" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=computer with a fixed text, namely 'Computer Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "computer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=confectionery with a fixed text, namely 'Candy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "confectionery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=convenience with a fixed text, namely 'Convenience Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "convenience" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=copyshop with a fixed text, namely 'Copy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "copyshop" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cosmetics with a fixed text, namely 'Cosmetics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "cosmetics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=country_store with a fixed text, namely 'Country Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "country_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=craft with a fixed text, namely 'Arts & Crafts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "craft" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=curtain with a fixed text, namely 'Curtain Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "curtain" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dairy with a fixed text, namely 'Dairy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "dairy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=deli with a fixed text, namely 'Deli' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "deli" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=department_store with a fixed text, namely 'Department Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "department_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doityourself with a fixed text, namely 'DIY Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "doityourself" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doors with a fixed text, namely 'Door Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "doors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dry_cleaning with a fixed text, namely 'Dry Cleaner' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "dry_cleaning" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=e-cigarette with a fixed text, namely 'E-Cigarette Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "e-cigarette" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electrical with a fixed text, namely 'Electrical Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "electrical" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electronics with a fixed text, namely 'Electronics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "electronics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=erotic with a fixed text, namely 'Erotic Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "erotic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fabric with a fixed text, namely 'Fabric Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fabric" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=farm with a fixed text, namely 'Produce Stand' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "farm" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fashion_accessories with a fixed text, namely 'Fashion Accessories Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fashion_accessories" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fireplace with a fixed text, namely 'Fireplace Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fireplace" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fishing with a fixed text, namely 'Fishing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=flooring with a fixed text, namely 'Flooring Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "flooring" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=florist with a fixed text, namely 'Florist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "florist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frame with a fixed text, namely 'Framing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "frame" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frozen_food with a fixed text, namely 'Frozen Food Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "frozen_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fuel with a fixed text, namely 'Fuel Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fuel" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=funeral_directors with a fixed text, namely 'Funeral Home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "funeral_directors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=furniture with a fixed text, namely 'Furniture Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "furniture" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=games with a fixed text, namely 'Tabletop Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=garden_centre with a fixed text, namely 'Garden Center' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "garden_centre" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gas with a fixed text, namely 'Bottled Gas Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "gas" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=general with a fixed text, namely 'General Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "general" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gift with a fixed text, namely 'Gift Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "gift" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=greengrocer with a fixed text, namely 'Greengrocer' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "greengrocer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser with a fixed text, namely 'Hairdresser' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hairdresser" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser_supply with a fixed text, namely 'Hairdresser Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hairdresser_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hardware with a fixed text, namely 'Hardware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hardware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=health_food with a fixed text, namely 'Health Food Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "health_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hearing_aids with a fixed text, namely 'Hearing Aids Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hearing_aids" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=herbalist with a fixed text, namely 'Herbalist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "herbalist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hifi with a fixed text, namely 'Hifi Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hifi" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hobby with a fixed text, namely 'Hobby Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hobby" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=household_linen with a fixed text, namely 'Household Linen Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "household_linen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=houseware with a fixed text, namely 'Houseware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "houseware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hunting with a fixed text, namely 'Hunting Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hunting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=interior_decoration with a fixed text, namely 'Interior Decoration Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "interior_decoration" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=jewelry with a fixed text, namely 'Jewelry Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "jewelry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kiosk with a fixed text, namely 'Kiosk' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "kiosk" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kitchen with a fixed text, namely 'Kitchen Design Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "kitchen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=laundry with a fixed text, namely 'Laundry' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "laundry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=leather with a fixed text, namely 'Leather Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "leather" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lighting with a fixed text, namely 'Lighting Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "lighting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=locksmith with a fixed text, namely 'Locksmith' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "locksmith" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lottery with a fixed text, namely 'Lottery Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "lottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mall with a fixed text, namely 'Mall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "mall" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=massage with a fixed text, namely 'Massage Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "massage" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=medical_supply with a fixed text, namely 'Medical Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "medical_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=military_surplus with a fixed text, namely 'Military Surplus Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "military_surplus" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mobile_phone with a fixed text, namely 'Mobile Phone Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "mobile_phone" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=model with a fixed text, namely 'Model Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "model" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=money_lender with a fixed text, namely 'Money Lender' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "money_lender" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle with a fixed text, namely 'Motorcycle Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "motorcycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle_repair with a fixed text, namely 'Motorcycle Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "motorcycle_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=music with a fixed text, namely 'Music Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "music" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=musical_instrument with a fixed text, namely 'Musical Instrument Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "musical_instrument" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=newsagent with a fixed text, namely 'Newspaper/Magazine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "newsagent" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=nutrition_supplements with a fixed text, namely 'Nutrition Supplements Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "nutrition_supplements" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=optician with a fixed text, namely 'Optician' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "optician" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outdoor with a fixed text, namely 'Outdoors Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "outdoor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outpost with a fixed text, namely 'Online Retailer Outpost' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "outpost" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=paint with a fixed text, namely 'Paint Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "paint" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=party with a fixed text, namely 'Party Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "party" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pastry with a fixed text, namely 'Pastry Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pastry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pawnbroker with a fixed text, namely 'Pawn Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pawnbroker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=perfumery with a fixed text, namely 'Perfume Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "perfumery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet with a fixed text, namely 'Pet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet_grooming with a fixed text, namely 'Pet Grooming Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pet_grooming" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=photo with a fixed text, namely 'Photography Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "photo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pottery with a fixed text, namely 'Pottery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=printer_ink with a fixed text, namely 'Printer Ink Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "printer_ink" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=psychic with a fixed text, namely 'Psychic' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "psychic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pyrotechnics with a fixed text, namely 'Fireworks Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pyrotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=radiotechnics with a fixed text, namely 'Radio/Electronic Component Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "radiotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=religion with a fixed text, namely 'Religious Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "religion" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=rental with a fixed text, namely 'Rental Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=repair with a fixed text, namely 'Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=scuba_diving with a fixed text, namely 'Scuba Diving Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "scuba_diving" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=seafood with a fixed text, namely 'Seafood Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "seafood" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=second_hand with a fixed text, namely 'Consignment/Thrift Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "second_hand" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sewing with a fixed text, namely 'Sewing Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "sewing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoe_repair with a fixed text, namely 'Shoe Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "shoe_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoes with a fixed text, namely 'Shoe Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "shoes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=spices with a fixed text, namely 'Spice Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "spices" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sports with a fixed text, namely 'Sporting Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=stationery with a fixed text, namely 'Stationery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "stationery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=storage_rental with a fixed text, namely 'Storage Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "storage_rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=supermarket with a fixed text, namely 'Supermarket' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "supermarket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=swimming_pool with a fixed text, namely 'Pool Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "swimming_pool" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tailor with a fixed text, namely 'Tailor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tailor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tattoo with a fixed text, namely 'Tattoo Parlor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tattoo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tea with a fixed text, namely 'Tea Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tea" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=telecommunication with a fixed text, namely 'Telecom Retail Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "telecommunication" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=ticket with a fixed text, namely 'Ticket Seller' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "ticket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tiles with a fixed text, namely 'Tile Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tiles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tobacco with a fixed text, namely 'Tobacco Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tobacco" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tool_hire with a fixed text, namely 'Tool Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tool_hire" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=toys with a fixed text, namely 'Toy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "toys" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trade with a fixed text, namely 'Trade Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "trade" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=travel_agency with a fixed text, namely 'Travel Agency' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "travel_agency" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trophy with a fixed text, namely 'Trophy Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "trophy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tyres with a fixed text, namely 'Tire Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tyres" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=vacuum_cleaner with a fixed text, namely 'Vacuum Cleaner Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "vacuum_cleaner" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=variety_store with a fixed text, namely 'Variety Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "variety_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video with a fixed text, namely 'Video Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "video" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video_games with a fixed text, namely 'Video Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "video_games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=watches with a fixed text, namely 'Watches Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "watches" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water with a fixed text, namely 'Drinking Water Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "water" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water_sports with a fixed text, namely 'Watersport/Swim Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "water_sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=weapons with a fixed text, namely 'Weapon Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "weapons" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wholesale with a fixed text, namely 'Wholesale Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "wholesale" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wigs with a fixed text, namely 'Wig Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "wigs" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=window_blind with a fixed text, namely 'Window Blind Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "window_blind" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wine with a fixed text, namely 'Wine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "wine" - }, { "key": "opening_hours", "description": "Layer 'Shop' shows and asks freeform values for key 'opening_hours' (in the MapComplete.osm.be theme 'Healthcare')" @@ -1339,6 +559,10 @@ "key": "shop", "description": "The MapComplete theme Healthcare has a layer Shop showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Shop' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Healthcare') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer '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" @@ -1359,810 +583,6 @@ "key": "name", "description": "Layer 'Shop' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Healthcare')" }, - { - "key": "shop", - "description": "Layer 'Shop' shows and asks freeform values for key 'shop' (in the MapComplete.osm.be theme 'Healthcare')" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=agrarian with a fixed text, namely 'Farm Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "agrarian" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=alcohol with a fixed text, namely 'Liquor Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "alcohol" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=anime with a fixed text, namely 'Anime / Manga Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "anime" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=antiques with a fixed text, namely 'Antiques Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "antiques" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=appliance with a fixed text, namely 'Appliance Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "appliance" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=art with a fixed text, namely 'Art Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "art" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=baby_goods with a fixed text, namely 'Baby Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "baby_goods" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bag with a fixed text, namely 'Bag/Luggage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bag" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bakery with a fixed text, namely 'Bakery' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bakery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bathroom_furnishing with a fixed text, namely 'Bathroom Furnishing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bathroom_furnishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beauty with a fixed text, namely 'Beauty Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "beauty" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bed with a fixed text, namely 'Bedding/Mattress Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bed" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beverages with a fixed text, namely 'Beverage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "beverages" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bicycle with a fixed text, namely 'Bicycle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bicycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=boat with a fixed text, namely 'Boat Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "boat" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bookmaker with a fixed text, namely 'Bookmaker' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "bookmaker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=books with a fixed text, namely 'Book Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "books" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=brewing_supplies with a fixed text, namely 'Brewing Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "brewing_supplies" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=butcher with a fixed text, namely 'Butcher' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "butcher" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=camera with a fixed text, namely 'Camera Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "camera" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=candles with a fixed text, namely 'Candle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "candles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cannabis with a fixed text, namely 'Cannabis Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "cannabis" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car with a fixed text, namely 'Car Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "car" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_parts with a fixed text, namely 'Car Parts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "car_parts" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_repair with a fixed text, namely 'Car Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "car_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=caravan with a fixed text, namely 'RV Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "caravan" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=carpet with a fixed text, namely 'Carpet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "carpet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=catalogue with a fixed text, namely 'Catalog Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "catalogue" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=charity with a fixed text, namely 'Charity Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "charity" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cheese with a fixed text, namely 'Cheese Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "cheese" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chemist with a fixed text, namely 'Drugstore' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "chemist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chocolate with a fixed text, namely 'Chocolate Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "chocolate" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=clothes with a fixed text, namely 'Clothing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "clothes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=coffee with a fixed text, namely 'Coffee Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "coffee" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=collector with a fixed text, namely 'Collectibles Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "collector" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=computer with a fixed text, namely 'Computer Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "computer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=confectionery with a fixed text, namely 'Candy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "confectionery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=convenience with a fixed text, namely 'Convenience Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "convenience" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=copyshop with a fixed text, namely 'Copy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "copyshop" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cosmetics with a fixed text, namely 'Cosmetics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "cosmetics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=country_store with a fixed text, namely 'Country Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "country_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=craft with a fixed text, namely 'Arts & Crafts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "craft" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=curtain with a fixed text, namely 'Curtain Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "curtain" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dairy with a fixed text, namely 'Dairy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "dairy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=deli with a fixed text, namely 'Deli' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "deli" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=department_store with a fixed text, namely 'Department Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "department_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doityourself with a fixed text, namely 'DIY Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "doityourself" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doors with a fixed text, namely 'Door Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "doors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dry_cleaning with a fixed text, namely 'Dry Cleaner' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "dry_cleaning" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=e-cigarette with a fixed text, namely 'E-Cigarette Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "e-cigarette" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electrical with a fixed text, namely 'Electrical Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "electrical" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electronics with a fixed text, namely 'Electronics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "electronics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=erotic with a fixed text, namely 'Erotic Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "erotic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fabric with a fixed text, namely 'Fabric Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fabric" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=farm with a fixed text, namely 'Produce Stand' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "farm" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fashion_accessories with a fixed text, namely 'Fashion Accessories Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fashion_accessories" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fireplace with a fixed text, namely 'Fireplace Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fireplace" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fishing with a fixed text, namely 'Fishing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=flooring with a fixed text, namely 'Flooring Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "flooring" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=florist with a fixed text, namely 'Florist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "florist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frame with a fixed text, namely 'Framing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "frame" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frozen_food with a fixed text, namely 'Frozen Food Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "frozen_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fuel with a fixed text, namely 'Fuel Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "fuel" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=funeral_directors with a fixed text, namely 'Funeral Home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "funeral_directors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=furniture with a fixed text, namely 'Furniture Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "furniture" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=games with a fixed text, namely 'Tabletop Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=garden_centre with a fixed text, namely 'Garden Center' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "garden_centre" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gas with a fixed text, namely 'Bottled Gas Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "gas" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=general with a fixed text, namely 'General Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "general" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gift with a fixed text, namely 'Gift Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "gift" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=greengrocer with a fixed text, namely 'Greengrocer' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "greengrocer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser with a fixed text, namely 'Hairdresser' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hairdresser" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser_supply with a fixed text, namely 'Hairdresser Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hairdresser_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hardware with a fixed text, namely 'Hardware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hardware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=health_food with a fixed text, namely 'Health Food Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "health_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hearing_aids with a fixed text, namely 'Hearing Aids Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hearing_aids" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=herbalist with a fixed text, namely 'Herbalist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "herbalist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hifi with a fixed text, namely 'Hifi Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hifi" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hobby with a fixed text, namely 'Hobby Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hobby" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=household_linen with a fixed text, namely 'Household Linen Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "household_linen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=houseware with a fixed text, namely 'Houseware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "houseware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hunting with a fixed text, namely 'Hunting Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "hunting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=interior_decoration with a fixed text, namely 'Interior Decoration Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "interior_decoration" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=jewelry with a fixed text, namely 'Jewelry Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "jewelry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kiosk with a fixed text, namely 'Kiosk' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "kiosk" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kitchen with a fixed text, namely 'Kitchen Design Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "kitchen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=laundry with a fixed text, namely 'Laundry' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "laundry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=leather with a fixed text, namely 'Leather Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "leather" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lighting with a fixed text, namely 'Lighting Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "lighting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=locksmith with a fixed text, namely 'Locksmith' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "locksmith" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lottery with a fixed text, namely 'Lottery Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "lottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mall with a fixed text, namely 'Mall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "mall" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=massage with a fixed text, namely 'Massage Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "massage" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=medical_supply with a fixed text, namely 'Medical Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "medical_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=military_surplus with a fixed text, namely 'Military Surplus Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "military_surplus" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mobile_phone with a fixed text, namely 'Mobile Phone Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "mobile_phone" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=model with a fixed text, namely 'Model Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "model" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=money_lender with a fixed text, namely 'Money Lender' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "money_lender" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle with a fixed text, namely 'Motorcycle Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "motorcycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle_repair with a fixed text, namely 'Motorcycle Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "motorcycle_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=music with a fixed text, namely 'Music Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "music" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=musical_instrument with a fixed text, namely 'Musical Instrument Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "musical_instrument" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=newsagent with a fixed text, namely 'Newspaper/Magazine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "newsagent" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=nutrition_supplements with a fixed text, namely 'Nutrition Supplements Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "nutrition_supplements" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=optician with a fixed text, namely 'Optician' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "optician" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outdoor with a fixed text, namely 'Outdoors Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "outdoor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outpost with a fixed text, namely 'Online Retailer Outpost' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "outpost" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=paint with a fixed text, namely 'Paint Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "paint" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=party with a fixed text, namely 'Party Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "party" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pastry with a fixed text, namely 'Pastry Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pastry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pawnbroker with a fixed text, namely 'Pawn Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pawnbroker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=perfumery with a fixed text, namely 'Perfume Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "perfumery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet with a fixed text, namely 'Pet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet_grooming with a fixed text, namely 'Pet Grooming Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pet_grooming" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=photo with a fixed text, namely 'Photography Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "photo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pottery with a fixed text, namely 'Pottery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=printer_ink with a fixed text, namely 'Printer Ink Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "printer_ink" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=psychic with a fixed text, namely 'Psychic' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "psychic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pyrotechnics with a fixed text, namely 'Fireworks Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "pyrotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=radiotechnics with a fixed text, namely 'Radio/Electronic Component Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "radiotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=religion with a fixed text, namely 'Religious Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "religion" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=rental with a fixed text, namely 'Rental Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=repair with a fixed text, namely 'Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=scuba_diving with a fixed text, namely 'Scuba Diving Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "scuba_diving" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=seafood with a fixed text, namely 'Seafood Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "seafood" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=second_hand with a fixed text, namely 'Consignment/Thrift Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "second_hand" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sewing with a fixed text, namely 'Sewing Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "sewing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoe_repair with a fixed text, namely 'Shoe Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "shoe_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoes with a fixed text, namely 'Shoe Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "shoes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=spices with a fixed text, namely 'Spice Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "spices" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sports with a fixed text, namely 'Sporting Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=stationery with a fixed text, namely 'Stationery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "stationery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=storage_rental with a fixed text, namely 'Storage Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "storage_rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=supermarket with a fixed text, namely 'Supermarket' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "supermarket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=swimming_pool with a fixed text, namely 'Pool Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "swimming_pool" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tailor with a fixed text, namely 'Tailor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tailor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tattoo with a fixed text, namely 'Tattoo Parlor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tattoo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tea with a fixed text, namely 'Tea Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tea" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=telecommunication with a fixed text, namely 'Telecom Retail Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "telecommunication" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=ticket with a fixed text, namely 'Ticket Seller' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "ticket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tiles with a fixed text, namely 'Tile Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tiles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tobacco with a fixed text, namely 'Tobacco Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tobacco" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tool_hire with a fixed text, namely 'Tool Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tool_hire" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=toys with a fixed text, namely 'Toy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "toys" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trade with a fixed text, namely 'Trade Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "trade" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=travel_agency with a fixed text, namely 'Travel Agency' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "travel_agency" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trophy with a fixed text, namely 'Trophy Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "trophy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tyres with a fixed text, namely 'Tire Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "tyres" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=vacuum_cleaner with a fixed text, namely 'Vacuum Cleaner Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "vacuum_cleaner" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=variety_store with a fixed text, namely 'Variety Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "variety_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video with a fixed text, namely 'Video Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "video" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video_games with a fixed text, namely 'Video Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "video_games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=watches with a fixed text, namely 'Watches Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "watches" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water with a fixed text, namely 'Drinking Water Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "water" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water_sports with a fixed text, namely 'Watersport/Swim Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "water_sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=weapons with a fixed text, namely 'Weapon Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "weapons" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wholesale with a fixed text, namely 'Wholesale Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "wholesale" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wigs with a fixed text, namely 'Wig Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "wigs" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=window_blind with a fixed text, namely 'Window Blind Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "window_blind" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wine with a fixed text, namely 'Wine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Healthcare')", - "value": "wine" - }, { "key": "opening_hours", "description": "Layer 'Shop' shows and asks freeform values for key 'opening_hours' (in the MapComplete.osm.be theme 'Healthcare')" diff --git a/Docs/TagInfo/mapcomplete_hotels.json b/Docs/TagInfo/mapcomplete_hotels.json index 5bf9458a9..41c3ed507 100644 --- a/Docs/TagInfo/mapcomplete_hotels.json +++ b/Docs/TagInfo/mapcomplete_hotels.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Hotels has a layer Hotels showing features with this tag", "value": "hotel" }, + { + "key": "id", + "description": "Layer 'Hotels' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Hotels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" diff --git a/Docs/TagInfo/mapcomplete_indoors.json b/Docs/TagInfo/mapcomplete_indoors.json index e1acbe987..611e83173 100644 --- a/Docs/TagInfo/mapcomplete_indoors.json +++ b/Docs/TagInfo/mapcomplete_indoors.json @@ -35,6 +35,10 @@ "description": "The MapComplete theme Indoors has a layer Indoors showing features with this tag", "value": "level" }, + { + "key": "id", + "description": "Layer 'Indoors' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Indoors') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "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" @@ -84,6 +88,10 @@ "description": "The MapComplete theme Indoors has a layer Elevator showing features with this tag", "value": "elevator" }, + { + "key": "id", + "description": "Layer 'Elevator' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Indoors') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Elevator 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" @@ -184,6 +192,10 @@ "key": "door", "description": "The MapComplete theme Indoors has a layer Entrance showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Entrance' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Indoors') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Entrance 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" diff --git a/Docs/TagInfo/mapcomplete_kerbs_and_crossings.json b/Docs/TagInfo/mapcomplete_kerbs_and_crossings.json index af83c9b87..4cfa906b8 100644 --- a/Docs/TagInfo/mapcomplete_kerbs_and_crossings.json +++ b/Docs/TagInfo/mapcomplete_kerbs_and_crossings.json @@ -105,6 +105,10 @@ "description": "The MapComplete theme Kerbs and crossings has a layer Cycleways and roads showing features with this tag", "value": "designated" }, + { + "key": "id", + "description": "Layer 'Cycleways and roads' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Kerbs and crossings') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "cycleway", "description": "Layer 'Cycleways and roads' shows cycleway=shared_lane with a fixed text, namely 'There is a shared lane' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Kerbs and crossings') (This is only shown if highway!=cycleway&highway!=path&highway!=footway)", @@ -568,6 +572,10 @@ "description": "The MapComplete theme Kerbs and crossings has a layer Crossings showing features with this tag", "value": "crossing" }, + { + "key": "id", + "description": "Layer 'Crossings' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Kerbs and crossings') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Crossings 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" @@ -744,6 +752,10 @@ "description": "The MapComplete theme Kerbs and crossings has a layer Kerbs showing features with this tag", "value": "kerb" }, + { + "key": "id", + "description": "Layer 'Kerbs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Kerbs and crossings') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Kerbs 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" diff --git a/Docs/TagInfo/mapcomplete_maps.json b/Docs/TagInfo/mapcomplete_maps.json index 132988f23..6a5d886bc 100644 --- a/Docs/TagInfo/mapcomplete_maps.json +++ b/Docs/TagInfo/mapcomplete_maps.json @@ -20,6 +20,10 @@ "description": "The MapComplete theme A map of maps has a layer Maps showing features with this tag", "value": "map" }, + { + "key": "id", + "description": "Layer 'Maps' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'A map of maps') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Maps 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" diff --git a/Docs/TagInfo/mapcomplete_maxspeed.json b/Docs/TagInfo/mapcomplete_maxspeed.json index fbc312617..b2b040511 100644 --- a/Docs/TagInfo/mapcomplete_maxspeed.json +++ b/Docs/TagInfo/mapcomplete_maxspeed.json @@ -80,6 +80,10 @@ "description": "The MapComplete theme Maxspeed has a layer Maxspeed showing features with this tag", "value": "motorway_link" }, + { + "key": "id", + "description": "Layer 'Maxspeed' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Maxspeed') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "maxspeed", "description": "Layer 'Maxspeed' shows and asks freeform values for key 'maxspeed' (in the MapComplete.osm.be theme 'Maxspeed')" @@ -99,6 +103,10 @@ "description": "The MapComplete theme Maxspeed has a layer Speed Camera showing features with this tag", "value": "speed_camera" }, + { + "key": "id", + "description": "Layer 'Speed Camera' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Maxspeed') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "maxspeed", "description": "Layer 'Speed Camera' shows and asks freeform values for key 'maxspeed' (in the MapComplete.osm.be theme 'Maxspeed')" @@ -108,6 +116,10 @@ "description": "The MapComplete theme Maxspeed has a layer Speed Display showing features with this tag", "value": "speed_display" }, + { + "key": "id", + "description": "Layer 'Speed Display' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Maxspeed') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "maxspeed", "description": "Layer 'Speed Display' shows and asks freeform values for key 'maxspeed' (in the MapComplete.osm.be theme 'Maxspeed')" diff --git a/Docs/TagInfo/mapcomplete_nature.json b/Docs/TagInfo/mapcomplete_nature.json index 5aeca54bd..bd0165e3c 100644 --- a/Docs/TagInfo/mapcomplete_nature.json +++ b/Docs/TagInfo/mapcomplete_nature.json @@ -20,6 +20,10 @@ "description": "The MapComplete theme Into nature has a layer Drinking water showing features with this tag", "value": "yes" }, + { + "key": "id", + "description": "Layer 'Drinking water' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Drinking water 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" @@ -70,6 +74,10 @@ "description": "The MapComplete theme Into nature has a layer Bird watching places showing features with this tag", "value": "bird_hide" }, + { + "key": "id", + "description": "Layer 'Bird watching places' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bird watching places 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" @@ -185,6 +193,10 @@ "description": "The MapComplete theme Into nature has a layer Nature reserve showing features with this tag", "value": "protected_area" }, + { + "key": "id", + "description": "Layer 'Nature reserve' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Nature reserve 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" @@ -363,6 +375,10 @@ "description": "The MapComplete theme Into nature has a layer Maps showing features with this tag", "value": "map" }, + { + "key": "id", + "description": "Layer 'Maps' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Maps 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" @@ -423,6 +439,10 @@ "description": "The MapComplete theme Into nature has a layer Information boards showing features with this tag", "value": "board" }, + { + "key": "id", + "description": "Layer 'Information boards' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Information boards 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" @@ -444,6 +464,10 @@ "description": "The MapComplete theme Into nature has a layer Benches showing features with this tag", "value": "bench" }, + { + "key": "id", + "description": "Layer 'Benches' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Benches 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" @@ -619,96 +643,15 @@ "description": "Layer 'Benches' shows not:historic=memorial with a fixed text, namely 'This bench is a not a memorial for someone or something' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if historic=memorial|inscription~.+|memorial=bench|tourism=artwork)", "value": "memorial" }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows and asks freeform values for key 'artwork_type' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=architecture with a fixed text, namely 'Architecture' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "architecture" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=mural with a fixed text, namely 'Mural' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "mural" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=painting with a fixed text, namely 'Painting' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "painting" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=sculpture with a fixed text, namely 'Sculpture' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "sculpture" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=statue with a fixed text, namely 'Statue' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "statue" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=bust with a fixed text, namely 'Bust' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "bust" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=stone with a fixed text, namely 'Stone' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "stone" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=installation with a fixed text, namely 'Installation' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "installation" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=graffiti with a fixed text, namely 'Graffiti' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "graffiti" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=relief with a fixed text, namely 'Relief' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "relief" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=azulejo with a fixed text, namely 'Azulejo (Spanish decorative tilework)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "azulejo" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=tilework with a fixed text, namely 'Tilework' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "tilework" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=woodcarving with a fixed text, namely 'Woodcarving' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)", - "value": "woodcarving" - }, - { - "key": "artist:wikidata", - "description": "Layer 'Benches' shows and asks freeform values for key 'artist:wikidata' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)" - }, - { - "key": "artist_name", - "description": "Layer 'Benches' shows and asks freeform values for key 'artist_name' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)" - }, - { - "key": "website", - "description": "Layer 'Benches' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)" - }, - { - "key": "subject:wikidata", - "description": "Layer 'Benches' shows and asks freeform values for key 'subject:wikidata' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if tourism=artwork)" - }, { "key": "leisure", "description": "The MapComplete theme Into nature has a layer Picnic tables showing features with this tag", "value": "picnic_table" }, + { + "key": "id", + "description": "Layer 'Picnic tables' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Picnic tables 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" @@ -778,6 +721,10 @@ "description": "The MapComplete theme Into nature has a layer Toilets showing features with this tag", "value": "toilets" }, + { + "key": "id", + "description": "Layer 'Toilets' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Into nature') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Toilets 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" diff --git a/Docs/TagInfo/mapcomplete_notes.json b/Docs/TagInfo/mapcomplete_notes.json index 4c1c6a164..0604baf0d 100644 --- a/Docs/TagInfo/mapcomplete_notes.json +++ b/Docs/TagInfo/mapcomplete_notes.json @@ -17,6 +17,10 @@ { "key": "FIXME", "description": "The MapComplete theme Notes on OpenStreetMap has a layer OSM objects with FIXME tags showing features with this tag" + }, + { + "key": "id", + "description": "Layer 'OSM objects with FIXME tags' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Notes on OpenStreetMap') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" } ] } \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_observation_towers.json b/Docs/TagInfo/mapcomplete_observation_towers.json index edeeade8d..576525e95 100644 --- a/Docs/TagInfo/mapcomplete_observation_towers.json +++ b/Docs/TagInfo/mapcomplete_observation_towers.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Observation towers has a layer Observation towers showing features with this tag", "value": "observation" }, + { + "key": "id", + "description": "Layer 'Observation towers' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Observation towers') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Observation towers 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" diff --git a/Docs/TagInfo/mapcomplete_onwheels.json b/Docs/TagInfo/mapcomplete_onwheels.json index 6af8afe2d..cd304e59d 100644 --- a/Docs/TagInfo/mapcomplete_onwheels.json +++ b/Docs/TagInfo/mapcomplete_onwheels.json @@ -35,6 +35,10 @@ "description": "The MapComplete theme OnWheels has a layer Cafés and pubs showing features with this tag", "value": "nightclub" }, + { + "key": "id", + "description": "Layer 'Cafés and pubs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Cafés and pubs 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" @@ -294,6 +298,10 @@ "key": "door", "description": "The MapComplete theme OnWheels has a layer Entrance showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Entrance' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Entrance 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" @@ -522,6 +530,10 @@ "description": "The MapComplete theme OnWheels has a layer Restaurants and fast food showing features with this tag", "value": "restaurant" }, + { + "key": "id", + "description": "Layer 'Restaurants and fast food' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "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" @@ -1007,6 +1019,10 @@ "description": "The MapComplete theme OnWheels has a layer Kerbs showing features with this tag", "value": "kerb" }, + { + "key": "id", + "description": "Layer 'Kerbs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Kerbs 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" @@ -1077,6 +1093,10 @@ "description": "The MapComplete theme OnWheels has a layer Parking showing features with this tag", "value": "parking" }, + { + "key": "id", + "description": "Layer 'Parking' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parking 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" @@ -1200,6 +1220,10 @@ "description": "The MapComplete theme OnWheels has a layer Disabled parking spaces showing features with this tag", "value": "disabled" }, + { + "key": "id", + "description": "Layer 'Disabled parking spaces' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Disabled parking spaces 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" @@ -1220,6 +1244,10 @@ "key": "shop", "description": "The MapComplete theme OnWheels has a layer Shop showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Shop' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer '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" @@ -1240,810 +1268,6 @@ "key": "name", "description": "Layer 'Shop' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'OnWheels')" }, - { - "key": "shop", - "description": "Layer 'Shop' shows and asks freeform values for key 'shop' (in the MapComplete.osm.be theme 'OnWheels')" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=agrarian with a fixed text, namely 'Farm Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "agrarian" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=alcohol with a fixed text, namely 'Liquor Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "alcohol" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=anime with a fixed text, namely 'Anime / Manga Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "anime" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=antiques with a fixed text, namely 'Antiques Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "antiques" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=appliance with a fixed text, namely 'Appliance Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "appliance" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=art with a fixed text, namely 'Art Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "art" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=baby_goods with a fixed text, namely 'Baby Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "baby_goods" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bag with a fixed text, namely 'Bag/Luggage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "bag" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bakery with a fixed text, namely 'Bakery' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "bakery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bathroom_furnishing with a fixed text, namely 'Bathroom Furnishing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "bathroom_furnishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beauty with a fixed text, namely 'Beauty Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "beauty" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bed with a fixed text, namely 'Bedding/Mattress Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "bed" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beverages with a fixed text, namely 'Beverage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "beverages" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bicycle with a fixed text, namely 'Bicycle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "bicycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=boat with a fixed text, namely 'Boat Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "boat" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bookmaker with a fixed text, namely 'Bookmaker' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "bookmaker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=books with a fixed text, namely 'Book Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "books" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=brewing_supplies with a fixed text, namely 'Brewing Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "brewing_supplies" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=butcher with a fixed text, namely 'Butcher' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "butcher" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=camera with a fixed text, namely 'Camera Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "camera" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=candles with a fixed text, namely 'Candle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "candles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cannabis with a fixed text, namely 'Cannabis Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "cannabis" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car with a fixed text, namely 'Car Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "car" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_parts with a fixed text, namely 'Car Parts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "car_parts" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_repair with a fixed text, namely 'Car Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "car_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=caravan with a fixed text, namely 'RV Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "caravan" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=carpet with a fixed text, namely 'Carpet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "carpet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=catalogue with a fixed text, namely 'Catalog Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "catalogue" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=charity with a fixed text, namely 'Charity Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "charity" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cheese with a fixed text, namely 'Cheese Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "cheese" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chemist with a fixed text, namely 'Drugstore' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "chemist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chocolate with a fixed text, namely 'Chocolate Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "chocolate" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=clothes with a fixed text, namely 'Clothing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "clothes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=coffee with a fixed text, namely 'Coffee Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "coffee" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=collector with a fixed text, namely 'Collectibles Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "collector" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=computer with a fixed text, namely 'Computer Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "computer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=confectionery with a fixed text, namely 'Candy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "confectionery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=convenience with a fixed text, namely 'Convenience Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "convenience" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=copyshop with a fixed text, namely 'Copy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "copyshop" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cosmetics with a fixed text, namely 'Cosmetics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "cosmetics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=country_store with a fixed text, namely 'Country Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "country_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=craft with a fixed text, namely 'Arts & Crafts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "craft" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=curtain with a fixed text, namely 'Curtain Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "curtain" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dairy with a fixed text, namely 'Dairy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "dairy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=deli with a fixed text, namely 'Deli' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "deli" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=department_store with a fixed text, namely 'Department Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "department_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doityourself with a fixed text, namely 'DIY Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "doityourself" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doors with a fixed text, namely 'Door Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "doors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dry_cleaning with a fixed text, namely 'Dry Cleaner' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "dry_cleaning" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=e-cigarette with a fixed text, namely 'E-Cigarette Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "e-cigarette" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electrical with a fixed text, namely 'Electrical Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "electrical" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electronics with a fixed text, namely 'Electronics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "electronics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=erotic with a fixed text, namely 'Erotic Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "erotic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fabric with a fixed text, namely 'Fabric Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "fabric" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=farm with a fixed text, namely 'Produce Stand' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "farm" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fashion_accessories with a fixed text, namely 'Fashion Accessories Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "fashion_accessories" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fireplace with a fixed text, namely 'Fireplace Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "fireplace" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fishing with a fixed text, namely 'Fishing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "fishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=flooring with a fixed text, namely 'Flooring Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "flooring" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=florist with a fixed text, namely 'Florist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "florist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frame with a fixed text, namely 'Framing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "frame" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frozen_food with a fixed text, namely 'Frozen Food Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "frozen_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fuel with a fixed text, namely 'Fuel Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "fuel" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=funeral_directors with a fixed text, namely 'Funeral Home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "funeral_directors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=furniture with a fixed text, namely 'Furniture Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "furniture" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=games with a fixed text, namely 'Tabletop Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=garden_centre with a fixed text, namely 'Garden Center' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "garden_centre" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gas with a fixed text, namely 'Bottled Gas Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "gas" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=general with a fixed text, namely 'General Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "general" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gift with a fixed text, namely 'Gift Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "gift" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=greengrocer with a fixed text, namely 'Greengrocer' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "greengrocer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser with a fixed text, namely 'Hairdresser' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "hairdresser" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser_supply with a fixed text, namely 'Hairdresser Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "hairdresser_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hardware with a fixed text, namely 'Hardware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "hardware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=health_food with a fixed text, namely 'Health Food Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "health_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hearing_aids with a fixed text, namely 'Hearing Aids Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "hearing_aids" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=herbalist with a fixed text, namely 'Herbalist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "herbalist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hifi with a fixed text, namely 'Hifi Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "hifi" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hobby with a fixed text, namely 'Hobby Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "hobby" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=household_linen with a fixed text, namely 'Household Linen Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "household_linen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=houseware with a fixed text, namely 'Houseware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "houseware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hunting with a fixed text, namely 'Hunting Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "hunting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=interior_decoration with a fixed text, namely 'Interior Decoration Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "interior_decoration" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=jewelry with a fixed text, namely 'Jewelry Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "jewelry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kiosk with a fixed text, namely 'Kiosk' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "kiosk" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kitchen with a fixed text, namely 'Kitchen Design Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "kitchen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=laundry with a fixed text, namely 'Laundry' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "laundry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=leather with a fixed text, namely 'Leather Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "leather" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lighting with a fixed text, namely 'Lighting Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "lighting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=locksmith with a fixed text, namely 'Locksmith' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "locksmith" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lottery with a fixed text, namely 'Lottery Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "lottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mall with a fixed text, namely 'Mall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "mall" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=massage with a fixed text, namely 'Massage Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "massage" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=medical_supply with a fixed text, namely 'Medical Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "medical_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=military_surplus with a fixed text, namely 'Military Surplus Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "military_surplus" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mobile_phone with a fixed text, namely 'Mobile Phone Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "mobile_phone" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=model with a fixed text, namely 'Model Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "model" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=money_lender with a fixed text, namely 'Money Lender' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "money_lender" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle with a fixed text, namely 'Motorcycle Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "motorcycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle_repair with a fixed text, namely 'Motorcycle Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "motorcycle_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=music with a fixed text, namely 'Music Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "music" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=musical_instrument with a fixed text, namely 'Musical Instrument Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "musical_instrument" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=newsagent with a fixed text, namely 'Newspaper/Magazine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "newsagent" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=nutrition_supplements with a fixed text, namely 'Nutrition Supplements Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "nutrition_supplements" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=optician with a fixed text, namely 'Optician' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "optician" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outdoor with a fixed text, namely 'Outdoors Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "outdoor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outpost with a fixed text, namely 'Online Retailer Outpost' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "outpost" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=paint with a fixed text, namely 'Paint Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "paint" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=party with a fixed text, namely 'Party Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "party" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pastry with a fixed text, namely 'Pastry Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "pastry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pawnbroker with a fixed text, namely 'Pawn Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "pawnbroker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=perfumery with a fixed text, namely 'Perfume Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "perfumery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet with a fixed text, namely 'Pet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "pet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet_grooming with a fixed text, namely 'Pet Grooming Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "pet_grooming" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=photo with a fixed text, namely 'Photography Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "photo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pottery with a fixed text, namely 'Pottery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "pottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=printer_ink with a fixed text, namely 'Printer Ink Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "printer_ink" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=psychic with a fixed text, namely 'Psychic' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "psychic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pyrotechnics with a fixed text, namely 'Fireworks Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "pyrotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=radiotechnics with a fixed text, namely 'Radio/Electronic Component Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "radiotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=religion with a fixed text, namely 'Religious Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "religion" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=rental with a fixed text, namely 'Rental Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=repair with a fixed text, namely 'Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=scuba_diving with a fixed text, namely 'Scuba Diving Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "scuba_diving" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=seafood with a fixed text, namely 'Seafood Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "seafood" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=second_hand with a fixed text, namely 'Consignment/Thrift Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "second_hand" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sewing with a fixed text, namely 'Sewing Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "sewing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoe_repair with a fixed text, namely 'Shoe Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "shoe_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoes with a fixed text, namely 'Shoe Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "shoes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=spices with a fixed text, namely 'Spice Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "spices" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sports with a fixed text, namely 'Sporting Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=stationery with a fixed text, namely 'Stationery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "stationery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=storage_rental with a fixed text, namely 'Storage Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "storage_rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=supermarket with a fixed text, namely 'Supermarket' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "supermarket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=swimming_pool with a fixed text, namely 'Pool Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "swimming_pool" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tailor with a fixed text, namely 'Tailor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "tailor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tattoo with a fixed text, namely 'Tattoo Parlor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "tattoo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tea with a fixed text, namely 'Tea Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "tea" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=telecommunication with a fixed text, namely 'Telecom Retail Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "telecommunication" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=ticket with a fixed text, namely 'Ticket Seller' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "ticket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tiles with a fixed text, namely 'Tile Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "tiles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tobacco with a fixed text, namely 'Tobacco Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "tobacco" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tool_hire with a fixed text, namely 'Tool Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "tool_hire" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=toys with a fixed text, namely 'Toy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "toys" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trade with a fixed text, namely 'Trade Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "trade" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=travel_agency with a fixed text, namely 'Travel Agency' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "travel_agency" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trophy with a fixed text, namely 'Trophy Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "trophy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tyres with a fixed text, namely 'Tire Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "tyres" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=vacuum_cleaner with a fixed text, namely 'Vacuum Cleaner Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "vacuum_cleaner" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=variety_store with a fixed text, namely 'Variety Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "variety_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video with a fixed text, namely 'Video Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "video" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video_games with a fixed text, namely 'Video Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "video_games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=watches with a fixed text, namely 'Watches Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "watches" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water with a fixed text, namely 'Drinking Water Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "water" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water_sports with a fixed text, namely 'Watersport/Swim Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "water_sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=weapons with a fixed text, namely 'Weapon Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "weapons" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wholesale with a fixed text, namely 'Wholesale Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "wholesale" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wigs with a fixed text, namely 'Wig Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "wigs" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=window_blind with a fixed text, namely 'Window Blind Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "window_blind" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wine with a fixed text, namely 'Wine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'OnWheels')", - "value": "wine" - }, { "key": "opening_hours", "description": "Layer 'Shop' shows and asks freeform values for key 'opening_hours' (in the MapComplete.osm.be theme 'OnWheels')" @@ -2210,6 +1434,10 @@ "description": "The MapComplete theme OnWheels has a layer Toilets showing features with this tag", "value": "toilets" }, + { + "key": "id", + "description": "Layer 'Toilets' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Toilets 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" @@ -2444,6 +1672,10 @@ "description": "The MapComplete theme OnWheels has a layer Pharmacies showing features with this tag", "value": "pharmacy" }, + { + "key": "id", + "description": "Layer 'Pharmacies' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Pharmacies 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" @@ -2512,6 +1744,10 @@ "description": "The MapComplete theme OnWheels has a layer Doctors showing features with this tag", "value": "doctors" }, + { + "key": "id", + "description": "Layer 'Doctors' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Doctors 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" @@ -2603,6 +1839,10 @@ "description": "The MapComplete theme OnWheels has a layer Hospitals showing features with this tag", "value": "clinic" }, + { + "key": "id", + "description": "Layer 'Hospitals' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Hospitals' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'OnWheels')" @@ -2650,6 +1890,10 @@ "description": "The MapComplete theme OnWheels has a layer Reception desks showing features with this tag", "value": "reception_desk" }, + { + "key": "id", + "description": "Layer 'Reception desks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Reception desks 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" @@ -2714,6 +1958,10 @@ "description": "The MapComplete theme OnWheels has a layer Elevator showing features with this tag", "value": "elevator" }, + { + "key": "id", + "description": "Layer 'Elevator' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Elevator 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" @@ -2806,6 +2054,10 @@ "description": "The MapComplete theme OnWheels has a layer Hotels showing features with this tag", "value": "hotel" }, + { + "key": "id", + "description": "Layer 'Hotels' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" @@ -2924,6 +2176,10 @@ "description": "The MapComplete theme OnWheels has a layer governments showing features with this tag", "value": "government" }, + { + "key": "id", + "description": "Layer 'governments' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OnWheels') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'governments 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" diff --git a/Docs/TagInfo/mapcomplete_openwindpowermap.json b/Docs/TagInfo/mapcomplete_openwindpowermap.json index 054e2fd45..bff08f0f5 100644 --- a/Docs/TagInfo/mapcomplete_openwindpowermap.json +++ b/Docs/TagInfo/mapcomplete_openwindpowermap.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme OpenWindPowerMap has a layer wind turbine showing features with this tag", "value": "wind" }, + { + "key": "id", + "description": "Layer 'wind turbine' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'OpenWindPowerMap') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "generator:output:electricity", "description": "Layer 'wind turbine' shows and asks freeform values for key 'generator:output:electricity' (in the MapComplete.osm.be theme 'OpenWindPowerMap')" diff --git a/Docs/TagInfo/mapcomplete_parkings.json b/Docs/TagInfo/mapcomplete_parkings.json index 070da12dd..6de8785b5 100644 --- a/Docs/TagInfo/mapcomplete_parkings.json +++ b/Docs/TagInfo/mapcomplete_parkings.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Parking has a layer Parking showing features with this tag", "value": "parking" }, + { + "key": "id", + "description": "Layer 'Parking' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Parking') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parking 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" @@ -138,6 +142,10 @@ "description": "The MapComplete theme Parking has a layer Parking Spaces showing features with this tag", "value": "parking_space" }, + { + "key": "id", + "description": "Layer 'Parking Spaces' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Parking') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parking Spaces 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" @@ -244,6 +252,10 @@ "description": "The MapComplete theme Parking has a layer Parking Ticket Machines showing features with this tag", "value": "parking_tickets" }, + { + "key": "id", + "description": "Layer 'Parking Ticket Machines' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Parking') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parking Ticket Machines 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" diff --git a/Docs/TagInfo/mapcomplete_personal.json b/Docs/TagInfo/mapcomplete_personal.json index 157790331..2a4cf508b 100644 --- a/Docs/TagInfo/mapcomplete_personal.json +++ b/Docs/TagInfo/mapcomplete_personal.json @@ -14,6 +14,10 @@ "key": "advertising", "description": "The MapComplete theme Personal theme has a layer Advertise showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Advertise' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Advertise 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" @@ -222,6 +226,10 @@ "description": "The MapComplete theme Personal theme has a layer Map of ambulance stations showing features with this tag", "value": "ambulance_station" }, + { + "key": "id", + "description": "Layer 'Map of ambulance stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Map of ambulance stations' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" @@ -283,6 +291,10 @@ "description": "The MapComplete theme Personal theme has a layer Artworks showing features with this tag", "value": "artwork" }, + { + "key": "id", + "description": "Layer 'Artworks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Artworks allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" @@ -407,160 +419,15 @@ "description": "Layer 'Artworks' shows with a fixed text, namely 'This artwork does not serve as a bench' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') Picking this answer will delete the key amenity.", "value": "" }, - { - "key": "backrest", - "description": "Layer 'Artworks' shows backrest=yes&two_sided=yes with a fixed text, namely 'This bench is two-sided and shares the backrest' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "yes" - }, - { - "key": "two_sided", - "description": "Layer 'Artworks' shows backrest=yes&two_sided=yes with a fixed text, namely 'This bench is two-sided and shares the backrest' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "yes" - }, - { - "key": "backrest", - "description": "Layer 'Artworks' shows backrest=yes with a fixed text, namely 'Does have a backrest' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "yes" - }, - { - "key": "backrest", - "description": "Layer 'Artworks' shows backrest=no with a fixed text, namely 'Does not have a backrest' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "no" - }, - { - "key": "seats", - "description": "Layer 'Artworks' shows and asks freeform values for key 'seats' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)" - }, - { - "key": "seats:separated", - "description": "Layer 'Artworks' shows seats:separated=no with a fixed text, namely 'This bench does not have separated seats' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "no" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows and asks freeform values for key 'material' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=wood with a fixed text, namely 'The seating is made from wood' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "wood" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=metal with a fixed text, namely 'The seating is made from metal' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "metal" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=stone with a fixed text, namely 'The seating is made from stone' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "stone" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=concrete with a fixed text, namely 'The seating is made from concrete' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "concrete" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=plastic with a fixed text, namely 'The seating is made from plastic' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "plastic" - }, - { - "key": "material", - "description": "Layer 'Artworks' shows material=steel with a fixed text, namely 'The seating is made from steel' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "steel" - }, - { - "key": "direction", - "description": "Layer 'Artworks' shows and asks freeform values for key 'direction' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows and asks freeform values for key 'colour' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=brown with a fixed text, namely 'Colour: brown' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "brown" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=green with a fixed text, namely 'Colour: green' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "green" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=gray with a fixed text, namely 'Colour: gray' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "gray" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=white with a fixed text, namely 'Colour: white' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "white" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=red with a fixed text, namely 'Colour: red' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "red" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=black with a fixed text, namely 'Colour: black' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "black" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=blue with a fixed text, namely 'Colour: blue' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "blue" - }, - { - "key": "colour", - "description": "Layer 'Artworks' shows colour=yellow with a fixed text, namely 'Colour: yellow' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "yellow" - }, - { - "key": "survey:date", - "description": "Layer 'Artworks' shows and asks freeform values for key 'survey:date' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)" - }, - { - "key": "survey:date", - "description": "Layer 'Artworks' shows survey:date= with a fixed text, namely 'Surveyed today!' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') Picking this answer will delete the key survey:date. (This is only shown if amenity=bench)", - "value": "" - }, - { - "key": "inscription", - "description": "Layer 'Artworks' shows and asks freeform values for key 'inscription' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)" - }, - { - "key": "not:inscription", - "description": "Layer 'Artworks' shows not:inscription=yes with a fixed text, namely 'This bench does not have an inscription' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "yes" - }, - { - "key": "inscription", - "description": "Layer 'Artworks' shows with a fixed text, namely 'This bench does (probably) not have an inscription' (in the MapComplete.osm.be theme 'Personal theme') Picking this answer will delete the key inscription. (This is only shown if amenity=bench)", - "value": "" - }, - { - "key": "historic", - "description": "Layer 'Artworks' shows historic=memorial with a fixed text, namely 'This bench is a memorial for someone or something' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "memorial" - }, - { - "key": "historic", - "description": "Layer 'Artworks' shows not:historic=memorial with a fixed text, namely 'This bench is a not a memorial for someone or something' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') Picking this answer will delete the key historic. (This is only shown if amenity=bench)", - "value": "" - }, - { - "key": "not:historic", - "description": "Layer 'Artworks' shows not:historic=memorial with a fixed text, namely 'This bench is a not a memorial for someone or something' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=bench)", - "value": "memorial" - }, { "key": "amenity", "description": "The MapComplete theme Personal theme has a layer ATMs showing features with this tag", "value": "atm" }, + { + "key": "id", + "description": "Layer 'ATMs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'ATMs 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" @@ -669,6 +536,10 @@ "description": "The MapComplete theme Personal theme has a layer Banks showing features with this tag", "value": "bank" }, + { + "key": "id", + "description": "Layer 'Banks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "atm", "description": "Layer 'Banks' shows atm=yes with a fixed text, namely 'This bank has an ATM' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", @@ -694,6 +565,10 @@ "description": "The MapComplete theme Personal theme has a layer Barriers showing features with this tag", "value": "cycle_barrier" }, + { + "key": "id", + "description": "Layer 'Barriers' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Barriers 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" @@ -796,6 +671,10 @@ "description": "The MapComplete theme Personal theme has a layer Benches showing features with this tag", "value": "bench" }, + { + "key": "id", + "description": "Layer 'Benches' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Benches 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" @@ -971,91 +850,6 @@ "description": "Layer 'Benches' shows not:historic=memorial with a fixed text, namely 'This bench is a not a memorial for someone or something' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if historic=memorial|inscription~.+|memorial=bench|tourism=artwork)", "value": "memorial" }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows and asks freeform values for key 'artwork_type' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=architecture with a fixed text, namely 'Architecture' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "architecture" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=mural with a fixed text, namely 'Mural' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "mural" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=painting with a fixed text, namely 'Painting' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "painting" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=sculpture with a fixed text, namely 'Sculpture' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "sculpture" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=statue with a fixed text, namely 'Statue' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "statue" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=bust with a fixed text, namely 'Bust' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "bust" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=stone with a fixed text, namely 'Stone' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "stone" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=installation with a fixed text, namely 'Installation' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "installation" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=graffiti with a fixed text, namely 'Graffiti' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "graffiti" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=relief with a fixed text, namely 'Relief' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "relief" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=azulejo with a fixed text, namely 'Azulejo (Spanish decorative tilework)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "azulejo" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=tilework with a fixed text, namely 'Tilework' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "tilework" - }, - { - "key": "artwork_type", - "description": "Layer 'Benches' shows artwork_type=woodcarving with a fixed text, namely 'Woodcarving' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)", - "value": "woodcarving" - }, - { - "key": "artist:wikidata", - "description": "Layer 'Benches' shows and asks freeform values for key 'artist:wikidata' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)" - }, - { - "key": "artist_name", - "description": "Layer 'Benches' shows and asks freeform values for key 'artist_name' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)" - }, - { - "key": "website", - "description": "Layer 'Benches' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)" - }, - { - "key": "subject:wikidata", - "description": "Layer 'Benches' shows and asks freeform values for key 'subject:wikidata' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if tourism=artwork)" - }, { "key": "highway", "description": "The MapComplete theme Personal theme has a layer Benches at public transport stops showing features with this tag", @@ -1071,6 +865,10 @@ "description": "The MapComplete theme Personal theme has a layer Benches at public transport stops showing features with this tag", "value": "stand_up_bench" }, + { + "key": "id", + "description": "Layer 'Benches at public transport stops' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Benches at public transport stops 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" @@ -1111,6 +909,10 @@ "description": "The MapComplete theme Personal theme has a layer Bicycle library showing features with this tag", "value": "bicycle_library" }, + { + "key": "id", + "description": "Layer 'Bicycle library' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle library 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" @@ -1220,6 +1022,10 @@ "key": "rental", "description": "The MapComplete theme Personal theme has a layer Bicycle rental showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Bicycle rental' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle rental 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" @@ -1425,6 +1231,10 @@ "key": "vending", "description": "The MapComplete theme Personal theme has a layer Bicycle tube vending machine showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Bicycle tube vending machine' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle tube vending machine 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" @@ -1572,6 +1382,10 @@ "description": "The MapComplete theme Personal theme has a layer Bike cafe showing features with this tag", "value": "bicycle" }, + { + "key": "id", + "description": "Layer 'Bike cafe' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike cafe 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" @@ -1670,6 +1484,10 @@ "description": "The MapComplete theme Personal theme has a layer Bike cleaning service showing features with this tag", "value": "bike_wash" }, + { + "key": "id", + "description": "Layer 'Bike cleaning service' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike cleaning service 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" @@ -1724,6 +1542,10 @@ "description": "The MapComplete theme Personal theme has a layer Bike parking showing features with this tag", "value": "bicycle_parking" }, + { + "key": "id", + "description": "Layer 'Bike parking' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike parking 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" @@ -1861,6 +1683,10 @@ "description": "The MapComplete theme Personal theme has a layer Bicycle pump and repair showing features with this tag", "value": "bicycle_repair_station" }, + { + "key": "id", + "description": "Layer 'Bicycle pump and repair' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bicycle pump and repair 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" @@ -2081,6 +1907,10 @@ "description": "The MapComplete theme Personal theme has a layer Bike repair/shop showing features with this tag", "value": "" }, + { + "key": "id", + "description": "Layer 'Bike repair/shop' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike repair/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" @@ -2178,78 +2008,6 @@ "description": "Layer 'Bike repair/shop' shows service:bicycle:rental=no with a fixed text, namely 'This shop doesn't rent out bikes' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "no" }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'rental' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if service:bicycle:rental=yes)" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=city_bike with a fixed text, namely 'Normal city bikes can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if service:bicycle:rental=yes)", - "value": "city_bike" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=ebike with a fixed text, namely 'Electrical bikes can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if service:bicycle:rental=yes)", - "value": "ebike" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=bmx with a fixed text, namely 'BMX bikes can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if service:bicycle:rental=yes)", - "value": "bmx" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=mtb with a fixed text, namely 'Mountainbikes can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if service:bicycle:rental=yes)", - "value": "mtb" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=kid_bike with a fixed text, namely 'Bikes for children can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if service:bicycle:rental=yes)", - "value": "kid_bike" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=tandem with a fixed text, namely 'Tandem bicycles can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if service:bicycle:rental=yes)", - "value": "tandem" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=racebike with a fixed text, namely 'Race bicycles can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if service:bicycle:rental=yes)", - "value": "racebike" - }, - { - "key": "rental", - "description": "Layer 'Bike repair/shop' shows rental=bike_helmet with a fixed text, namely 'Bike helmets can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if service:bicycle:rental=yes)", - "value": "bike_helmet" - }, - { - "key": "capacity:city_bike", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:city_bike' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if rental~^(.*city_bike.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:ebike", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:ebike' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if rental~^(.*ebike.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:kid_bike", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:kid_bike' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if rental~^(.*kid_bike.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:bmx", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:bmx' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if rental~^(.*bmx.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:mtb", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:mtb' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if rental~^(.*mtb.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:bicycle_pannier", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:bicycle_pannier' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if rental~^(.*bicycle_pannier.*)$&service:bicycle:rental=yes)" - }, - { - "key": "capacity:tandem_bicycle", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'capacity:tandem_bicycle' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if rental~^(.*tandem_bicycle.*)$&service:bicycle:rental=yes)" - }, { "key": "service:bicycle:second_hand", "description": "Layer 'Bike repair/shop' shows service:bicycle:second_hand=yes with a fixed text, namely 'This shop sells second-hand bikes' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", @@ -2310,25 +2068,6 @@ "description": "Layer 'Bike repair/shop' shows service:bicycle:cleaning=no with a fixed text, namely 'This shop doesn't offer bicycle cleaning' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "no" }, - { - "key": "service:bicycle:cleaning:charge", - "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'service:bicycle:cleaning:charge' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity!=bike_wash&amenity!=bicycle_wash)" - }, - { - "key": "service:bicycle:cleaning:fee", - "description": "Layer 'Bike repair/shop' shows service:bicycle:cleaning:fee=no with a fixed text, namely 'The cleaning service is free to use' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity!=bike_wash&amenity!=bicycle_wash)", - "value": "no" - }, - { - "key": "service:bicycle:cleaning:fee", - "description": "Layer 'Bike repair/shop' shows service:bicycle:cleaning:fee=yes with a fixed text, namely 'Free to use' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity!=bike_wash&amenity!=bicycle_wash)", - "value": "yes" - }, - { - "key": "service:bicycle:cleaning:charge", - "description": "Layer 'Bike repair/shop' shows service:bicycle:cleaning:fee=yes with a fixed text, namely 'Free to use' (in the MapComplete.osm.be theme 'Personal theme') Picking this answer will delete the key service:bicycle:cleaning:charge. (This is only shown if amenity!=bike_wash&amenity!=bicycle_wash)", - "value": "" - }, { "key": "description", "description": "Layer 'Bike repair/shop' shows and asks freeform values for key 'description' (in the MapComplete.osm.be theme 'Personal theme')" @@ -2378,6 +2117,10 @@ "description": "The MapComplete theme Personal theme has a layer Bike-related object showing features with this tag", "value": "cycling" }, + { + "key": "id", + "description": "Layer 'Bike-related object' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike-related object 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" @@ -2431,6 +2174,10 @@ "description": "The MapComplete theme Personal theme has a layer Binoculars showing features with this tag", "value": "binoculars" }, + { + "key": "id", + "description": "Layer 'Binoculars' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Binoculars 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" @@ -2470,6 +2217,10 @@ "description": "The MapComplete theme Personal theme has a layer Bird watching places showing features with this tag", "value": "bird_hide" }, + { + "key": "id", + "description": "Layer 'Bird watching places' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bird watching places 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" @@ -2600,6 +2351,10 @@ "description": "The MapComplete theme Personal theme has a layer Cafés and pubs showing features with this tag", "value": "nightclub" }, + { + "key": "id", + "description": "Layer 'Cafés and pubs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Cafés and pubs 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" @@ -2866,6 +2621,10 @@ "description": "The MapComplete theme Personal theme has a layer Charging stations showing features with this tag", "value": "charging_station" }, + { + "key": "id", + "description": "Layer 'Charging stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Charging stations 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" @@ -4114,6 +3873,10 @@ "description": "The MapComplete theme Personal theme has a layer Climbing opportunities showing features with this tag", "value": "climbing" }, + { + "key": "id", + "description": "Layer 'Climbing opportunities' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Climbing opportunities 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" @@ -4168,48 +3931,6 @@ "description": "Layer 'Climbing opportunities' shows rock=limestone with a fixed text, namely 'Limestone' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if climbing=crag|natural=cliff|natural=bare_rock)", "value": "limestone" }, - { - "key": "url", - "description": "Layer 'Climbing opportunities' shows and asks freeform values for key 'url' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if leisure!~^(sports_centre)$&sport=climbing)" - }, - { - "key": "charge", - "description": "Layer 'Climbing opportunities' shows and asks freeform values for key 'charge' (in the MapComplete.osm.be theme 'Personal theme')" - }, - { - "key": "fee", - "description": "Layer 'Climbing opportunities' shows fee=no with a fixed text, namely 'Climbing here is free of charge' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "no" - }, - { - "key": "fee", - "description": "Layer 'Climbing opportunities' shows fee=yes with a fixed text, namely 'Paying a fee is required to climb here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "yes" - }, - { - "key": "charge", - "description": "Layer 'Climbing opportunities' shows fee=yes with a fixed text, namely 'Paying a fee is required to climb here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') Picking this answer will delete the key charge.", - "value": "" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing opportunities' shows climbing:boulder=yes with a fixed text, namely 'Bouldering is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "yes" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing opportunities' shows climbing:boulder=no with a fixed text, namely 'Bouldering is not possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "no" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing opportunities' shows climbing:boulder=limited with a fixed text, namely 'Bouldering is possible, allthough there are only a few routes' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "limited" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing opportunities' shows climbing:boulder~.+ with a fixed text, namely 'There are {climbing:boulder} boulder routes' (in the MapComplete.osm.be theme 'Personal theme')" - }, { "key": "club", "description": "The MapComplete theme Personal theme has a layer Climbing club showing features with this tag", @@ -4228,6 +3949,10 @@ "key": "club", "description": "The MapComplete theme Personal theme has a layer Climbing club showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Climbing club' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Climbing club' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" @@ -4270,6 +3995,10 @@ "description": "The MapComplete theme Personal theme has a layer Climbing gyms showing features with this tag", "value": "sports_centre" }, + { + "key": "id", + "description": "Layer 'Climbing gyms' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Climbing gyms 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" @@ -4315,23 +4044,19 @@ "description": "Layer 'Climbing gyms' shows contact:email~.+ with a fixed text, namely '{contact:email}' (in the MapComplete.osm.be theme 'Personal theme')" }, { - "key": "charge", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'charge' (in the MapComplete.osm.be theme 'Personal theme')" - }, - { - "key": "fee", - "description": "Layer 'Climbing gyms' shows fee=no with a fixed text, namely 'Climbing here is free of charge' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "no" - }, - { - "key": "fee", - "description": "Layer 'Climbing gyms' shows fee=yes with a fixed text, namely 'Paying a fee is required to climb here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "key": "payment:cash", + "description": "Layer 'Climbing gyms' shows payment:cash=yes with a fixed text, namely 'Cash is accepted here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "yes" }, { - "key": "charge", - "description": "Layer 'Climbing gyms' shows fee=yes with a fixed text, namely 'Paying a fee is required to climb here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') Picking this answer will delete the key charge.", - "value": "" + "key": "payment:cards", + "description": "Layer 'Climbing gyms' shows payment:cards=yes with a fixed text, namely 'Payment cards are accepted here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "value": "yes" + }, + { + "key": "payment:qr_code", + "description": "Layer 'Climbing gyms' 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.osm.be theme 'Personal theme')", + "value": "yes" }, { "key": "opening_hours", @@ -4358,68 +4083,15 @@ "value": "no" }, { - "key": "climbing:toprope", - "description": "Layer 'Climbing gyms' shows climbing:toprope=yes with a fixed text, namely 'Toprope climbing is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "key": "service:rental:climbing_rope", + "description": "Layer 'Climbing gyms' shows service:rental:climbing_rope=yes with a fixed text, namely 'A climbing rope can be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "yes" }, { - "key": "climbing:toprope", - "description": "Layer 'Climbing gyms' shows climbing:toprope=no with a fixed text, namely 'Toprope climbing is not possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "key": "service:rental:climbing_rope", + "description": "Layer 'Climbing gyms' shows service:rental:climbing_rope=no with a fixed text, namely 'A climbing rope can not be rented here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", "value": "no" }, - { - "key": "climbing:toprope", - "description": "Layer 'Climbing gyms' shows climbing:toprope~.+ with a fixed text, namely 'There are {climbing:toprope} toprope routes' (in the MapComplete.osm.be theme 'Personal theme')" - }, - { - "key": "climbing:length", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'climbing:length' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if climbing:toprope!=no)" - }, - { - "key": "climbing:grade:french:min", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'climbing:grade:french:min' (in the MapComplete.osm.be theme 'Personal theme')" - }, - { - "key": "climbing:grade:french:max", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'climbing:grade:french:max' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if climbing!~^(route)$&climbing:sport=yes|sport=climbing)" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing gyms' shows climbing:boulder=yes with a fixed text, namely 'Bouldering is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "yes" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing gyms' shows climbing:boulder=no with a fixed text, namely 'Bouldering is not possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "no" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing gyms' shows climbing:boulder=limited with a fixed text, namely 'Bouldering is possible, allthough there are only a few routes' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "limited" - }, - { - "key": "climbing:boulder", - "description": "Layer 'Climbing gyms' shows climbing:boulder~.+ with a fixed text, namely 'There are {climbing:boulder} boulder routes' (in the MapComplete.osm.be theme 'Personal theme')" - }, - { - "key": "climbing:sport", - "description": "Layer 'Climbing gyms' shows climbing:sport=yes with a fixed text, namely 'Sport climbing is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "yes" - }, - { - "key": "climbing:sport", - "description": "Layer 'Climbing gyms' shows climbing:sport=no with a fixed text, namely 'Sport climbing is not possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "no" - }, - { - "key": "climbing:sport", - "description": "Layer 'Climbing gyms' shows climbing:sport~.+ with a fixed text, namely 'There are {climbing:sport} sport climbing routes' (in the MapComplete.osm.be theme 'Personal theme')" - }, - { - "key": "climbing:bolts:max", - "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'climbing:bolts:max' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if climbing:sport=yes)" - }, { "key": "climbing:speed", "description": "Layer 'Climbing gyms' shows climbing:speed=yes with a fixed text, namely 'There is a speed climbing wall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", @@ -4434,6 +4106,55 @@ "key": "climbing:speed", "description": "Layer 'Climbing gyms' shows climbing:speed~.+ with a fixed text, namely 'There are {climbing:speed} speed climbing walls' (in the MapComplete.osm.be theme 'Personal theme')" }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=wlan with a fixed text, namely 'This place offers wireless internet access' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "value": "wlan" + }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=no with a fixed text, namely 'This place does not offer internet access' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "value": "no" + }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=yes with a fixed text, namely 'This place offers internet access' (in the MapComplete.osm.be theme 'Personal theme')", + "value": "yes" + }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=terminal with a fixed text, namely 'This place offers internet access via a terminal or computer' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "value": "terminal" + }, + { + "key": "internet_access", + "description": "Layer 'Climbing gyms' shows internet_access=wired with a fixed text, namely 'This place offers wired internet access' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "value": "wired" + }, + { + "key": "internet_access:fee", + "description": "Layer 'Climbing gyms' shows internet_access:fee=yes with a fixed text, namely 'There is a fee for the internet access at this place' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if internet_access!=no&internet_access~.+)", + "value": "yes" + }, + { + "key": "internet_access:fee", + "description": "Layer 'Climbing gyms' shows internet_access:fee=no with a fixed text, namely 'Internet access is free at this place' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if internet_access!=no&internet_access~.+)", + "value": "no" + }, + { + "key": "internet_access:fee", + "description": "Layer 'Climbing gyms' shows internet_access:fee=customers with a fixed text, namely 'Internet access is free at this place, for customers only' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if internet_access!=no&internet_access~.+)", + "value": "customers" + }, + { + "key": "internet_access:ssid", + "description": "Layer 'Climbing gyms' shows and asks freeform values for key 'internet_access:ssid' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if internet_access=wlan)" + }, + { + "key": "internet_access:ssid", + "description": "Layer 'Climbing gyms' shows internet_access:ssid=Telekom with a fixed text, namely 'Telekom' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if internet_access=wlan)", + "value": "Telekom" + }, { "key": "leisure", "description": "The MapComplete theme Personal theme has a layer Climbing opportunities? showing features with this tag", @@ -4469,6 +4190,10 @@ "description": "The MapComplete theme Personal theme has a layer Climbing opportunities? showing features with this tag", "value": "" }, + { + "key": "id", + "description": "Layer 'Climbing opportunities?' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "sport", "description": "Layer 'Climbing opportunities?' shows sport=climbing with a fixed text, namely 'Climbing is possible here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", @@ -4484,6 +4209,10 @@ "description": "The MapComplete theme Personal theme has a layer Climbing routes showing features with this tag", "value": "route" }, + { + "key": "id", + "description": "Layer 'Climbing routes' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Climbing routes 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" @@ -4540,6 +4269,10 @@ "description": "The MapComplete theme Personal theme has a layer Clocks showing features with this tag", "value": "clock" }, + { + "key": "id", + "description": "Layer 'Clocks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Clocks 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" @@ -4700,6 +4433,10 @@ "description": "The MapComplete theme Personal theme has a layer Crossings showing features with this tag", "value": "crossing" }, + { + "key": "id", + "description": "Layer 'Crossings' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Crossings 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" @@ -4966,6 +4703,10 @@ "description": "The MapComplete theme Personal theme has a layer Cycleways and roads showing features with this tag", "value": "designated" }, + { + "key": "id", + "description": "Layer 'Cycleways and roads' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "cycleway", "description": "Layer 'Cycleways and roads' shows cycleway=shared_lane with a fixed text, namely 'There is a shared lane' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if highway!=cycleway&highway!=path&highway!=footway)", @@ -5429,6 +5170,10 @@ "description": "The MapComplete theme Personal theme has a layer Defibrillators showing features with this tag", "value": "defibrillator" }, + { + "key": "id", + "description": "Layer 'Defibrillators' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Defibrillators 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" @@ -5592,6 +5337,10 @@ "description": "The MapComplete theme Personal theme has a layer Dentist showing features with this tag", "value": "dentist" }, + { + "key": "id", + "description": "Layer 'Dentist' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Dentist 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" @@ -5640,11 +5389,27 @@ "key": "name", "description": "Layer 'Dentist' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" }, + { + "key": "camera:direction", + "description": "The MapComplete theme Personal theme has a layer Direction visualization showing features with this tag" + }, + { + "key": "direction", + "description": "The MapComplete theme Personal theme has a layer Direction visualization showing features with this tag" + }, + { + "key": "id", + "description": "Layer 'Direction visualization' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "amenity", "description": "The MapComplete theme Personal theme has a layer Doctors showing features with this tag", "value": "doctors" }, + { + "key": "id", + "description": "Layer 'Doctors' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Doctors 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" @@ -5741,6 +5506,10 @@ "description": "The MapComplete theme Personal theme has a layer dog parks showing features with this tag", "value": "unleashed" }, + { + "key": "id", + "description": "Layer 'dog parks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "barrier", "description": "Layer 'dog parks' shows barrier=fence with a fixed text, namely 'This dogpark is fenced all around' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", @@ -5791,6 +5560,10 @@ "description": "The MapComplete theme Personal theme has a layer Drinking water showing features with this tag", "value": "yes" }, + { + "key": "id", + "description": "Layer 'Drinking water' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Drinking water 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" @@ -5841,6 +5614,10 @@ "description": "The MapComplete theme Personal theme has a layer Elevator showing features with this tag", "value": "elevator" }, + { + "key": "id", + "description": "Layer 'Elevator' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Elevator 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" @@ -5941,6 +5718,10 @@ "key": "door", "description": "The MapComplete theme Personal theme has a layer Entrance showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Entrance' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Entrance 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" @@ -6167,6 +5948,10 @@ "key": "name:etymology", "description": "The MapComplete theme Personal theme has a layer Has etymology showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Has etymology' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Has etymology shows images based on the keys image, image:0, image:1,... and wikidata, wikipedia, wikimedia_commons and mapillary" @@ -6217,6 +6002,10 @@ "description": "The MapComplete theme Personal theme has a layer Map of fire extinguishers showing features with this tag", "value": "fire_extinguisher" }, + { + "key": "id", + "description": "Layer 'Map of fire extinguishers' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "location", "description": "Layer 'Map of fire extinguishers' shows and asks freeform values for key 'location' (in the MapComplete.osm.be theme 'Personal theme')" @@ -6252,6 +6041,10 @@ "description": "The MapComplete theme Personal theme has a layer Map of fire stations showing features with this tag", "value": "fire_station" }, + { + "key": "id", + "description": "Layer 'Map of fire stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Map of fire stations' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" @@ -6323,6 +6116,10 @@ "description": "The MapComplete theme Personal theme has a layer Fitness Centres showing features with this tag", "value": "fitness_centre" }, + { + "key": "id", + "description": "Layer 'Fitness Centres' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Fitness Centres' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" @@ -6430,6 +6227,10 @@ "description": "The MapComplete theme Personal theme has a layer Fitness Stations showing features with this tag", "value": "fitness_station" }, + { + "key": "id", + "description": "Layer 'Fitness Stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Fitness Stations 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" @@ -6601,6 +6402,10 @@ "key": "FIXME", "description": "The MapComplete theme Personal theme has a layer OSM objects with FIXME tags showing features with this tag" }, + { + "key": "id", + "description": "Layer 'OSM objects with FIXME tags' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "amenity", "description": "The MapComplete theme Personal theme has a layer Restaurants and fast food showing features with this tag", @@ -6611,6 +6416,10 @@ "description": "The MapComplete theme Personal theme has a layer Restaurants and fast food showing features with this tag", "value": "restaurant" }, + { + "key": "id", + "description": "Layer 'Restaurants and fast food' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "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" @@ -7096,6 +6905,10 @@ "description": "The MapComplete theme Personal theme has a layer Ghost bikes showing features with this tag", "value": "ghost_bike" }, + { + "key": "id", + "description": "Layer 'Ghost bikes' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Ghost bikes 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" @@ -7138,6 +6951,10 @@ "description": "The MapComplete theme Personal theme has a layer governments showing features with this tag", "value": "government" }, + { + "key": "id", + "description": "Layer 'governments' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'governments 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" @@ -7187,6 +7004,10 @@ "description": "The MapComplete theme Personal theme has a layer Hackerspace showing features with this tag", "value": "hackerspace" }, + { + "key": "id", + "description": "Layer 'Hackerspace' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Hackerspace 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" @@ -7353,6 +7174,10 @@ "description": "The MapComplete theme Personal theme has a layer Hospitals showing features with this tag", "value": "clinic" }, + { + "key": "id", + "description": "Layer 'Hospitals' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Hospitals' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" @@ -7400,6 +7225,10 @@ "description": "The MapComplete theme Personal theme has a layer Hotels showing features with this tag", "value": "hotel" }, + { + "key": "id", + "description": "Layer 'Hotels' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Hotels allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" @@ -7518,6 +7347,10 @@ "description": "The MapComplete theme Personal theme has a layer Map of hydrants showing features with this tag", "value": "fire_hydrant" }, + { + "key": "id", + "description": "Layer 'Map of hydrants' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "colour", "description": "Layer 'Map of hydrants' shows and asks freeform values for key 'colour' (in the MapComplete.osm.be theme 'Personal theme')" @@ -7653,6 +7486,10 @@ "description": "The MapComplete theme Personal theme has a layer Indoors showing features with this tag", "value": "level" }, + { + "key": "id", + "description": "Layer 'Indoors' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "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" @@ -7682,6 +7519,10 @@ "description": "The MapComplete theme Personal theme has a layer Information boards showing features with this tag", "value": "board" }, + { + "key": "id", + "description": "Layer 'Information boards' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Information boards 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" @@ -7703,6 +7544,10 @@ "description": "The MapComplete theme Personal theme has a layer Kerbs showing features with this tag", "value": "kerb" }, + { + "key": "id", + "description": "Layer 'Kerbs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Kerbs 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" @@ -7783,6 +7628,10 @@ "description": "The MapComplete theme Personal theme has a layer Kindergartens and childcare showing features with this tag", "value": "early_childhood" }, + { + "key": "id", + "description": "Layer 'Kindergartens and childcare' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "amenity", "description": "Layer 'Kindergartens and childcare' shows amenity=kindergarten with a fixed text, namely 'This is a kindergarten (also known as preschool) where small kids receive early education.' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", @@ -7839,6 +7688,10 @@ "description": "The MapComplete theme Personal theme has a layer Maps showing features with this tag", "value": "map" }, + { + "key": "id", + "description": "Layer 'Maps' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Maps 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" @@ -7964,6 +7817,10 @@ "description": "The MapComplete theme Personal theme has a layer Maxspeed showing features with this tag", "value": "motorway_link" }, + { + "key": "id", + "description": "Layer 'Maxspeed' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "maxspeed", "description": "Layer 'Maxspeed' shows and asks freeform values for key 'maxspeed' (in the MapComplete.osm.be theme 'Personal theme')" @@ -7988,6 +7845,10 @@ "description": "The MapComplete theme Personal theme has a layer Nature reserve showing features with this tag", "value": "protected_area" }, + { + "key": "id", + "description": "Layer 'Nature reserve' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Nature reserve 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" @@ -8161,6 +8022,10 @@ "description": "The MapComplete theme Personal theme has a layer Observation towers showing features with this tag", "value": "observation" }, + { + "key": "id", + "description": "Layer 'Observation towers' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Observation towers 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" @@ -8303,6 +8168,10 @@ "description": "The MapComplete theme Personal theme has a layer Parcel Lockers showing features with this tag", "value": "parcel_pickup;parcel_mail_in" }, + { + "key": "id", + "description": "Layer 'Parcel Lockers' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parcel Lockers 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" @@ -8385,6 +8254,10 @@ "description": "The MapComplete theme Personal theme has a layer Parking showing features with this tag", "value": "parking" }, + { + "key": "id", + "description": "Layer 'Parking' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parking 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" @@ -8508,6 +8381,10 @@ "description": "The MapComplete theme Personal theme has a layer Parking Spaces showing features with this tag", "value": "parking_space" }, + { + "key": "id", + "description": "Layer 'Parking Spaces' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parking Spaces 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" @@ -8614,6 +8491,10 @@ "description": "The MapComplete theme Personal theme has a layer Parking Ticket Machines showing features with this tag", "value": "parking_tickets" }, + { + "key": "id", + "description": "Layer 'Parking Ticket Machines' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parking Ticket Machines 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" @@ -8774,6 +8655,10 @@ "description": "The MapComplete theme Personal theme has a layer Pharmacies showing features with this tag", "value": "pharmacy" }, + { + "key": "id", + "description": "Layer 'Pharmacies' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Pharmacies 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" @@ -8842,6 +8727,10 @@ "description": "The MapComplete theme Personal theme has a layer Physiotherapist showing features with this tag", "value": "physiotherapist" }, + { + "key": "id", + "description": "Layer 'Physiotherapist' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Physiotherapist 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" @@ -8904,6 +8793,10 @@ "description": "The MapComplete theme Personal theme has a layer Picnic tables showing features with this tag", "value": "picnic_table" }, + { + "key": "id", + "description": "Layer 'Picnic tables' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Picnic tables 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" @@ -8973,6 +8866,10 @@ "description": "The MapComplete theme Personal theme has a layer Playgrounds showing features with this tag", "value": "playground" }, + { + "key": "id", + "description": "Layer 'Playgrounds' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Playgrounds 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" @@ -9135,6 +9032,10 @@ "description": "The MapComplete theme Personal theme has a layer Postboxes showing features with this tag", "value": "post_box" }, + { + "key": "id", + "description": "Layer 'Postboxes' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Postboxes 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" @@ -9161,6 +9062,10 @@ "description": "The MapComplete theme Personal theme has a layer Post offices showing features with this tag", "value": "post_partner" }, + { + "key": "id", + "description": "Layer 'Post offices' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Post offices 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" @@ -9310,6 +9215,10 @@ "description": "The MapComplete theme Personal theme has a layer Bookcases showing features with this tag", "value": "public_bookcase" }, + { + "key": "id", + "description": "Layer 'Bookcases' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bookcases 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" @@ -9438,11 +9347,30 @@ "key": "website", "description": "Layer 'Bookcases' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Personal theme')" }, + { + "key": "surface:colour", + "description": "The MapComplete theme Personal theme has a layer Crossings with rainbow paintings showing features with this tag", + "value": "rainbow" + }, { "key": "highway", "description": "The MapComplete theme Personal theme has a layer Crossings with rainbow paintings showing features with this tag", "value": "crossing" }, + { + "key": "highway", + "description": "The MapComplete theme Personal theme has a layer Crossings with rainbow paintings showing features with this tag", + "value": "footway" + }, + { + "key": "footway", + "description": "The MapComplete theme Personal theme has a layer Crossings with rainbow paintings showing features with this tag", + "value": "crossing" + }, + { + "key": "id", + "description": "Layer 'Crossings with rainbow paintings' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Crossings with rainbow paintings 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" @@ -9460,13 +9388,13 @@ "description": "The layer 'Crossings with rainbow paintings 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": "crossing:marking", - "description": "Layer 'Crossings with rainbow paintings' shows crossing:marking=rainbow with a fixed text, namely 'This crossing has rainbow paintings' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if highway=crossing)", + "key": "surface:colour", + "description": "Layer 'Crossings with rainbow paintings' shows surface:colour=rainbow with a fixed text, namely 'This crossing has rainbow paintings' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if footway=crossing)", "value": "rainbow" }, { - "key": "not:crossing:marking", - "description": "Layer 'Crossings with rainbow paintings' shows not:crossing:marking=rainbow with a fixed text, namely 'No rainbow paintings here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if highway=crossing)", + "key": "not:surface:colour", + "description": "Layer 'Crossings with rainbow paintings' shows not:surface:colour=rainbow with a fixed text, namely 'No rainbow paintings here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if footway=crossing)", "value": "rainbow" }, { @@ -9474,6 +9402,10 @@ "description": "The MapComplete theme Personal theme has a layer Reception desks showing features with this tag", "value": "reception_desk" }, + { + "key": "id", + "description": "Layer 'Reception desks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Reception desks 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" @@ -9538,6 +9470,10 @@ "description": "The MapComplete theme Personal theme has a layer Recycling showing features with this tag", "value": "recycling" }, + { + "key": "id", + "description": "Layer 'Recycling' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Recycling 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" @@ -9789,6 +9725,10 @@ "description": "The MapComplete theme Personal theme has a layer Primary and secondary schools showing features with this tag", "value": "school" }, + { + "key": "id", + "description": "Layer 'Primary and secondary schools' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Primary and secondary schools' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" @@ -9930,6 +9870,10 @@ "description": "The MapComplete theme Personal theme has a layer Shelter showing features with this tag", "value": "shelter" }, + { + "key": "id", + "description": "Layer 'Shelter' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "shelter_type", "description": "Layer 'Shelter' shows and asks freeform values for key 'shelter_type' (in the MapComplete.osm.be theme 'Personal theme')" @@ -9973,6 +9917,10 @@ "key": "shop", "description": "The MapComplete theme Personal theme has a layer Shop showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Shop' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer '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" @@ -9993,810 +9941,6 @@ "key": "name", "description": "Layer 'Shop' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" }, - { - "key": "shop", - "description": "Layer 'Shop' shows and asks freeform values for key 'shop' (in the MapComplete.osm.be theme 'Personal theme')" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=agrarian with a fixed text, namely 'Farm Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "agrarian" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=alcohol with a fixed text, namely 'Liquor Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "alcohol" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=anime with a fixed text, namely 'Anime / Manga Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "anime" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=antiques with a fixed text, namely 'Antiques Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "antiques" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=appliance with a fixed text, namely 'Appliance Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "appliance" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=art with a fixed text, namely 'Art Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "art" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=baby_goods with a fixed text, namely 'Baby Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "baby_goods" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bag with a fixed text, namely 'Bag/Luggage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "bag" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bakery with a fixed text, namely 'Bakery' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "bakery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bathroom_furnishing with a fixed text, namely 'Bathroom Furnishing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "bathroom_furnishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beauty with a fixed text, namely 'Beauty Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "beauty" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bed with a fixed text, namely 'Bedding/Mattress Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "bed" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beverages with a fixed text, namely 'Beverage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "beverages" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bicycle with a fixed text, namely 'Bicycle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "bicycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=boat with a fixed text, namely 'Boat Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "boat" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bookmaker with a fixed text, namely 'Bookmaker' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "bookmaker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=books with a fixed text, namely 'Book Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "books" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=brewing_supplies with a fixed text, namely 'Brewing Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "brewing_supplies" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=butcher with a fixed text, namely 'Butcher' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "butcher" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=camera with a fixed text, namely 'Camera Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "camera" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=candles with a fixed text, namely 'Candle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "candles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cannabis with a fixed text, namely 'Cannabis Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "cannabis" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car with a fixed text, namely 'Car Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "car" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_parts with a fixed text, namely 'Car Parts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "car_parts" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_repair with a fixed text, namely 'Car Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "car_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=caravan with a fixed text, namely 'RV Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "caravan" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=carpet with a fixed text, namely 'Carpet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "carpet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=catalogue with a fixed text, namely 'Catalog Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "catalogue" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=charity with a fixed text, namely 'Charity Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "charity" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cheese with a fixed text, namely 'Cheese Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "cheese" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chemist with a fixed text, namely 'Drugstore' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "chemist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chocolate with a fixed text, namely 'Chocolate Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "chocolate" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=clothes with a fixed text, namely 'Clothing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "clothes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=coffee with a fixed text, namely 'Coffee Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "coffee" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=collector with a fixed text, namely 'Collectibles Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "collector" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=computer with a fixed text, namely 'Computer Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "computer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=confectionery with a fixed text, namely 'Candy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "confectionery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=convenience with a fixed text, namely 'Convenience Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "convenience" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=copyshop with a fixed text, namely 'Copy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "copyshop" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cosmetics with a fixed text, namely 'Cosmetics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "cosmetics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=country_store with a fixed text, namely 'Country Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "country_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=craft with a fixed text, namely 'Arts & Crafts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "craft" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=curtain with a fixed text, namely 'Curtain Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "curtain" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dairy with a fixed text, namely 'Dairy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "dairy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=deli with a fixed text, namely 'Deli' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "deli" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=department_store with a fixed text, namely 'Department Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "department_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doityourself with a fixed text, namely 'DIY Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "doityourself" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doors with a fixed text, namely 'Door Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "doors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dry_cleaning with a fixed text, namely 'Dry Cleaner' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "dry_cleaning" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=e-cigarette with a fixed text, namely 'E-Cigarette Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "e-cigarette" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electrical with a fixed text, namely 'Electrical Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "electrical" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electronics with a fixed text, namely 'Electronics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "electronics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=erotic with a fixed text, namely 'Erotic Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "erotic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fabric with a fixed text, namely 'Fabric Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "fabric" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=farm with a fixed text, namely 'Produce Stand' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "farm" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fashion_accessories with a fixed text, namely 'Fashion Accessories Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "fashion_accessories" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fireplace with a fixed text, namely 'Fireplace Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "fireplace" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fishing with a fixed text, namely 'Fishing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "fishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=flooring with a fixed text, namely 'Flooring Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "flooring" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=florist with a fixed text, namely 'Florist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "florist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frame with a fixed text, namely 'Framing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "frame" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frozen_food with a fixed text, namely 'Frozen Food Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "frozen_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fuel with a fixed text, namely 'Fuel Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "fuel" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=funeral_directors with a fixed text, namely 'Funeral Home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "funeral_directors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=furniture with a fixed text, namely 'Furniture Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "furniture" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=games with a fixed text, namely 'Tabletop Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=garden_centre with a fixed text, namely 'Garden Center' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "garden_centre" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gas with a fixed text, namely 'Bottled Gas Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "gas" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=general with a fixed text, namely 'General Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "general" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gift with a fixed text, namely 'Gift Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "gift" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=greengrocer with a fixed text, namely 'Greengrocer' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "greengrocer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser with a fixed text, namely 'Hairdresser' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "hairdresser" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser_supply with a fixed text, namely 'Hairdresser Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "hairdresser_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hardware with a fixed text, namely 'Hardware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "hardware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=health_food with a fixed text, namely 'Health Food Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "health_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hearing_aids with a fixed text, namely 'Hearing Aids Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "hearing_aids" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=herbalist with a fixed text, namely 'Herbalist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "herbalist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hifi with a fixed text, namely 'Hifi Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "hifi" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hobby with a fixed text, namely 'Hobby Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "hobby" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=household_linen with a fixed text, namely 'Household Linen Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "household_linen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=houseware with a fixed text, namely 'Houseware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "houseware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hunting with a fixed text, namely 'Hunting Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "hunting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=interior_decoration with a fixed text, namely 'Interior Decoration Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "interior_decoration" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=jewelry with a fixed text, namely 'Jewelry Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "jewelry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kiosk with a fixed text, namely 'Kiosk' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "kiosk" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kitchen with a fixed text, namely 'Kitchen Design Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "kitchen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=laundry with a fixed text, namely 'Laundry' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "laundry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=leather with a fixed text, namely 'Leather Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "leather" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lighting with a fixed text, namely 'Lighting Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "lighting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=locksmith with a fixed text, namely 'Locksmith' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "locksmith" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lottery with a fixed text, namely 'Lottery Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "lottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mall with a fixed text, namely 'Mall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "mall" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=massage with a fixed text, namely 'Massage Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "massage" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=medical_supply with a fixed text, namely 'Medical Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "medical_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=military_surplus with a fixed text, namely 'Military Surplus Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "military_surplus" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mobile_phone with a fixed text, namely 'Mobile Phone Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "mobile_phone" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=model with a fixed text, namely 'Model Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "model" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=money_lender with a fixed text, namely 'Money Lender' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "money_lender" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle with a fixed text, namely 'Motorcycle Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "motorcycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle_repair with a fixed text, namely 'Motorcycle Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "motorcycle_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=music with a fixed text, namely 'Music Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "music" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=musical_instrument with a fixed text, namely 'Musical Instrument Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "musical_instrument" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=newsagent with a fixed text, namely 'Newspaper/Magazine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "newsagent" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=nutrition_supplements with a fixed text, namely 'Nutrition Supplements Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "nutrition_supplements" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=optician with a fixed text, namely 'Optician' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "optician" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outdoor with a fixed text, namely 'Outdoors Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "outdoor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outpost with a fixed text, namely 'Online Retailer Outpost' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "outpost" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=paint with a fixed text, namely 'Paint Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "paint" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=party with a fixed text, namely 'Party Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "party" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pastry with a fixed text, namely 'Pastry Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "pastry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pawnbroker with a fixed text, namely 'Pawn Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "pawnbroker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=perfumery with a fixed text, namely 'Perfume Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "perfumery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet with a fixed text, namely 'Pet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "pet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet_grooming with a fixed text, namely 'Pet Grooming Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "pet_grooming" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=photo with a fixed text, namely 'Photography Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "photo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pottery with a fixed text, namely 'Pottery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "pottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=printer_ink with a fixed text, namely 'Printer Ink Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "printer_ink" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=psychic with a fixed text, namely 'Psychic' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "psychic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pyrotechnics with a fixed text, namely 'Fireworks Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "pyrotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=radiotechnics with a fixed text, namely 'Radio/Electronic Component Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "radiotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=religion with a fixed text, namely 'Religious Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "religion" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=rental with a fixed text, namely 'Rental Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=repair with a fixed text, namely 'Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=scuba_diving with a fixed text, namely 'Scuba Diving Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "scuba_diving" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=seafood with a fixed text, namely 'Seafood Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "seafood" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=second_hand with a fixed text, namely 'Consignment/Thrift Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "second_hand" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sewing with a fixed text, namely 'Sewing Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "sewing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoe_repair with a fixed text, namely 'Shoe Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "shoe_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoes with a fixed text, namely 'Shoe Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "shoes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=spices with a fixed text, namely 'Spice Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "spices" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sports with a fixed text, namely 'Sporting Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=stationery with a fixed text, namely 'Stationery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "stationery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=storage_rental with a fixed text, namely 'Storage Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "storage_rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=supermarket with a fixed text, namely 'Supermarket' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "supermarket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=swimming_pool with a fixed text, namely 'Pool Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "swimming_pool" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tailor with a fixed text, namely 'Tailor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "tailor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tattoo with a fixed text, namely 'Tattoo Parlor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "tattoo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tea with a fixed text, namely 'Tea Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "tea" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=telecommunication with a fixed text, namely 'Telecom Retail Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "telecommunication" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=ticket with a fixed text, namely 'Ticket Seller' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "ticket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tiles with a fixed text, namely 'Tile Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "tiles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tobacco with a fixed text, namely 'Tobacco Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "tobacco" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tool_hire with a fixed text, namely 'Tool Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "tool_hire" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=toys with a fixed text, namely 'Toy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "toys" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trade with a fixed text, namely 'Trade Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "trade" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=travel_agency with a fixed text, namely 'Travel Agency' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "travel_agency" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trophy with a fixed text, namely 'Trophy Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "trophy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tyres with a fixed text, namely 'Tire Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "tyres" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=vacuum_cleaner with a fixed text, namely 'Vacuum Cleaner Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "vacuum_cleaner" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=variety_store with a fixed text, namely 'Variety Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "variety_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video with a fixed text, namely 'Video Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "video" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video_games with a fixed text, namely 'Video Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "video_games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=watches with a fixed text, namely 'Watches Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "watches" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water with a fixed text, namely 'Drinking Water Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "water" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water_sports with a fixed text, namely 'Watersport/Swim Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "water_sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=weapons with a fixed text, namely 'Weapon Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "weapons" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wholesale with a fixed text, namely 'Wholesale Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "wholesale" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wigs with a fixed text, namely 'Wig Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "wigs" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=window_blind with a fixed text, namely 'Window Blind Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "window_blind" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wine with a fixed text, namely 'Wine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "wine" - }, { "key": "opening_hours", "description": "Layer 'Shop' shows and asks freeform values for key 'opening_hours' (in the MapComplete.osm.be theme 'Personal theme')" @@ -10963,6 +10107,10 @@ "description": "The MapComplete theme Personal theme has a layer Speed Camera showing features with this tag", "value": "speed_camera" }, + { + "key": "id", + "description": "Layer 'Speed Camera' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "maxspeed", "description": "Layer 'Speed Camera' shows and asks freeform values for key 'maxspeed' (in the MapComplete.osm.be theme 'Personal theme')" @@ -10972,6 +10120,10 @@ "description": "The MapComplete theme Personal theme has a layer Speed Display showing features with this tag", "value": "speed_display" }, + { + "key": "id", + "description": "Layer 'Speed Display' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "maxspeed", "description": "Layer 'Speed Display' shows and asks freeform values for key 'maxspeed' (in the MapComplete.osm.be theme 'Personal theme')" @@ -10985,6 +10137,10 @@ "description": "The MapComplete theme Personal theme has a layer Sport pitches showing features with this tag", "value": "pitch" }, + { + "key": "id", + "description": "Layer 'Sport pitches' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Sport pitches 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" @@ -11035,6 +10191,11 @@ "description": "Layer 'Sport pitches' shows sport=basket with a fixed text, namely 'Basketball is played here' (in the MapComplete.osm.be theme 'Personal theme')", "value": "basket" }, + { + "key": "sport", + "description": "Layer 'Sport pitches' shows sport=skateboard with a fixed text, namely 'This is a skatepark' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", + "value": "skateboard" + }, { "key": "surface", "description": "Layer 'Sport pitches' shows and asks freeform values for key 'surface' (in the MapComplete.osm.be theme 'Personal theme')" @@ -11136,6 +10297,10 @@ "description": "The MapComplete theme Personal theme has a layer Sports centres showing features with this tag", "value": "sports_centre" }, + { + "key": "id", + "description": "Layer 'Sports centres' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Sports centres 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" @@ -11205,6 +10370,10 @@ "description": "The MapComplete theme Personal theme has a layer Stairs showing features with this tag", "value": "steps" }, + { + "key": "id", + "description": "Layer 'Stairs' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Stairs 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" @@ -11315,6 +10484,10 @@ "description": "The MapComplete theme Personal theme has a layer Street Lamps showing features with this tag", "value": "street_lamp" }, + { + "key": "id", + "description": "Layer 'Street Lamps' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Street Lamps 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" @@ -11517,6 +10690,10 @@ "description": "The MapComplete theme Personal theme has a layer Surveillance camera's showing features with this tag", "value": "ANPR" }, + { + "key": "id", + "description": "Layer 'Surveillance camera's' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "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" @@ -11685,6 +10862,10 @@ "key": "isced:2011:level", "description": "The MapComplete theme Personal theme has a layer Colleges and universities showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Colleges and universities' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "amenity", "description": "Layer 'Colleges and universities' shows amenity=college with a fixed text, namely 'This is an institution of post-secondary, non-tertiary education. One has to have completed secondary education to enroll here, but no bachelor (or higher) degrees are awarded here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", @@ -11710,30 +10891,6 @@ "description": "Layer 'Colleges and universities' shows isced:2011:level=doctorate with a fixed text, namely 'Doctorate degrees are awarded here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if amenity=university)", "value": "doctorate" }, - { - "key": "capacity", - "description": "Layer 'Colleges and universities' shows and asks freeform values for key 'capacity' (in the MapComplete.osm.be theme 'Personal theme')" - }, - { - "key": "school:gender", - "description": "Layer 'Colleges and universities' shows school:gender=mixed with a fixed text, namely 'Both boys and girls can enroll here and have classes together' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "mixed" - }, - { - "key": "school:gender", - "description": "Layer 'Colleges and universities' shows school:gender=separated with a fixed text, namely 'Both boys and girls can enroll here but they are separated (e.g. they have lessons in different classrooms or at different times)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "separated" - }, - { - "key": "school:gender", - "description": "Layer 'Colleges and universities' shows school:gender=male with a fixed text, namely 'This is a boys only-school' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "male" - }, - { - "key": "school:gender", - "description": "Layer 'Colleges and universities' shows school:gender=female with a fixed text, namely 'This is a girls-only school' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "female" - }, { "key": "website", "description": "Layer 'Colleges and universities' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Personal theme')" @@ -11763,6 +10920,10 @@ "description": "The MapComplete theme Personal theme has a layer Toilets showing features with this tag", "value": "toilets" }, + { + "key": "id", + "description": "Layer 'Toilets' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Toilets 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" @@ -11997,6 +11158,10 @@ "description": "The MapComplete theme Personal theme has a layer Toilets at other amenities showing features with this tag", "value": "yes" }, + { + "key": "id", + "description": "Layer 'Toilets at other amenities' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Toilets at other amenities 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" @@ -12108,80 +11273,6 @@ "key": "toilets:door:width", "description": "Layer 'Toilets at other amenities' shows and asks freeform values for key 'toilets:door:width' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if toilets:wheelchair=yes|toilets:wheelchair=designated)" }, - { - "key": "toilets:position", - "description": "Layer 'Toilets at other amenities' shows toilets:position=seated with a fixed text, namely 'There are only seated toilets' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "seated" - }, - { - "key": "toilets:position", - "description": "Layer 'Toilets at other amenities' shows toilets:position=urinal with a fixed text, namely 'There are only urinals here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "urinal" - }, - { - "key": "toilets:position", - "description": "Layer 'Toilets at other amenities' shows toilets:position=squat with a fixed text, namely 'There are only squat toilets here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "squat" - }, - { - "key": "toilets:position", - "description": "Layer 'Toilets at other amenities' shows toilets:position=seated;urinal with a fixed text, namely 'Both seated toilets and urinals are available here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "seated;urinal" - }, - { - "key": "changing_table", - "description": "Layer 'Toilets at other amenities' shows changing_table=yes with a fixed text, namely 'A changing table is available' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "yes" - }, - { - "key": "changing_table", - "description": "Layer 'Toilets at other amenities' shows changing_table=no with a fixed text, namely 'No changing table is available' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "no" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows and asks freeform values for key 'changing_table:location' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if changing_table=yes)" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows changing_table:location=female_toilet with a fixed text, namely 'The changing table is in the toilet for women. ' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if changing_table=yes)", - "value": "female_toilet" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows changing_table:location=male_toilet with a fixed text, namely 'The changing table is in the toilet for men. ' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if changing_table=yes)", - "value": "male_toilet" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows changing_table:location=wheelchair_toilet with a fixed text, namely 'The changing table is in the toilet for wheelchair users. ' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if changing_table=yes)", - "value": "wheelchair_toilet" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows changing_table:location=dedicated_room with a fixed text, namely 'The changing table is in a dedicated room. ' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if changing_table=yes)", - "value": "dedicated_room" - }, - { - "key": "toilets:handwashing", - "description": "Layer 'Toilets at other amenities' shows toilets:handwashing=yes with a fixed text, namely 'This toilets have a sink to wash your hands' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "yes" - }, - { - "key": "toilets:handwashing", - "description": "Layer 'Toilets at other amenities' shows toilets:handwashing=no with a fixed text, namely 'This toilets don't have a sink to wash your hands' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme')", - "value": "no" - }, - { - "key": "toilets:paper_supplied", - "description": "Layer 'Toilets at other amenities' shows toilets:paper_supplied=yes with a fixed text, namely 'This toilet is equipped with toilet paper' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if toilets:position!=urinal)", - "value": "yes" - }, - { - "key": "toilets:paper_supplied", - "description": "Layer 'Toilets at other amenities' shows toilets:paper_supplied=no with a fixed text, namely 'You have to bring your own toilet paper to this toilet' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if toilets:position!=urinal)", - "value": "no" - }, { "key": "toilets:description", "description": "Layer 'Toilets at other amenities' shows and asks freeform values for key 'toilets:description' (in the MapComplete.osm.be theme 'Personal theme')" @@ -12196,6 +11287,10 @@ "description": "The MapComplete theme Personal theme has a layer Bus lines showing features with this tag", "value": "bus" }, + { + "key": "id", + "description": "Layer 'Bus lines' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Bus lines' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" @@ -12229,6 +11324,10 @@ "description": "The MapComplete theme Personal theme has a layer Transit Stops showing features with this tag", "value": "bus_stop" }, + { + "key": "id", + "description": "Layer 'Transit Stops' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Transit Stops' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Personal theme')" @@ -12379,6 +11478,10 @@ "description": "The MapComplete theme Personal theme has a layer Tree showing features with this tag", "value": "tree" }, + { + "key": "id", + "description": "Layer 'Tree' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Tree 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" @@ -12543,6 +11646,10 @@ "description": "The MapComplete theme Personal theme has a layer veterinary showing features with this tag", "value": "veterinary" }, + { + "key": "id", + "description": "Layer 'veterinary' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "website", "description": "Layer 'veterinary' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Personal theme')" @@ -12572,6 +11679,10 @@ "description": "The MapComplete theme Personal theme has a layer Waste Basket showing features with this tag", "value": "waste_basket" }, + { + "key": "id", + "description": "Layer 'Waste Basket' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Waste Basket 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" @@ -12653,6 +11764,10 @@ "description": "The MapComplete theme Personal theme has a layer Waste Disposal Bins showing features with this tag", "value": "waste_disposal" }, + { + "key": "id", + "description": "Layer 'Waste Disposal Bins' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Waste Disposal Bins 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" @@ -12718,6 +11833,10 @@ "description": "The MapComplete theme Personal theme has a layer wind turbine showing features with this tag", "value": "wind" }, + { + "key": "id", + "description": "Layer 'wind turbine' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Personal theme') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "generator:output:electricity", "description": "Layer 'wind turbine' shows and asks freeform values for key 'generator:output:electricity' (in the MapComplete.osm.be theme 'Personal theme')" diff --git a/Docs/TagInfo/mapcomplete_pets.json b/Docs/TagInfo/mapcomplete_pets.json index 48778a753..0b9ba9924 100644 --- a/Docs/TagInfo/mapcomplete_pets.json +++ b/Docs/TagInfo/mapcomplete_pets.json @@ -25,6 +25,10 @@ "description": "The MapComplete theme Veterinarians, dog parks and other pet-amenities has a layer dog parks showing features with this tag", "value": "unleashed" }, + { + "key": "id", + "description": "Layer 'dog parks' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "barrier", "description": "Layer 'dog parks' shows barrier=fence with a fixed text, namely 'This dogpark is fenced all around' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", @@ -90,6 +94,10 @@ "description": "The MapComplete theme Veterinarians, dog parks and other pet-amenities has a layer Dog friendly eateries showing features with this tag", "value": "yes" }, + { + "key": "id", + "description": "Layer 'Dog friendly eateries' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "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" @@ -589,6 +597,10 @@ "description": "The MapComplete theme Veterinarians, dog parks and other pet-amenities has a layer Dog-friendly shops showing features with this tag", "value": "pet" }, + { + "key": "id", + "description": "Layer 'Dog-friendly shops' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Dog-friendly shops 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" @@ -609,810 +621,6 @@ "key": "name", "description": "Layer 'Dog-friendly shops' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')" }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows and asks freeform values for key 'shop' (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=agrarian with a fixed text, namely 'Farm Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "agrarian" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=alcohol with a fixed text, namely 'Liquor Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "alcohol" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=anime with a fixed text, namely 'Anime / Manga Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "anime" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=antiques with a fixed text, namely 'Antiques Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "antiques" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=appliance with a fixed text, namely 'Appliance Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "appliance" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=art with a fixed text, namely 'Art Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "art" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=baby_goods with a fixed text, namely 'Baby Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "baby_goods" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=bag with a fixed text, namely 'Bag/Luggage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "bag" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=bakery with a fixed text, namely 'Bakery' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "bakery" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=bathroom_furnishing with a fixed text, namely 'Bathroom Furnishing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "bathroom_furnishing" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=beauty with a fixed text, namely 'Beauty Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "beauty" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=bed with a fixed text, namely 'Bedding/Mattress Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "bed" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=beverages with a fixed text, namely 'Beverage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "beverages" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=bicycle with a fixed text, namely 'Bicycle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "bicycle" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=boat with a fixed text, namely 'Boat Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "boat" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=bookmaker with a fixed text, namely 'Bookmaker' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "bookmaker" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=books with a fixed text, namely 'Book Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "books" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=brewing_supplies with a fixed text, namely 'Brewing Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "brewing_supplies" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=butcher with a fixed text, namely 'Butcher' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "butcher" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=camera with a fixed text, namely 'Camera Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "camera" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=candles with a fixed text, namely 'Candle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "candles" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=cannabis with a fixed text, namely 'Cannabis Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "cannabis" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=car with a fixed text, namely 'Car Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "car" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=car_parts with a fixed text, namely 'Car Parts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "car_parts" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=car_repair with a fixed text, namely 'Car Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "car_repair" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=caravan with a fixed text, namely 'RV Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "caravan" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=carpet with a fixed text, namely 'Carpet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "carpet" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=catalogue with a fixed text, namely 'Catalog Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "catalogue" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=charity with a fixed text, namely 'Charity Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "charity" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=cheese with a fixed text, namely 'Cheese Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "cheese" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=chemist with a fixed text, namely 'Drugstore' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "chemist" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=chocolate with a fixed text, namely 'Chocolate Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "chocolate" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=clothes with a fixed text, namely 'Clothing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "clothes" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=coffee with a fixed text, namely 'Coffee Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "coffee" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=collector with a fixed text, namely 'Collectibles Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "collector" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=computer with a fixed text, namely 'Computer Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "computer" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=confectionery with a fixed text, namely 'Candy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "confectionery" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=convenience with a fixed text, namely 'Convenience Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "convenience" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=copyshop with a fixed text, namely 'Copy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "copyshop" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=cosmetics with a fixed text, namely 'Cosmetics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "cosmetics" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=country_store with a fixed text, namely 'Country Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "country_store" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=craft with a fixed text, namely 'Arts & Crafts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "craft" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=curtain with a fixed text, namely 'Curtain Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "curtain" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=dairy with a fixed text, namely 'Dairy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "dairy" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=deli with a fixed text, namely 'Deli' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "deli" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=department_store with a fixed text, namely 'Department Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "department_store" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=doityourself with a fixed text, namely 'DIY Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "doityourself" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=doors with a fixed text, namely 'Door Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "doors" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=dry_cleaning with a fixed text, namely 'Dry Cleaner' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "dry_cleaning" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=e-cigarette with a fixed text, namely 'E-Cigarette Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "e-cigarette" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=electrical with a fixed text, namely 'Electrical Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "electrical" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=electronics with a fixed text, namely 'Electronics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "electronics" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=erotic with a fixed text, namely 'Erotic Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "erotic" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=fabric with a fixed text, namely 'Fabric Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "fabric" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=farm with a fixed text, namely 'Produce Stand' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "farm" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=fashion_accessories with a fixed text, namely 'Fashion Accessories Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "fashion_accessories" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=fireplace with a fixed text, namely 'Fireplace Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "fireplace" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=fishing with a fixed text, namely 'Fishing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "fishing" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=flooring with a fixed text, namely 'Flooring Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "flooring" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=florist with a fixed text, namely 'Florist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "florist" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=frame with a fixed text, namely 'Framing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "frame" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=frozen_food with a fixed text, namely 'Frozen Food Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "frozen_food" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=fuel with a fixed text, namely 'Fuel Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "fuel" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=funeral_directors with a fixed text, namely 'Funeral Home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "funeral_directors" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=furniture with a fixed text, namely 'Furniture Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "furniture" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=games with a fixed text, namely 'Tabletop Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "games" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=garden_centre with a fixed text, namely 'Garden Center' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "garden_centre" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=gas with a fixed text, namely 'Bottled Gas Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "gas" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=general with a fixed text, namely 'General Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "general" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=gift with a fixed text, namely 'Gift Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "gift" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=greengrocer with a fixed text, namely 'Greengrocer' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "greengrocer" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=hairdresser with a fixed text, namely 'Hairdresser' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "hairdresser" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=hairdresser_supply with a fixed text, namely 'Hairdresser Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "hairdresser_supply" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=hardware with a fixed text, namely 'Hardware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "hardware" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=health_food with a fixed text, namely 'Health Food Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "health_food" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=hearing_aids with a fixed text, namely 'Hearing Aids Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "hearing_aids" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=herbalist with a fixed text, namely 'Herbalist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "herbalist" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=hifi with a fixed text, namely 'Hifi Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "hifi" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=hobby with a fixed text, namely 'Hobby Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "hobby" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=household_linen with a fixed text, namely 'Household Linen Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "household_linen" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=houseware with a fixed text, namely 'Houseware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "houseware" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=hunting with a fixed text, namely 'Hunting Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "hunting" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=interior_decoration with a fixed text, namely 'Interior Decoration Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "interior_decoration" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=jewelry with a fixed text, namely 'Jewelry Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "jewelry" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=kiosk with a fixed text, namely 'Kiosk' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "kiosk" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=kitchen with a fixed text, namely 'Kitchen Design Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "kitchen" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=laundry with a fixed text, namely 'Laundry' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "laundry" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=leather with a fixed text, namely 'Leather Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "leather" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=lighting with a fixed text, namely 'Lighting Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "lighting" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=locksmith with a fixed text, namely 'Locksmith' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "locksmith" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=lottery with a fixed text, namely 'Lottery Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "lottery" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=mall with a fixed text, namely 'Mall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "mall" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=massage with a fixed text, namely 'Massage Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "massage" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=medical_supply with a fixed text, namely 'Medical Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "medical_supply" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=military_surplus with a fixed text, namely 'Military Surplus Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "military_surplus" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=mobile_phone with a fixed text, namely 'Mobile Phone Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "mobile_phone" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=model with a fixed text, namely 'Model Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "model" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=money_lender with a fixed text, namely 'Money Lender' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "money_lender" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=motorcycle with a fixed text, namely 'Motorcycle Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "motorcycle" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=motorcycle_repair with a fixed text, namely 'Motorcycle Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "motorcycle_repair" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=music with a fixed text, namely 'Music Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "music" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=musical_instrument with a fixed text, namely 'Musical Instrument Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "musical_instrument" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=newsagent with a fixed text, namely 'Newspaper/Magazine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "newsagent" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=nutrition_supplements with a fixed text, namely 'Nutrition Supplements Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "nutrition_supplements" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=optician with a fixed text, namely 'Optician' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "optician" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=outdoor with a fixed text, namely 'Outdoors Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "outdoor" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=outpost with a fixed text, namely 'Online Retailer Outpost' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "outpost" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=paint with a fixed text, namely 'Paint Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "paint" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=party with a fixed text, namely 'Party Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "party" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=pastry with a fixed text, namely 'Pastry Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "pastry" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=pawnbroker with a fixed text, namely 'Pawn Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "pawnbroker" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=perfumery with a fixed text, namely 'Perfume Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "perfumery" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=pet with a fixed text, namely 'Pet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "pet" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=pet_grooming with a fixed text, namely 'Pet Grooming Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "pet_grooming" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=photo with a fixed text, namely 'Photography Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "photo" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=pottery with a fixed text, namely 'Pottery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "pottery" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=printer_ink with a fixed text, namely 'Printer Ink Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "printer_ink" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=psychic with a fixed text, namely 'Psychic' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "psychic" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=pyrotechnics with a fixed text, namely 'Fireworks Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "pyrotechnics" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=radiotechnics with a fixed text, namely 'Radio/Electronic Component Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "radiotechnics" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=religion with a fixed text, namely 'Religious Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "religion" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=rental with a fixed text, namely 'Rental Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "rental" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=repair with a fixed text, namely 'Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "repair" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=scuba_diving with a fixed text, namely 'Scuba Diving Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "scuba_diving" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=seafood with a fixed text, namely 'Seafood Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "seafood" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=second_hand with a fixed text, namely 'Consignment/Thrift Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "second_hand" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=sewing with a fixed text, namely 'Sewing Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "sewing" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=shoe_repair with a fixed text, namely 'Shoe Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "shoe_repair" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=shoes with a fixed text, namely 'Shoe Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "shoes" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=spices with a fixed text, namely 'Spice Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "spices" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=sports with a fixed text, namely 'Sporting Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "sports" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=stationery with a fixed text, namely 'Stationery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "stationery" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=storage_rental with a fixed text, namely 'Storage Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "storage_rental" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=supermarket with a fixed text, namely 'Supermarket' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "supermarket" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=swimming_pool with a fixed text, namely 'Pool Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "swimming_pool" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=tailor with a fixed text, namely 'Tailor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "tailor" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=tattoo with a fixed text, namely 'Tattoo Parlor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "tattoo" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=tea with a fixed text, namely 'Tea Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "tea" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=telecommunication with a fixed text, namely 'Telecom Retail Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "telecommunication" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=ticket with a fixed text, namely 'Ticket Seller' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "ticket" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=tiles with a fixed text, namely 'Tile Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "tiles" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=tobacco with a fixed text, namely 'Tobacco Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "tobacco" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=tool_hire with a fixed text, namely 'Tool Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "tool_hire" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=toys with a fixed text, namely 'Toy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "toys" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=trade with a fixed text, namely 'Trade Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "trade" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=travel_agency with a fixed text, namely 'Travel Agency' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "travel_agency" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=trophy with a fixed text, namely 'Trophy Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "trophy" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=tyres with a fixed text, namely 'Tire Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "tyres" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=vacuum_cleaner with a fixed text, namely 'Vacuum Cleaner Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "vacuum_cleaner" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=variety_store with a fixed text, namely 'Variety Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "variety_store" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=video with a fixed text, namely 'Video Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "video" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=video_games with a fixed text, namely 'Video Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "video_games" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=watches with a fixed text, namely 'Watches Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "watches" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=water with a fixed text, namely 'Drinking Water Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "water" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=water_sports with a fixed text, namely 'Watersport/Swim Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "water_sports" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=weapons with a fixed text, namely 'Weapon Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "weapons" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=wholesale with a fixed text, namely 'Wholesale Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "wholesale" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=wigs with a fixed text, namely 'Wig Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "wigs" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=window_blind with a fixed text, namely 'Window Blind Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "window_blind" - }, - { - "key": "shop", - "description": "Layer 'Dog-friendly shops' shows shop=wine with a fixed text, namely 'Wine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')", - "value": "wine" - }, { "key": "opening_hours", "description": "Layer 'Dog-friendly shops' shows and asks freeform values for key 'opening_hours' (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')" @@ -1579,6 +787,10 @@ "description": "The MapComplete theme Veterinarians, dog parks and other pet-amenities has a layer veterinary showing features with this tag", "value": "veterinary" }, + { + "key": "id", + "description": "Layer 'veterinary' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "website", "description": "Layer 'veterinary' shows and asks freeform values for key 'website' (in the MapComplete.osm.be theme 'Veterinarians, dog parks and other pet-amenities')" diff --git a/Docs/TagInfo/mapcomplete_playgrounds.json b/Docs/TagInfo/mapcomplete_playgrounds.json index 460ba871a..f48a48921 100644 --- a/Docs/TagInfo/mapcomplete_playgrounds.json +++ b/Docs/TagInfo/mapcomplete_playgrounds.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Playgrounds has a layer Playgrounds showing features with this tag", "value": "playground" }, + { + "key": "id", + "description": "Layer 'Playgrounds' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Playgrounds') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Playgrounds 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" diff --git a/Docs/TagInfo/mapcomplete_postboxes.json b/Docs/TagInfo/mapcomplete_postboxes.json index 8c7434eff..bfad8e57e 100644 --- a/Docs/TagInfo/mapcomplete_postboxes.json +++ b/Docs/TagInfo/mapcomplete_postboxes.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Postbox and Post Office Map has a layer Postboxes showing features with this tag", "value": "post_box" }, + { + "key": "id", + "description": "Layer 'Postboxes' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Postbox and Post Office Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Postboxes 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" @@ -41,6 +45,10 @@ "description": "The MapComplete theme Postbox and Post Office Map has a layer Post offices showing features with this tag", "value": "post_partner" }, + { + "key": "id", + "description": "Layer 'Post offices' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Postbox and Post Office Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Post offices 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" @@ -200,6 +208,10 @@ "description": "The MapComplete theme Postbox and Post Office Map has a layer Parcel Lockers showing features with this tag", "value": "parcel_pickup;parcel_mail_in" }, + { + "key": "id", + "description": "Layer 'Parcel Lockers' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Postbox and Post Office Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parcel Lockers 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" diff --git a/Docs/TagInfo/mapcomplete_rainbow_crossings.json b/Docs/TagInfo/mapcomplete_rainbow_crossings.json index c506f32c5..edcf4fb4e 100644 --- a/Docs/TagInfo/mapcomplete_rainbow_crossings.json +++ b/Docs/TagInfo/mapcomplete_rainbow_crossings.json @@ -10,11 +10,30 @@ "contact_email": "pietervdvn@posteo.net" }, "tags": [ + { + "key": "surface:colour", + "description": "The MapComplete theme Rainbow pedestrian crossings has a layer Crossings with rainbow paintings showing features with this tag", + "value": "rainbow" + }, + { + "key": "highway", + "description": "The MapComplete theme Rainbow pedestrian crossings has a layer Crossings with rainbow paintings showing features with this tag", + "value": "crossing" + }, + { + "key": "highway", + "description": "The MapComplete theme Rainbow pedestrian crossings has a layer Crossings with rainbow paintings showing features with this tag", + "value": "footway" + }, { "key": "footway", "description": "The MapComplete theme Rainbow pedestrian crossings has a layer Crossings with rainbow paintings showing features with this tag", "value": "crossing" }, + { + "key": "id", + "description": "Layer 'Crossings with rainbow paintings' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Rainbow pedestrian crossings') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Crossings with rainbow paintings 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" @@ -42,4 +61,4 @@ "value": "rainbow" } ] -} +} \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_shops.json b/Docs/TagInfo/mapcomplete_shops.json index d2f56271a..f6d8380dc 100644 --- a/Docs/TagInfo/mapcomplete_shops.json +++ b/Docs/TagInfo/mapcomplete_shops.json @@ -14,6 +14,10 @@ "key": "shop", "description": "The MapComplete theme Open Shop Map has a layer Shop showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Shop' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Shop Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer '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" @@ -34,810 +38,6 @@ "key": "name", "description": "Layer 'Shop' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Open Shop Map')" }, - { - "key": "shop", - "description": "Layer 'Shop' shows and asks freeform values for key 'shop' (in the MapComplete.osm.be theme 'Open Shop Map')" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=agrarian with a fixed text, namely 'Farm Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "agrarian" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=alcohol with a fixed text, namely 'Liquor Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "alcohol" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=anime with a fixed text, namely 'Anime / Manga Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "anime" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=antiques with a fixed text, namely 'Antiques Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "antiques" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=appliance with a fixed text, namely 'Appliance Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "appliance" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=art with a fixed text, namely 'Art Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "art" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=baby_goods with a fixed text, namely 'Baby Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "baby_goods" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bag with a fixed text, namely 'Bag/Luggage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "bag" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bakery with a fixed text, namely 'Bakery' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "bakery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bathroom_furnishing with a fixed text, namely 'Bathroom Furnishing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "bathroom_furnishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beauty with a fixed text, namely 'Beauty Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "beauty" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bed with a fixed text, namely 'Bedding/Mattress Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "bed" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beverages with a fixed text, namely 'Beverage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "beverages" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bicycle with a fixed text, namely 'Bicycle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "bicycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=boat with a fixed text, namely 'Boat Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "boat" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bookmaker with a fixed text, namely 'Bookmaker' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "bookmaker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=books with a fixed text, namely 'Book Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "books" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=brewing_supplies with a fixed text, namely 'Brewing Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "brewing_supplies" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=butcher with a fixed text, namely 'Butcher' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "butcher" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=camera with a fixed text, namely 'Camera Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "camera" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=candles with a fixed text, namely 'Candle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "candles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cannabis with a fixed text, namely 'Cannabis Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "cannabis" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car with a fixed text, namely 'Car Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "car" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_parts with a fixed text, namely 'Car Parts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "car_parts" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_repair with a fixed text, namely 'Car Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "car_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=caravan with a fixed text, namely 'RV Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "caravan" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=carpet with a fixed text, namely 'Carpet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "carpet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=catalogue with a fixed text, namely 'Catalog Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "catalogue" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=charity with a fixed text, namely 'Charity Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "charity" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cheese with a fixed text, namely 'Cheese Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "cheese" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chemist with a fixed text, namely 'Drugstore' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "chemist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chocolate with a fixed text, namely 'Chocolate Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "chocolate" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=clothes with a fixed text, namely 'Clothing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "clothes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=coffee with a fixed text, namely 'Coffee Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "coffee" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=collector with a fixed text, namely 'Collectibles Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "collector" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=computer with a fixed text, namely 'Computer Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "computer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=confectionery with a fixed text, namely 'Candy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "confectionery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=convenience with a fixed text, namely 'Convenience Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "convenience" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=copyshop with a fixed text, namely 'Copy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "copyshop" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cosmetics with a fixed text, namely 'Cosmetics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "cosmetics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=country_store with a fixed text, namely 'Country Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "country_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=craft with a fixed text, namely 'Arts & Crafts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "craft" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=curtain with a fixed text, namely 'Curtain Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "curtain" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dairy with a fixed text, namely 'Dairy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "dairy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=deli with a fixed text, namely 'Deli' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "deli" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=department_store with a fixed text, namely 'Department Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "department_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doityourself with a fixed text, namely 'DIY Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "doityourself" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doors with a fixed text, namely 'Door Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "doors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dry_cleaning with a fixed text, namely 'Dry Cleaner' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "dry_cleaning" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=e-cigarette with a fixed text, namely 'E-Cigarette Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "e-cigarette" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electrical with a fixed text, namely 'Electrical Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "electrical" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electronics with a fixed text, namely 'Electronics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "electronics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=erotic with a fixed text, namely 'Erotic Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "erotic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fabric with a fixed text, namely 'Fabric Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "fabric" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=farm with a fixed text, namely 'Produce Stand' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "farm" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fashion_accessories with a fixed text, namely 'Fashion Accessories Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "fashion_accessories" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fireplace with a fixed text, namely 'Fireplace Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "fireplace" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fishing with a fixed text, namely 'Fishing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "fishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=flooring with a fixed text, namely 'Flooring Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "flooring" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=florist with a fixed text, namely 'Florist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "florist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frame with a fixed text, namely 'Framing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "frame" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frozen_food with a fixed text, namely 'Frozen Food Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "frozen_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fuel with a fixed text, namely 'Fuel Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "fuel" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=funeral_directors with a fixed text, namely 'Funeral Home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "funeral_directors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=furniture with a fixed text, namely 'Furniture Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "furniture" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=games with a fixed text, namely 'Tabletop Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=garden_centre with a fixed text, namely 'Garden Center' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "garden_centre" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gas with a fixed text, namely 'Bottled Gas Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "gas" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=general with a fixed text, namely 'General Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "general" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gift with a fixed text, namely 'Gift Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "gift" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=greengrocer with a fixed text, namely 'Greengrocer' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "greengrocer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser with a fixed text, namely 'Hairdresser' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "hairdresser" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser_supply with a fixed text, namely 'Hairdresser Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "hairdresser_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hardware with a fixed text, namely 'Hardware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "hardware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=health_food with a fixed text, namely 'Health Food Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "health_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hearing_aids with a fixed text, namely 'Hearing Aids Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "hearing_aids" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=herbalist with a fixed text, namely 'Herbalist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "herbalist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hifi with a fixed text, namely 'Hifi Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "hifi" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hobby with a fixed text, namely 'Hobby Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "hobby" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=household_linen with a fixed text, namely 'Household Linen Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "household_linen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=houseware with a fixed text, namely 'Houseware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "houseware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hunting with a fixed text, namely 'Hunting Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "hunting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=interior_decoration with a fixed text, namely 'Interior Decoration Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "interior_decoration" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=jewelry with a fixed text, namely 'Jewelry Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "jewelry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kiosk with a fixed text, namely 'Kiosk' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "kiosk" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kitchen with a fixed text, namely 'Kitchen Design Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "kitchen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=laundry with a fixed text, namely 'Laundry' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "laundry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=leather with a fixed text, namely 'Leather Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "leather" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lighting with a fixed text, namely 'Lighting Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "lighting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=locksmith with a fixed text, namely 'Locksmith' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "locksmith" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lottery with a fixed text, namely 'Lottery Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "lottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mall with a fixed text, namely 'Mall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "mall" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=massage with a fixed text, namely 'Massage Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "massage" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=medical_supply with a fixed text, namely 'Medical Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "medical_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=military_surplus with a fixed text, namely 'Military Surplus Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "military_surplus" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mobile_phone with a fixed text, namely 'Mobile Phone Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "mobile_phone" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=model with a fixed text, namely 'Model Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "model" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=money_lender with a fixed text, namely 'Money Lender' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "money_lender" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle with a fixed text, namely 'Motorcycle Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "motorcycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle_repair with a fixed text, namely 'Motorcycle Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "motorcycle_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=music with a fixed text, namely 'Music Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "music" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=musical_instrument with a fixed text, namely 'Musical Instrument Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "musical_instrument" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=newsagent with a fixed text, namely 'Newspaper/Magazine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "newsagent" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=nutrition_supplements with a fixed text, namely 'Nutrition Supplements Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "nutrition_supplements" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=optician with a fixed text, namely 'Optician' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "optician" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outdoor with a fixed text, namely 'Outdoors Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "outdoor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outpost with a fixed text, namely 'Online Retailer Outpost' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "outpost" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=paint with a fixed text, namely 'Paint Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "paint" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=party with a fixed text, namely 'Party Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "party" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pastry with a fixed text, namely 'Pastry Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "pastry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pawnbroker with a fixed text, namely 'Pawn Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "pawnbroker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=perfumery with a fixed text, namely 'Perfume Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "perfumery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet with a fixed text, namely 'Pet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "pet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet_grooming with a fixed text, namely 'Pet Grooming Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "pet_grooming" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=photo with a fixed text, namely 'Photography Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "photo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pottery with a fixed text, namely 'Pottery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "pottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=printer_ink with a fixed text, namely 'Printer Ink Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "printer_ink" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=psychic with a fixed text, namely 'Psychic' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "psychic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pyrotechnics with a fixed text, namely 'Fireworks Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "pyrotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=radiotechnics with a fixed text, namely 'Radio/Electronic Component Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "radiotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=religion with a fixed text, namely 'Religious Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "religion" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=rental with a fixed text, namely 'Rental Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=repair with a fixed text, namely 'Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=scuba_diving with a fixed text, namely 'Scuba Diving Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "scuba_diving" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=seafood with a fixed text, namely 'Seafood Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "seafood" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=second_hand with a fixed text, namely 'Consignment/Thrift Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "second_hand" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sewing with a fixed text, namely 'Sewing Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "sewing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoe_repair with a fixed text, namely 'Shoe Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "shoe_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoes with a fixed text, namely 'Shoe Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "shoes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=spices with a fixed text, namely 'Spice Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "spices" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sports with a fixed text, namely 'Sporting Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=stationery with a fixed text, namely 'Stationery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "stationery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=storage_rental with a fixed text, namely 'Storage Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "storage_rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=supermarket with a fixed text, namely 'Supermarket' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "supermarket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=swimming_pool with a fixed text, namely 'Pool Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "swimming_pool" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tailor with a fixed text, namely 'Tailor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "tailor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tattoo with a fixed text, namely 'Tattoo Parlor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "tattoo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tea with a fixed text, namely 'Tea Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "tea" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=telecommunication with a fixed text, namely 'Telecom Retail Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "telecommunication" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=ticket with a fixed text, namely 'Ticket Seller' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "ticket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tiles with a fixed text, namely 'Tile Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "tiles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tobacco with a fixed text, namely 'Tobacco Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "tobacco" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tool_hire with a fixed text, namely 'Tool Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "tool_hire" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=toys with a fixed text, namely 'Toy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "toys" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trade with a fixed text, namely 'Trade Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "trade" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=travel_agency with a fixed text, namely 'Travel Agency' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "travel_agency" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trophy with a fixed text, namely 'Trophy Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "trophy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tyres with a fixed text, namely 'Tire Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "tyres" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=vacuum_cleaner with a fixed text, namely 'Vacuum Cleaner Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "vacuum_cleaner" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=variety_store with a fixed text, namely 'Variety Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "variety_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video with a fixed text, namely 'Video Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "video" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video_games with a fixed text, namely 'Video Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "video_games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=watches with a fixed text, namely 'Watches Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "watches" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water with a fixed text, namely 'Drinking Water Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "water" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water_sports with a fixed text, namely 'Watersport/Swim Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "water_sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=weapons with a fixed text, namely 'Weapon Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "weapons" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wholesale with a fixed text, namely 'Wholesale Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "wholesale" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wigs with a fixed text, namely 'Wig Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "wigs" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=window_blind with a fixed text, namely 'Window Blind Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "window_blind" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wine with a fixed text, namely 'Wine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Shop Map')", - "value": "wine" - }, { "key": "opening_hours", "description": "Layer 'Shop' shows and asks freeform values for key 'opening_hours' (in the MapComplete.osm.be theme 'Open Shop Map')" @@ -1004,6 +204,10 @@ "description": "The MapComplete theme Open Shop Map has a layer Pharmacies showing features with this tag", "value": "pharmacy" }, + { + "key": "id", + "description": "Layer 'Pharmacies' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Shop Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Pharmacies 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" diff --git a/Docs/TagInfo/mapcomplete_sport_pitches.json b/Docs/TagInfo/mapcomplete_sport_pitches.json index 2ee7f6413..ad8e95df1 100644 --- a/Docs/TagInfo/mapcomplete_sport_pitches.json +++ b/Docs/TagInfo/mapcomplete_sport_pitches.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Sport pitches has a layer Sport pitches showing features with this tag", "value": "pitch" }, + { + "key": "id", + "description": "Layer 'Sport pitches' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Sport pitches') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Sport pitches 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" @@ -65,6 +69,11 @@ "description": "Layer 'Sport pitches' shows sport=basket with a fixed text, namely 'Basketball is played here' (in the MapComplete.osm.be theme 'Sport pitches')", "value": "basket" }, + { + "key": "sport", + "description": "Layer 'Sport pitches' shows sport=skateboard with a fixed text, namely 'This is a skatepark' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sport pitches')", + "value": "skateboard" + }, { "key": "surface", "description": "Layer 'Sport pitches' shows and asks freeform values for key 'surface' (in the MapComplete.osm.be theme 'Sport pitches')" diff --git a/Docs/TagInfo/mapcomplete_sports.json b/Docs/TagInfo/mapcomplete_sports.json index f0a359b24..b88569c98 100644 --- a/Docs/TagInfo/mapcomplete_sports.json +++ b/Docs/TagInfo/mapcomplete_sports.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Sports has a layer Sport pitches showing features with this tag", "value": "pitch" }, + { + "key": "id", + "description": "Layer 'Sport pitches' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Sports') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Sport pitches 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" @@ -65,6 +69,11 @@ "description": "Layer 'Sport pitches' shows sport=basket with a fixed text, namely 'Basketball is played here' (in the MapComplete.osm.be theme 'Sports')", "value": "basket" }, + { + "key": "sport", + "description": "Layer 'Sport pitches' shows sport=skateboard with a fixed text, namely 'This is a skatepark' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", + "value": "skateboard" + }, { "key": "surface", "description": "Layer 'Sport pitches' shows and asks freeform values for key 'surface' (in the MapComplete.osm.be theme 'Sports')" @@ -166,6 +175,10 @@ "description": "The MapComplete theme Sports has a layer Fitness Centres showing features with this tag", "value": "fitness_centre" }, + { + "key": "id", + "description": "Layer 'Fitness Centres' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Sports') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Fitness Centres' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Sports')" @@ -273,6 +286,10 @@ "description": "The MapComplete theme Sports has a layer Fitness Stations showing features with this tag", "value": "fitness_station" }, + { + "key": "id", + "description": "Layer 'Fitness Stations' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Sports') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Fitness Stations 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" @@ -441,6 +458,10 @@ "description": "The MapComplete theme Sports has a layer Sports centres showing features with this tag", "value": "sports_centre" }, + { + "key": "id", + "description": "Layer 'Sports centres' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Sports') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Sports centres 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" @@ -510,6 +531,10 @@ "description": "The MapComplete theme Sports has a layer Shop showing features with this tag", "value": "sports" }, + { + "key": "id", + "description": "Layer 'Shop' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Sports') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer '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" @@ -530,810 +555,6 @@ "key": "name", "description": "Layer 'Shop' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Sports')" }, - { - "key": "shop", - "description": "Layer 'Shop' shows and asks freeform values for key 'shop' (in the MapComplete.osm.be theme 'Sports')" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=agrarian with a fixed text, namely 'Farm Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "agrarian" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=alcohol with a fixed text, namely 'Liquor Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "alcohol" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=anime with a fixed text, namely 'Anime / Manga Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "anime" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=antiques with a fixed text, namely 'Antiques Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "antiques" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=appliance with a fixed text, namely 'Appliance Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "appliance" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=art with a fixed text, namely 'Art Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "art" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=baby_goods with a fixed text, namely 'Baby Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "baby_goods" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bag with a fixed text, namely 'Bag/Luggage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "bag" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bakery with a fixed text, namely 'Bakery' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "bakery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bathroom_furnishing with a fixed text, namely 'Bathroom Furnishing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "bathroom_furnishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beauty with a fixed text, namely 'Beauty Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "beauty" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bed with a fixed text, namely 'Bedding/Mattress Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "bed" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=beverages with a fixed text, namely 'Beverage Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "beverages" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bicycle with a fixed text, namely 'Bicycle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "bicycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=boat with a fixed text, namely 'Boat Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "boat" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=bookmaker with a fixed text, namely 'Bookmaker' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "bookmaker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=books with a fixed text, namely 'Book Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "books" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=brewing_supplies with a fixed text, namely 'Brewing Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "brewing_supplies" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=butcher with a fixed text, namely 'Butcher' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "butcher" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=camera with a fixed text, namely 'Camera Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "camera" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=candles with a fixed text, namely 'Candle Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "candles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cannabis with a fixed text, namely 'Cannabis Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "cannabis" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car with a fixed text, namely 'Car Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "car" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_parts with a fixed text, namely 'Car Parts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "car_parts" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=car_repair with a fixed text, namely 'Car Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "car_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=caravan with a fixed text, namely 'RV Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "caravan" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=carpet with a fixed text, namely 'Carpet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "carpet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=catalogue with a fixed text, namely 'Catalog Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "catalogue" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=charity with a fixed text, namely 'Charity Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "charity" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cheese with a fixed text, namely 'Cheese Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "cheese" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chemist with a fixed text, namely 'Drugstore' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "chemist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=chocolate with a fixed text, namely 'Chocolate Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "chocolate" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=clothes with a fixed text, namely 'Clothing Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "clothes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=coffee with a fixed text, namely 'Coffee Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "coffee" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=collector with a fixed text, namely 'Collectibles Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "collector" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=computer with a fixed text, namely 'Computer Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "computer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=confectionery with a fixed text, namely 'Candy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "confectionery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=convenience with a fixed text, namely 'Convenience Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "convenience" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=copyshop with a fixed text, namely 'Copy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "copyshop" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=cosmetics with a fixed text, namely 'Cosmetics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "cosmetics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=country_store with a fixed text, namely 'Country Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "country_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=craft with a fixed text, namely 'Arts & Crafts Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "craft" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=curtain with a fixed text, namely 'Curtain Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "curtain" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dairy with a fixed text, namely 'Dairy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "dairy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=deli with a fixed text, namely 'Deli' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "deli" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=department_store with a fixed text, namely 'Department Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "department_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doityourself with a fixed text, namely 'DIY Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "doityourself" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=doors with a fixed text, namely 'Door Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "doors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=dry_cleaning with a fixed text, namely 'Dry Cleaner' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "dry_cleaning" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=e-cigarette with a fixed text, namely 'E-Cigarette Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "e-cigarette" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electrical with a fixed text, namely 'Electrical Equipment Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "electrical" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=electronics with a fixed text, namely 'Electronics Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "electronics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=erotic with a fixed text, namely 'Erotic Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "erotic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fabric with a fixed text, namely 'Fabric Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "fabric" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=farm with a fixed text, namely 'Produce Stand' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "farm" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fashion_accessories with a fixed text, namely 'Fashion Accessories Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "fashion_accessories" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fireplace with a fixed text, namely 'Fireplace Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "fireplace" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fishing with a fixed text, namely 'Fishing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "fishing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=flooring with a fixed text, namely 'Flooring Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "flooring" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=florist with a fixed text, namely 'Florist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "florist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frame with a fixed text, namely 'Framing Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "frame" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=frozen_food with a fixed text, namely 'Frozen Food Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "frozen_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=fuel with a fixed text, namely 'Fuel Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "fuel" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=funeral_directors with a fixed text, namely 'Funeral Home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "funeral_directors" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=furniture with a fixed text, namely 'Furniture Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "furniture" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=games with a fixed text, namely 'Tabletop Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=garden_centre with a fixed text, namely 'Garden Center' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "garden_centre" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gas with a fixed text, namely 'Bottled Gas Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "gas" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=general with a fixed text, namely 'General Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "general" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=gift with a fixed text, namely 'Gift Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "gift" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=greengrocer with a fixed text, namely 'Greengrocer' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "greengrocer" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser with a fixed text, namely 'Hairdresser' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "hairdresser" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hairdresser_supply with a fixed text, namely 'Hairdresser Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "hairdresser_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hardware with a fixed text, namely 'Hardware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "hardware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=health_food with a fixed text, namely 'Health Food Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "health_food" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hearing_aids with a fixed text, namely 'Hearing Aids Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "hearing_aids" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=herbalist with a fixed text, namely 'Herbalist' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "herbalist" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hifi with a fixed text, namely 'Hifi Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "hifi" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hobby with a fixed text, namely 'Hobby Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "hobby" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=household_linen with a fixed text, namely 'Household Linen Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "household_linen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=houseware with a fixed text, namely 'Houseware Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "houseware" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=hunting with a fixed text, namely 'Hunting Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "hunting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=interior_decoration with a fixed text, namely 'Interior Decoration Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "interior_decoration" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=jewelry with a fixed text, namely 'Jewelry Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "jewelry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kiosk with a fixed text, namely 'Kiosk' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "kiosk" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=kitchen with a fixed text, namely 'Kitchen Design Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "kitchen" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=laundry with a fixed text, namely 'Laundry' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "laundry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=leather with a fixed text, namely 'Leather Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "leather" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lighting with a fixed text, namely 'Lighting Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "lighting" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=locksmith with a fixed text, namely 'Locksmith' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "locksmith" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=lottery with a fixed text, namely 'Lottery Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "lottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mall with a fixed text, namely 'Mall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "mall" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=massage with a fixed text, namely 'Massage Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "massage" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=medical_supply with a fixed text, namely 'Medical Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "medical_supply" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=military_surplus with a fixed text, namely 'Military Surplus Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "military_surplus" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=mobile_phone with a fixed text, namely 'Mobile Phone Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "mobile_phone" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=model with a fixed text, namely 'Model Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "model" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=money_lender with a fixed text, namely 'Money Lender' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "money_lender" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle with a fixed text, namely 'Motorcycle Dealership' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "motorcycle" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=motorcycle_repair with a fixed text, namely 'Motorcycle Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "motorcycle_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=music with a fixed text, namely 'Music Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "music" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=musical_instrument with a fixed text, namely 'Musical Instrument Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "musical_instrument" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=newsagent with a fixed text, namely 'Newspaper/Magazine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "newsagent" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=nutrition_supplements with a fixed text, namely 'Nutrition Supplements Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "nutrition_supplements" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=optician with a fixed text, namely 'Optician' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "optician" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outdoor with a fixed text, namely 'Outdoors Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "outdoor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=outpost with a fixed text, namely 'Online Retailer Outpost' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "outpost" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=paint with a fixed text, namely 'Paint Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "paint" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=party with a fixed text, namely 'Party Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "party" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pastry with a fixed text, namely 'Pastry Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "pastry" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pawnbroker with a fixed text, namely 'Pawn Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "pawnbroker" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=perfumery with a fixed text, namely 'Perfume Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "perfumery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet with a fixed text, namely 'Pet Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "pet" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pet_grooming with a fixed text, namely 'Pet Grooming Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "pet_grooming" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=photo with a fixed text, namely 'Photography Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "photo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pottery with a fixed text, namely 'Pottery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "pottery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=printer_ink with a fixed text, namely 'Printer Ink Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "printer_ink" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=psychic with a fixed text, namely 'Psychic' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "psychic" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=pyrotechnics with a fixed text, namely 'Fireworks Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "pyrotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=radiotechnics with a fixed text, namely 'Radio/Electronic Component Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "radiotechnics" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=religion with a fixed text, namely 'Religious Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "religion" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=rental with a fixed text, namely 'Rental Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=repair with a fixed text, namely 'Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=scuba_diving with a fixed text, namely 'Scuba Diving Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "scuba_diving" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=seafood with a fixed text, namely 'Seafood Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "seafood" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=second_hand with a fixed text, namely 'Consignment/Thrift Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "second_hand" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sewing with a fixed text, namely 'Sewing Supply Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "sewing" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoe_repair with a fixed text, namely 'Shoe Repair Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "shoe_repair" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=shoes with a fixed text, namely 'Shoe Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "shoes" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=spices with a fixed text, namely 'Spice Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "spices" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=sports with a fixed text, namely 'Sporting Goods Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=stationery with a fixed text, namely 'Stationery Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "stationery" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=storage_rental with a fixed text, namely 'Storage Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "storage_rental" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=supermarket with a fixed text, namely 'Supermarket' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "supermarket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=swimming_pool with a fixed text, namely 'Pool Supply Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "swimming_pool" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tailor with a fixed text, namely 'Tailor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "tailor" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tattoo with a fixed text, namely 'Tattoo Parlor' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "tattoo" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tea with a fixed text, namely 'Tea Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "tea" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=telecommunication with a fixed text, namely 'Telecom Retail Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "telecommunication" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=ticket with a fixed text, namely 'Ticket Seller' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "ticket" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tiles with a fixed text, namely 'Tile Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "tiles" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tobacco with a fixed text, namely 'Tobacco Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "tobacco" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tool_hire with a fixed text, namely 'Tool Rental' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "tool_hire" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=toys with a fixed text, namely 'Toy Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "toys" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trade with a fixed text, namely 'Trade Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "trade" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=travel_agency with a fixed text, namely 'Travel Agency' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "travel_agency" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=trophy with a fixed text, namely 'Trophy Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "trophy" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=tyres with a fixed text, namely 'Tire Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "tyres" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=vacuum_cleaner with a fixed text, namely 'Vacuum Cleaner Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "vacuum_cleaner" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=variety_store with a fixed text, namely 'Variety Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "variety_store" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video with a fixed text, namely 'Video Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "video" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=video_games with a fixed text, namely 'Video Game Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "video_games" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=watches with a fixed text, namely 'Watches Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "watches" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water with a fixed text, namely 'Drinking Water Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "water" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=water_sports with a fixed text, namely 'Watersport/Swim Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "water_sports" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=weapons with a fixed text, namely 'Weapon Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "weapons" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wholesale with a fixed text, namely 'Wholesale Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "wholesale" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wigs with a fixed text, namely 'Wig Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "wigs" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=window_blind with a fixed text, namely 'Window Blind Store' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "window_blind" - }, - { - "key": "shop", - "description": "Layer 'Shop' shows shop=wine with a fixed text, namely 'Wine Shop' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Sports')", - "value": "wine" - }, { "key": "opening_hours", "description": "Layer 'Shop' shows and asks freeform values for key 'opening_hours' (in the MapComplete.osm.be theme 'Sports')" diff --git a/Docs/TagInfo/mapcomplete_street_lighting.json b/Docs/TagInfo/mapcomplete_street_lighting.json index d2798787d..0147de7e5 100644 --- a/Docs/TagInfo/mapcomplete_street_lighting.json +++ b/Docs/TagInfo/mapcomplete_street_lighting.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Street Lighting has a layer Street Lamps showing features with this tag", "value": "street_lamp" }, + { + "key": "id", + "description": "Layer 'Street Lamps' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Street Lighting') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Street Lamps 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" @@ -205,6 +209,10 @@ "key": "lit", "description": "The MapComplete theme Street Lighting has a layer Lit streets showing features with this tag" }, + { + "key": "id", + "description": "Layer 'Lit streets' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Street Lighting') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Lit streets 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" @@ -245,6 +253,10 @@ "key": "highway", "description": "The MapComplete theme Street Lighting has a layer All streets showing features with this tag" }, + { + "key": "id", + "description": "Layer 'All streets' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Street Lighting') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'All streets 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" diff --git a/Docs/TagInfo/mapcomplete_surveillance.json b/Docs/TagInfo/mapcomplete_surveillance.json index de44ce25c..67eae7311 100644 --- a/Docs/TagInfo/mapcomplete_surveillance.json +++ b/Docs/TagInfo/mapcomplete_surveillance.json @@ -10,6 +10,18 @@ "contact_email": "pietervdvn@posteo.net" }, "tags": [ + { + "key": "camera:direction", + "description": "The MapComplete theme Surveillance under Surveillance has a layer Direction visualization showing features with this tag" + }, + { + "key": "direction", + "description": "The MapComplete theme Surveillance under Surveillance has a layer Direction visualization showing features with this tag" + }, + { + "key": "id", + "description": "Layer 'Direction visualization' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Surveillance under Surveillance') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "man_made", "description": "The MapComplete theme Surveillance under Surveillance has a layer Surveillance camera's showing features with this tag", @@ -30,6 +42,10 @@ "description": "The MapComplete theme Surveillance under Surveillance has a layer Surveillance camera's showing features with this tag", "value": "ANPR" }, + { + "key": "id", + "description": "Layer 'Surveillance camera's' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Surveillance under Surveillance') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "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" diff --git a/Docs/TagInfo/mapcomplete_toilets.json b/Docs/TagInfo/mapcomplete_toilets.json index ab88bf492..247ab7767 100644 --- a/Docs/TagInfo/mapcomplete_toilets.json +++ b/Docs/TagInfo/mapcomplete_toilets.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Open Toilet Map has a layer Toilets showing features with this tag", "value": "toilets" }, + { + "key": "id", + "description": "Layer 'Toilets' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Toilets 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" @@ -249,6 +253,10 @@ "description": "The MapComplete theme Open Toilet Map has a layer Toilets at other amenities showing features with this tag", "value": "yes" }, + { + "key": "id", + "description": "Layer 'Toilets at other amenities' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Toilets at other amenities 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" @@ -360,80 +368,6 @@ "key": "toilets:door:width", "description": "Layer 'Toilets at other amenities' shows and asks freeform values for key 'toilets:door:width' (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if toilets:wheelchair=yes|toilets:wheelchair=designated)" }, - { - "key": "toilets:position", - "description": "Layer 'Toilets at other amenities' shows toilets:position=seated with a fixed text, namely 'There are only seated toilets' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map')", - "value": "seated" - }, - { - "key": "toilets:position", - "description": "Layer 'Toilets at other amenities' shows toilets:position=urinal with a fixed text, namely 'There are only urinals here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map')", - "value": "urinal" - }, - { - "key": "toilets:position", - "description": "Layer 'Toilets at other amenities' shows toilets:position=squat with a fixed text, namely 'There are only squat toilets here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map')", - "value": "squat" - }, - { - "key": "toilets:position", - "description": "Layer 'Toilets at other amenities' shows toilets:position=seated;urinal with a fixed text, namely 'Both seated toilets and urinals are available here' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map')", - "value": "seated;urinal" - }, - { - "key": "changing_table", - "description": "Layer 'Toilets at other amenities' shows changing_table=yes with a fixed text, namely 'A changing table is available' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map')", - "value": "yes" - }, - { - "key": "changing_table", - "description": "Layer 'Toilets at other amenities' shows changing_table=no with a fixed text, namely 'No changing table is available' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map')", - "value": "no" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows and asks freeform values for key 'changing_table:location' (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if changing_table=yes)" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows changing_table:location=female_toilet with a fixed text, namely 'The changing table is in the toilet for women. ' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if changing_table=yes)", - "value": "female_toilet" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows changing_table:location=male_toilet with a fixed text, namely 'The changing table is in the toilet for men. ' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if changing_table=yes)", - "value": "male_toilet" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows changing_table:location=wheelchair_toilet with a fixed text, namely 'The changing table is in the toilet for wheelchair users. ' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if changing_table=yes)", - "value": "wheelchair_toilet" - }, - { - "key": "changing_table:location", - "description": "Layer 'Toilets at other amenities' shows changing_table:location=dedicated_room with a fixed text, namely 'The changing table is in a dedicated room. ' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if changing_table=yes)", - "value": "dedicated_room" - }, - { - "key": "toilets:handwashing", - "description": "Layer 'Toilets at other amenities' shows toilets:handwashing=yes with a fixed text, namely 'This toilets have a sink to wash your hands' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map')", - "value": "yes" - }, - { - "key": "toilets:handwashing", - "description": "Layer 'Toilets at other amenities' shows toilets:handwashing=no with a fixed text, namely 'This toilets don't have a sink to wash your hands' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map')", - "value": "no" - }, - { - "key": "toilets:paper_supplied", - "description": "Layer 'Toilets at other amenities' shows toilets:paper_supplied=yes with a fixed text, namely 'This toilet is equipped with toilet paper' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if toilets:position!=urinal)", - "value": "yes" - }, - { - "key": "toilets:paper_supplied", - "description": "Layer 'Toilets at other amenities' shows toilets:paper_supplied=no with a fixed text, namely 'You have to bring your own toilet paper to this toilet' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Open Toilet Map') (This is only shown if toilets:position!=urinal)", - "value": "no" - }, { "key": "toilets:description", "description": "Layer 'Toilets at other amenities' shows and asks freeform values for key 'toilets:description' (in the MapComplete.osm.be theme 'Open Toilet Map')" diff --git a/Docs/TagInfo/mapcomplete_transit.json b/Docs/TagInfo/mapcomplete_transit.json index 9494bedcd..e0c3485cc 100644 --- a/Docs/TagInfo/mapcomplete_transit.json +++ b/Docs/TagInfo/mapcomplete_transit.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Bus routes has a layer Transit Stops showing features with this tag", "value": "bus_stop" }, + { + "key": "id", + "description": "Layer 'Transit Stops' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bus routes') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Transit Stops' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Bus routes')" @@ -170,6 +174,10 @@ "description": "The MapComplete theme Bus routes has a layer Bus lines showing features with this tag", "value": "bus" }, + { + "key": "id", + "description": "Layer 'Bus lines' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bus routes') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "name", "description": "Layer 'Bus lines' shows and asks freeform values for key 'name' (in the MapComplete.osm.be theme 'Bus routes')" @@ -203,6 +211,10 @@ "description": "The MapComplete theme Bus routes has a layer Bike parking showing features with this tag", "value": "bicycle_parking" }, + { + "key": "id", + "description": "Layer 'Bike parking' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bus routes') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Bike parking 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" @@ -340,6 +352,10 @@ "description": "The MapComplete theme Bus routes has a layer Parking showing features with this tag", "value": "parking" }, + { + "key": "id", + "description": "Layer 'Parking' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bus routes') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Parking 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" @@ -467,6 +483,10 @@ "key": "shelter_type", "description": "The MapComplete theme Bus routes has a layer Shelter showing features with this tag", "value": "public_transport" + }, + { + "key": "id", + "description": "Layer 'Shelter' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Bus routes') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" } ] } \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_trees.json b/Docs/TagInfo/mapcomplete_trees.json index ce35ea2c5..d4e270bf5 100644 --- a/Docs/TagInfo/mapcomplete_trees.json +++ b/Docs/TagInfo/mapcomplete_trees.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Trees has a layer Tree showing features with this tag", "value": "tree" }, + { + "key": "id", + "description": "Layer 'Tree' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Trees') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Tree 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" diff --git a/Docs/TagInfo/mapcomplete_uk_addresses.json b/Docs/TagInfo/mapcomplete_uk_addresses.json deleted file mode 100644 index 92774e2f1..000000000 --- a/Docs/TagInfo/mapcomplete_uk_addresses.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "data_format": 1, - "project": { - "name": "MapComplete UK Addresses", - "description": "Help to build an open dataset of UK addresses", - "project_url": "https://mapcomplete.osm.be/uk_addresses", - "doc_url": "https://github.com/pietervdvn/MapComplete/tree/master/assets/themes/", - "icon_url": "https://mapcomplete.osm.be/assets/themes/uk_addresses/housenumber_unknown.svg", - "contact_name": "Pieter Vander Vennet, Pieter Vander Vennet, Rob Nickerson, Russ Garrett", - "contact_email": "pietervdvn@posteo.net" - }, - "tags": [ - { - "key": "inspireid", - "description": "The MapComplete theme UK Addresses has a layer Addresses to check showing features with this tag" - }, - { - "key": "addr:housenumber", - "description": "The MapComplete theme UK Addresses has a layer Known addresses in OSM showing features with this tag" - }, - { - "key": "addr:street", - "description": "The MapComplete theme UK Addresses has a layer Known addresses in OSM showing features with this tag" - }, - { - "key": "addr:housenumber", - "description": "Layer 'Known addresses in OSM' shows and asks freeform values for key 'addr:housenumber' (in the MapComplete.osm.be theme 'UK Addresses')" - }, - { - "key": "nohousenumber", - "description": "Layer 'Known addresses in OSM' shows nohousenumber=yes with a fixed text, namely 'This building has no house number' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'UK Addresses')", - "value": "yes" - }, - { - "key": "addr:street", - "description": "Layer 'Known addresses in OSM' shows and asks freeform values for key 'addr:street' (in the MapComplete.osm.be theme 'UK Addresses')" - } - ] -} \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_walls_and_buildings.json b/Docs/TagInfo/mapcomplete_walls_and_buildings.json deleted file mode 100644 index efffff8ae..000000000 --- a/Docs/TagInfo/mapcomplete_walls_and_buildings.json +++ /dev/null @@ -1,223 +0,0 @@ -{ - "data_format": 1, - "project": { - "name": "MapComplete Walls and buildings", - "description": "Special builtin layer providing all walls and buildings", - "project_url": "https://mapcomplete.osm.be/walls_and_buildings", - "doc_url": "https://github.com/pietervdvn/MapComplete/tree/master/assets/themes/", - "icon_url": "https://mapcomplete.osm.be/assets/layers/walls_and_buildings/walls_and_buildings.png", - "contact_name": "Pieter Vander Vennet, MapComplete", - "contact_email": "pietervdvn@posteo.net" - }, - "tags": [ - { - "key": "highway", - "description": "The MapComplete theme Walls and buildings has a layer Pedestrian paths showing features with this tag", - "value": "footway" - }, - { - "key": "highway", - "description": "The MapComplete theme Walls and buildings has a layer Pedestrian paths showing features with this tag", - "value": "path" - }, - { - "key": "highway", - "description": "The MapComplete theme Walls and buildings has a layer Pedestrian paths showing features with this tag", - "value": "corridor" - }, - { - "key": "highway", - "description": "The MapComplete theme Walls and buildings has a layer Pedestrian paths showing features with this tag", - "value": "steps" - }, - { - "key": "entrance", - "description": "The MapComplete theme Walls and buildings has a layer Entrance showing features with this tag" - }, - { - "key": "indoor", - "description": "The MapComplete theme Walls and buildings has a layer Entrance showing features with this tag", - "value": "door" - }, - { - "key": "image", - "description": "The layer 'Entrance allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "mapillary", - "description": "The layer 'Entrance allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikidata", - "description": "The layer 'Entrance allows to upload images and adds them under the 'image'-tag (and image:0, image:1, ... for multiple images). Furhtermore, this layer shows images based on the keys image, wikidata, wikipedia, wikimedia_commons and mapillary" - }, - { - "key": "wikipedia", - "description": "The layer 'Entrance 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": "entrance", - "description": "Layer 'Entrance' shows entrance=yes with a fixed text, namely 'No specific entrance type is known' (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "yes" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows indoor=door with a fixed text, namely 'This is an indoor door, separating a room or a corridor within a single building' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings') Picking this answer will delete the key entrance.", - "value": "" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows indoor=door with a fixed text, namely 'This is an indoor door, separating a room or a corridor within a single building' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "door" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=main with a fixed text, namely 'This is the main entrance' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=main with a fixed text, namely 'This is the main entrance' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "main" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=secondary with a fixed text, namely 'This is a secondary entrance' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=secondary with a fixed text, namely 'This is a secondary entrance' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "secondary" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=service with a fixed text, namely 'This is a service entrance - normally only used for employees, delivery, …' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=service with a fixed text, namely 'This is a service entrance - normally only used for employees, delivery, …' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "service" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=exit with a fixed text, namely 'This is an exit where one can not enter' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=exit with a fixed text, namely 'This is an exit where one can not enter' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "exit" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=entrance with a fixed text, namely 'This is an entrance where one can only enter (but not exit)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=entrance with a fixed text, namely 'This is an entrance where one can only enter (but not exit)' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "entrance" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=emergency with a fixed text, namely 'This is emergency exit' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=emergency with a fixed text, namely 'This is emergency exit' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "emergency" - }, - { - "key": "indoor", - "description": "Layer 'Entrance' shows entrance=home with a fixed text, namely 'This is the entrance to a private home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings') Picking this answer will delete the key indoor.", - "value": "" - }, - { - "key": "entrance", - "description": "Layer 'Entrance' shows entrance=home with a fixed text, namely 'This is the entrance to a private home' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "home" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=yes with a fixed text, namely 'The door type is not known' (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "yes" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=hinged with a fixed text, namely 'A classical, hinged door supported by joints' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "hinged" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=revolving with a fixed text, namely 'A revolving door which hangs on a central shaft, rotating within a cylindrical enclosure' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "revolving" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=sliding with a fixed text, namely 'A sliding door where the door slides sidewards, typically parallel with a wall' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "sliding" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=overhead with a fixed text, namely 'A door which rolls from overhead, typically seen for garages' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "overhead" - }, - { - "key": "door", - "description": "Layer 'Entrance' shows door=no with a fixed text, namely 'This is an entrance without a physical door' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "no" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=yes with a fixed text, namely 'This is an automatic door' (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "yes" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=no with a fixed text, namely 'This door is not automated' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "no" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=motion with a fixed text, namely 'This door will open automatically when motion is detected' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "motion" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=floor with a fixed text, namely 'This door will open automatically when a sensor in the floor is triggered' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "floor" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=button with a fixed text, namely 'This door will open automatically when a button is pressed' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "button" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=slowdown_button with a fixed text, namely 'This door revolves automatically all the time, but has a button to slow it down, e.g. for wheelchair users' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "slowdown_button" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=continuous with a fixed text, namely 'This door revolves automatically all the time' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "continuous" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=serviced_on_button_press with a fixed text, namely 'This door will be opened by staff when requested by pressing a button' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "serviced_on_button_press" - }, - { - "key": "automatic_door", - "description": "Layer 'Entrance' shows automatic_door=serviced_on_request with a fixed text, namely 'This door will be opened by staff when requested' and allows to pick this as a default answer (in the MapComplete.osm.be theme 'Walls and buildings')", - "value": "serviced_on_request" - }, - { - "key": "width", - "description": "Layer 'Entrance' shows and asks freeform values for key 'width' (in the MapComplete.osm.be theme 'Walls and buildings')" - } - ] -} \ No newline at end of file diff --git a/Docs/TagInfo/mapcomplete_waste.json b/Docs/TagInfo/mapcomplete_waste.json index c5c27a23c..fdbb16f0b 100644 --- a/Docs/TagInfo/mapcomplete_waste.json +++ b/Docs/TagInfo/mapcomplete_waste.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Waste has a layer Waste Basket showing features with this tag", "value": "waste_basket" }, + { + "key": "id", + "description": "Layer 'Waste Basket' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Waste') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Waste Basket 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" @@ -96,6 +100,10 @@ "description": "The MapComplete theme Waste has a layer Recycling showing features with this tag", "value": "recycling" }, + { + "key": "id", + "description": "Layer 'Recycling' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Waste') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Recycling 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" @@ -347,6 +355,10 @@ "description": "The MapComplete theme Waste has a layer Waste Disposal Bins showing features with this tag", "value": "waste_disposal" }, + { + "key": "id", + "description": "Layer 'Waste Disposal Bins' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Waste') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Waste Disposal Bins 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" diff --git a/Docs/TagInfo/mapcomplete_waste_basket.json b/Docs/TagInfo/mapcomplete_waste_basket.json index c63b5d9a2..fef61fa62 100644 --- a/Docs/TagInfo/mapcomplete_waste_basket.json +++ b/Docs/TagInfo/mapcomplete_waste_basket.json @@ -15,6 +15,10 @@ "description": "The MapComplete theme Waste Basket has a layer Waste Basket showing features with this tag", "value": "waste_basket" }, + { + "key": "id", + "description": "Layer 'Waste Basket' shows id~.+ with a fixed text, namely 'You just created this element! Thanks for sharing this info with the world and helping people worldwide.' (in the MapComplete.osm.be theme 'Waste Basket') (This is only shown if _backend~.+&_last_edit:passed_time<300&|_version_number=1)" + }, { "key": "image", "description": "The layer 'Waste Basket 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" diff --git a/Docs/Themes/advertising.md b/Docs/Themes/advertising.md index 109be29eb..f2440bb98 100644 --- a/Docs/Themes/advertising.md +++ b/Docs/Themes/advertising.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/aed.md b/Docs/Themes/aed.md index 412b84d10..fe3e4484a 100644 --- a/Docs/Themes/aed.md +++ b/Docs/Themes/aed.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/artwork.md b/Docs/Themes/artwork.md index 9449dad6d..6b002069b 100644 --- a/Docs/Themes/artwork.md +++ b/Docs/Themes/artwork.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/atm.md b/Docs/Themes/atm.md index 2b8701626..c34128e5a 100644 --- a/Docs/Themes/atm.md +++ b/Docs/Themes/atm.md @@ -14,11 +14,14 @@ This theme contains the following layers: - [atm](../Layers/atm.md) - [banks_with_atm](../Layers/banks_with_atm.md) - [bank](../Layers/bank.md) + - [maproulette_challenge](../Layers/maproulette_challenge.md) - [selected_element](../Layers/selected_element.md) - [gps_location](../Layers/gps_location.md) - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/bag.md b/Docs/Themes/bag.md index f64655199..094a9e7a0 100644 --- a/Docs/Themes/bag.md +++ b/Docs/Themes/bag.md @@ -11,7 +11,6 @@ This theme contains the following layers: - - [type_node](../Layers/type_node.md) - [osm:buildings](../Layers/osm:buildings.md) - [osm:adresses](../Layers/osm:adresses.md) - [bag:pand](../Layers/bag:pand.md) @@ -21,6 +20,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/benches.md b/Docs/Themes/benches.md index 14b9b864c..8cc3c1f5b 100644 --- a/Docs/Themes/benches.md +++ b/Docs/Themes/benches.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/bicycle_rental.md b/Docs/Themes/bicycle_rental.md index 923bcd139..7372dbe11 100644 --- a/Docs/Themes/bicycle_rental.md +++ b/Docs/Themes/bicycle_rental.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/bicyclelib.md b/Docs/Themes/bicyclelib.md index d407578a5..5dd671af6 100644 --- a/Docs/Themes/bicyclelib.md +++ b/Docs/Themes/bicyclelib.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/binoculars.md b/Docs/Themes/binoculars.md index 6694ef1ce..0cf65f2cf 100644 --- a/Docs/Themes/binoculars.md +++ b/Docs/Themes/binoculars.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/blind_osm.md b/Docs/Themes/blind_osm.md index 45c759bcf..b85df4915 100644 --- a/Docs/Themes/blind_osm.md +++ b/Docs/Themes/blind_osm.md @@ -22,6 +22,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/bookcases.md b/Docs/Themes/bookcases.md index bcbb926b8..fbe349309 100644 --- a/Docs/Themes/bookcases.md +++ b/Docs/Themes/bookcases.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/buurtnatuur.md b/Docs/Themes/buurtnatuur.md index 65405502c..563498d5b 100644 --- a/Docs/Themes/buurtnatuur.md +++ b/Docs/Themes/buurtnatuur.md @@ -20,6 +20,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/cafes_and_pubs.md b/Docs/Themes/cafes_and_pubs.md index eb02d783d..a845fb492 100644 --- a/Docs/Themes/cafes_and_pubs.md +++ b/Docs/Themes/cafes_and_pubs.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/campersite.md b/Docs/Themes/campersite.md index 90e6a5480..e1e557e72 100644 --- a/Docs/Themes/campersite.md +++ b/Docs/Themes/campersite.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/charging_stations.md b/Docs/Themes/charging_stations.md index a51910133..24c9c8445 100644 --- a/Docs/Themes/charging_stations.md +++ b/Docs/Themes/charging_stations.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/climbing.md b/Docs/Themes/climbing.md index 3d2b8ac89..88d595a7b 100644 --- a/Docs/Themes/climbing.md +++ b/Docs/Themes/climbing.md @@ -21,6 +21,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/clock.md b/Docs/Themes/clock.md index fc080b16a..4c1923208 100644 --- a/Docs/Themes/clock.md +++ b/Docs/Themes/clock.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/cycle_highways.md b/Docs/Themes/cycle_highways.md index 0b52ab17e..e80239b63 100644 --- a/Docs/Themes/cycle_highways.md +++ b/Docs/Themes/cycle_highways.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/cycle_infra.md b/Docs/Themes/cycle_infra.md index 1072bf2eb..4e6b6e718 100644 --- a/Docs/Themes/cycle_infra.md +++ b/Docs/Themes/cycle_infra.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/cyclenodes.md b/Docs/Themes/cyclenodes.md index 91ecf714e..35c3bb656 100644 --- a/Docs/Themes/cyclenodes.md +++ b/Docs/Themes/cyclenodes.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/cyclestreets.md b/Docs/Themes/cyclestreets.md index 0aa3c02da..2bcb8a93a 100644 --- a/Docs/Themes/cyclestreets.md +++ b/Docs/Themes/cyclestreets.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/cyclofix.md b/Docs/Themes/cyclofix.md index 88a5f52f9..d0481b418 100644 --- a/Docs/Themes/cyclofix.md +++ b/Docs/Themes/cyclofix.md @@ -29,6 +29,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/drinking_water.md b/Docs/Themes/drinking_water.md index 39cbb220e..16bbce6cc 100644 --- a/Docs/Themes/drinking_water.md +++ b/Docs/Themes/drinking_water.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/education.md b/Docs/Themes/education.md index d8f5f89d8..aa4a39b83 100644 --- a/Docs/Themes/education.md +++ b/Docs/Themes/education.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/etymology.md b/Docs/Themes/etymology.md index a9b25f871..111cb90c3 100644 --- a/Docs/Themes/etymology.md +++ b/Docs/Themes/etymology.md @@ -24,6 +24,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/facadegardens.md b/Docs/Themes/facadegardens.md index 21db11ee4..2390bb62c 100644 --- a/Docs/Themes/facadegardens.md +++ b/Docs/Themes/facadegardens.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/food.md b/Docs/Themes/food.md index 6fce414d9..21953d570 100644 --- a/Docs/Themes/food.md +++ b/Docs/Themes/food.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/fritures.md b/Docs/Themes/fritures.md index 55ed3cd99..d6b302a58 100644 --- a/Docs/Themes/fritures.md +++ b/Docs/Themes/fritures.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/fruit_trees.md b/Docs/Themes/fruit_trees.md index 54d72fc18..fdb9ed1c2 100644 --- a/Docs/Themes/fruit_trees.md +++ b/Docs/Themes/fruit_trees.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/ghostbikes.md b/Docs/Themes/ghostbikes.md index 3f9581afa..5bef85151 100644 --- a/Docs/Themes/ghostbikes.md +++ b/Docs/Themes/ghostbikes.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/grb.md b/Docs/Themes/grb.md index 24383d6e5..9af4452d8 100644 --- a/Docs/Themes/grb.md +++ b/Docs/Themes/grb.md @@ -12,19 +12,20 @@ This theme contains the following layers: - [named_streets](../Layers/named_streets.md) - - [type_node](../Layers/type_node.md) - [osm-buildings](../Layers/osm-buildings.md) + - [grb](../Layers/grb.md) - [service_ways](../Layers/service_ways.md) - [generic_osm_object](../Layers/generic_osm_object.md) - [address](../Layers/address.md) - [crab_address](../Layers/crab_address.md) - - [grb](../Layers/grb.md) - [current_view](../Layers/current_view.md) - [selected_element](../Layers/selected_element.md) - [gps_location](../Layers/gps_location.md) - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/grb_fixme.md b/Docs/Themes/grb_fixme.md index df16092b3..18f44e4d9 100644 --- a/Docs/Themes/grb_fixme.md +++ b/Docs/Themes/grb_fixme.md @@ -20,6 +20,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/hackerspaces.md b/Docs/Themes/hackerspaces.md index 4074f4399..5366265e5 100644 --- a/Docs/Themes/hackerspaces.md +++ b/Docs/Themes/hackerspaces.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/hailhydrant.md b/Docs/Themes/hailhydrant.md index 22fed0054..7c4b62b57 100644 --- a/Docs/Themes/hailhydrant.md +++ b/Docs/Themes/hailhydrant.md @@ -20,6 +20,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/healthcare.md b/Docs/Themes/healthcare.md index 67c769a70..658f9e346 100644 --- a/Docs/Themes/healthcare.md +++ b/Docs/Themes/healthcare.md @@ -23,6 +23,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/hotels.md b/Docs/Themes/hotels.md index fc072e535..6cd0b14b2 100644 --- a/Docs/Themes/hotels.md +++ b/Docs/Themes/hotels.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/indoors.md b/Docs/Themes/indoors.md index c347bcdcd..5ed0b4b71 100644 --- a/Docs/Themes/indoors.md +++ b/Docs/Themes/indoors.md @@ -21,6 +21,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/kerbs_and_crossings.md b/Docs/Themes/kerbs_and_crossings.md index 4dbcf7ca3..b35fb4ed9 100644 --- a/Docs/Themes/kerbs_and_crossings.md +++ b/Docs/Themes/kerbs_and_crossings.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/mapcomplete-changes.md b/Docs/Themes/mapcomplete-changes.md index 5b69e7f18..3ec4b2938 100644 --- a/Docs/Themes/mapcomplete-changes.md +++ b/Docs/Themes/mapcomplete-changes.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/maproulette.md b/Docs/Themes/maproulette.md index 5d43c32c3..6b6c6f21d 100644 --- a/Docs/Themes/maproulette.md +++ b/Docs/Themes/maproulette.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/maps.md b/Docs/Themes/maps.md index 4fd08f1a4..effce72c6 100644 --- a/Docs/Themes/maps.md +++ b/Docs/Themes/maps.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/maxspeed.md b/Docs/Themes/maxspeed.md index 840ab76c3..9937b1888 100644 --- a/Docs/Themes/maxspeed.md +++ b/Docs/Themes/maxspeed.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/nature.md b/Docs/Themes/nature.md index b848ea574..7e16dd813 100644 --- a/Docs/Themes/nature.md +++ b/Docs/Themes/nature.md @@ -24,6 +24,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/natuurpunt.md b/Docs/Themes/natuurpunt.md deleted file mode 100644 index d819447ea..000000000 --- a/Docs/Themes/natuurpunt.md +++ /dev/null @@ -1,39 +0,0 @@ -[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources) - - The map of Natuurpunt ( [natuurpunt](https://mapcomplete.osm.be/natuurpunt) ) -------------------------------------------------------------------------------- - - - -On this map you can find all the nature reserves that Natuurpunt offers - -This theme contains the following layers: - - - - - [nature_reserve](../Layers/nature_reserve.md) - - [nature_reserve_centerpoints](../Layers/nature_reserve_centerpoints.md) - - [visitor_information_centre](../Layers/visitor_information_centre.md) - - [trail](../Layers/trail.md) - - [toilet](../Layers/toilet.md) - - [birdhide](../Layers/birdhide.md) - - [picnic_table](../Layers/picnic_table.md) - - [drinking_water](../Layers/drinking_water.md) - - [parking](../Layers/parking.md) - - [information_board](../Layers/information_board.md) - - [bench](../Layers/bench.md) - - [gps_track](../Layers/gps_track.md) - - [selected_element](../Layers/selected_element.md) - - [gps_location](../Layers/gps_location.md) - - [gps_location_history](../Layers/gps_location_history.md) - - [home_location](../Layers/home_location.md) - - -Available languages: - - - - - nl - - -This document is autogenerated from [assets/themes/natuurpunt/natuurpunt.json](https://github.com/pietervdvn/MapComplete/blob/develop/assets/themes/natuurpunt/natuurpunt.json) diff --git a/Docs/Themes/notes.md b/Docs/Themes/notes.md index 47bb77fe7..c1c6ece10 100644 --- a/Docs/Themes/notes.md +++ b/Docs/Themes/notes.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/observation_towers.md b/Docs/Themes/observation_towers.md index 06e5ae7cd..fe9e72782 100644 --- a/Docs/Themes/observation_towers.md +++ b/Docs/Themes/observation_towers.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/onwheels.md b/Docs/Themes/onwheels.md index 58ff97bdc..06fe8f9c1 100644 --- a/Docs/Themes/onwheels.md +++ b/Docs/Themes/onwheels.md @@ -37,6 +37,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/openwindpowermap.md b/Docs/Themes/openwindpowermap.md index dc9370507..8a5355fb2 100644 --- a/Docs/Themes/openwindpowermap.md +++ b/Docs/Themes/openwindpowermap.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/osm_community_index.md b/Docs/Themes/osm_community_index.md index fbccf84f5..83d449ab3 100644 --- a/Docs/Themes/osm_community_index.md +++ b/Docs/Themes/osm_community_index.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/parkings.md b/Docs/Themes/parkings.md index 3e3600700..24c85b1f5 100644 --- a/Docs/Themes/parkings.md +++ b/Docs/Themes/parkings.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/personal.md b/Docs/Themes/personal.md index 0e3822f8a..321cd9958 100644 --- a/Docs/Themes/personal.md +++ b/Docs/Themes/personal.md @@ -39,9 +39,11 @@ This theme contains the following layers: - [climbing_route](../Layers/climbing_route.md) - [clock](../Layers/clock.md) - [crossings](../Layers/crossings.md) + - [current_view](../Layers/current_view.md) - [cycleways_and_roads](../Layers/cycleways_and_roads.md) - [defibrillator](../Layers/defibrillator.md) - [dentist](../Layers/dentist.md) + - [direction](../Layers/direction.md) - [doctors](../Layers/doctors.md) - [dogpark](../Layers/dogpark.md) - [drinking_water](../Layers/drinking_water.md) @@ -68,6 +70,7 @@ This theme contains the following layers: - [maproulette_challenge](../Layers/maproulette_challenge.md) - [maxspeed](../Layers/maxspeed.md) - [nature_reserve](../Layers/nature_reserve.md) + - [note](../Layers/note.md) - [observation_tower](../Layers/observation_tower.md) - [osm_community_index](../Layers/osm_community_index.md) - [parcel_lockers](../Layers/parcel_lockers.md) @@ -111,6 +114,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/pets.md b/Docs/Themes/pets.md index c626724be..259d38a3b 100644 --- a/Docs/Themes/pets.md +++ b/Docs/Themes/pets.md @@ -23,6 +23,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/play_forests.md b/Docs/Themes/play_forests.md index c6894c1b0..31ae3f9a2 100644 --- a/Docs/Themes/play_forests.md +++ b/Docs/Themes/play_forests.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/playgrounds.md b/Docs/Themes/playgrounds.md index 54da48de6..919933469 100644 --- a/Docs/Themes/playgrounds.md +++ b/Docs/Themes/playgrounds.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/postal_codes.md b/Docs/Themes/postal_codes.md index 95db8d2e4..6f72542fd 100644 --- a/Docs/Themes/postal_codes.md +++ b/Docs/Themes/postal_codes.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/postboxes.md b/Docs/Themes/postboxes.md index ab61d0ba8..058e31594 100644 --- a/Docs/Themes/postboxes.md +++ b/Docs/Themes/postboxes.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/rainbow_crossings.md b/Docs/Themes/rainbow_crossings.md index 33a4a84c0..9ec114b46 100644 --- a/Docs/Themes/rainbow_crossings.md +++ b/Docs/Themes/rainbow_crossings.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/shops.md b/Docs/Themes/shops.md index aa91e6e32..6bbb412e9 100644 --- a/Docs/Themes/shops.md +++ b/Docs/Themes/shops.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/sidewalks.md b/Docs/Themes/sidewalks.md index bded59a2a..0faffaf77 100644 --- a/Docs/Themes/sidewalks.md +++ b/Docs/Themes/sidewalks.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/speelplekken.md b/Docs/Themes/speelplekken.md index ce897e1de..c367bf1c1 100644 --- a/Docs/Themes/speelplekken.md +++ b/Docs/Themes/speelplekken.md @@ -15,7 +15,6 @@ This theme contains the following layers: - [play_forest](../Layers/play_forest.md) - [playground](../Layers/playground.md) - [village_green](../Layers/village_green.md) - - [grass_in_parks](../Layers/grass_in_parks.md) - [sport_pitch](../Layers/sport_pitch.md) - [slow_roads](../Layers/slow_roads.md) - [walking_routes](../Layers/walking_routes.md) @@ -24,6 +23,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/sport_pitches.md b/Docs/Themes/sport_pitches.md index 116814d3f..7f67d19a3 100644 --- a/Docs/Themes/sport_pitches.md +++ b/Docs/Themes/sport_pitches.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/sports.md b/Docs/Themes/sports.md index cbe9933ba..056a192b9 100644 --- a/Docs/Themes/sports.md +++ b/Docs/Themes/sports.md @@ -21,6 +21,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/stations.md b/Docs/Themes/stations.md index d5a53a14a..6333e0fc8 100644 --- a/Docs/Themes/stations.md +++ b/Docs/Themes/stations.md @@ -39,6 +39,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/street_lighting.md b/Docs/Themes/street_lighting.md index 3b57edfd7..45ed966dc 100644 --- a/Docs/Themes/street_lighting.md +++ b/Docs/Themes/street_lighting.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/street_lighting_assen.md b/Docs/Themes/street_lighting_assen.md index 9b9ff8721..58261ae55 100644 --- a/Docs/Themes/street_lighting_assen.md +++ b/Docs/Themes/street_lighting_assen.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/surveillance.md b/Docs/Themes/surveillance.md index 1ef6a8b03..890aa1468 100644 --- a/Docs/Themes/surveillance.md +++ b/Docs/Themes/surveillance.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/toerisme_vlaanderen.md b/Docs/Themes/toerisme_vlaanderen.md index e98be92f8..5fa3cdd80 100644 --- a/Docs/Themes/toerisme_vlaanderen.md +++ b/Docs/Themes/toerisme_vlaanderen.md @@ -26,6 +26,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/toilets.md b/Docs/Themes/toilets.md index 5cd93e089..86ac71936 100644 --- a/Docs/Themes/toilets.md +++ b/Docs/Themes/toilets.md @@ -18,6 +18,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/transit.md b/Docs/Themes/transit.md index f8d0b2606..515583810 100644 --- a/Docs/Themes/transit.md +++ b/Docs/Themes/transit.md @@ -21,6 +21,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/trees.md b/Docs/Themes/trees.md index 857b59bc8..3770f43f2 100644 --- a/Docs/Themes/trees.md +++ b/Docs/Themes/trees.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/uk_addresses.md b/Docs/Themes/uk_addresses.md index 852e601a7..f570cf0c9 100644 --- a/Docs/Themes/uk_addresses.md +++ b/Docs/Themes/uk_addresses.md @@ -20,6 +20,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/walls_and_buildings.md b/Docs/Themes/walls_and_buildings.md index 5bafc44fd..e9eb63a64 100644 --- a/Docs/Themes/walls_and_buildings.md +++ b/Docs/Themes/walls_and_buildings.md @@ -20,6 +20,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/waste.md b/Docs/Themes/waste.md index 5551ccedd..244119e88 100644 --- a/Docs/Themes/waste.md +++ b/Docs/Themes/waste.md @@ -19,6 +19,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/waste_assen.md b/Docs/Themes/waste_assen.md index 7a6ab99ce..3a7a3ae9d 100644 --- a/Docs/Themes/waste_assen.md +++ b/Docs/Themes/waste_assen.md @@ -21,6 +21,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/waste_basket.md b/Docs/Themes/waste_basket.md index f60723696..5c8ce0928 100644 --- a/Docs/Themes/waste_basket.md +++ b/Docs/Themes/waste_basket.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/Themes/width.md b/Docs/Themes/width.md index b62479576..ded595c03 100644 --- a/Docs/Themes/width.md +++ b/Docs/Themes/width.md @@ -17,6 +17,8 @@ This theme contains the following layers: - [gps_location_history](../Layers/gps_location_history.md) - [home_location](../Layers/home_location.md) - [gps_track](../Layers/gps_track.md) + - [range](../Layers/range.md) + - [last_click](../Layers/last_click.md) Available languages: diff --git a/Docs/URL_Parameters.md b/Docs/URL_Parameters.md index c9c10727f..70a21fc3f 100644 --- a/Docs/URL_Parameters.md +++ b/Docs/URL_Parameters.md @@ -9,9 +9,9 @@ 1. [URL-parameters and URL-hash](#url-parameters-and-url-hash) - [What is a URL parameter?](#what-is-a-url-parameter) - - [language](#language) - [fs-translation-mode](#fs-translation-mode) - - [tab](#tab) + - [backend](#backend) + - [fake-user](#fake-user) - [fs-userbadge](#fs-userbadge) - [fs-search](#fs-search) - [fs-background](#fs-background) @@ -25,11 +25,8 @@ - [fs-geolocation](#fs-geolocation) - [fs-all-questions](#fs-all-questions) - [fs-export](#fs-export) - - [fs-pdf](#fs-pdf) - - [backend](#backend) - [test](#test) - [debug](#debug) - - [fake-user](#fake-user) - [overpassUrl](#overpassurl) - [overpassTimeout](#overpasstimeout) - [overpassMaxZoom](#overpassmaxzoom) @@ -64,13 +61,6 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case. - language ----------- - - The language to display mapcomplete in. Will be ignored in case a logged-in-user did set their language before. If the specified language does not exist, it will default to the first language in the theme. No default value set - - - fs-translation-mode --------------------- @@ -78,10 +68,17 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case. - tab ------ + backend +--------- - The tab that is shown in the welcome-message. The default value is _0_ + The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test' The default value is _osm_ + + + + fake-user +----------- + + If true, 'dryrun' mode is activated and a fake user account is loaded The default value is _false_ @@ -172,21 +169,7 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case. fs-export ----------- - Enable the export as GeoJSON and CSV button The default value is _false_ - - - - fs-pdf --------- - - Enable the PDF download button The default value is _false_ - - - - backend ---------- - - The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test' The default value is _osm_ + Enable the export as GeoJSON and CSV button The default value is _true_ @@ -204,13 +187,6 @@ Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case. - fake-user ------------ - - If true, 'dryrun' mode is activated and a fake user account is loaded The default value is _false_ - - - overpassUrl ------------- diff --git a/Docs/wikiIndex.txt b/Docs/wikiIndex.txt index c89788585..7438fa3d4 100644 --- a/Docs/wikiIndex.txt +++ b/Docs/wikiIndex.txt @@ -266,7 +266,7 @@ |name= [https://mapcomplete.osm.be/ghostbikes ghostbikes] |region= Worldwide |lang= {{#language:en|en}}, {{#language:nl|en}}, {{#language:de|en}}, {{#language:ja|en}}, {{#language:zh_Hant|en}}, {{#language:fr|en}}, {{#language:it|en}}, {{#language:hu|en}}, {{#language:da|en}}, {{#language:cs|en}}, {{#language:es|en}}, {{#language:ca|en}} -|descr= A MapComplete theme: A ghost bike is a memorial for a cyclist who died in a traffic accident, in the form of a white bicycle placed permanently near the accident location +|descr= A MapComplete theme: A |material= {{yes|[https://mapcomplete.osm.be/ Yes]}} |image= MapComplete_Screenshot.png |genre= POI, editor, ghostbikes diff --git a/Logic/Actors/AvailableBaseLayers.ts b/Logic/Actors/AvailableBaseLayers.ts deleted file mode 100644 index f6de0451a..000000000 --- a/Logic/Actors/AvailableBaseLayers.ts +++ /dev/null @@ -1,51 +0,0 @@ -import BaseLayer from "../../Models/BaseLayer" -import { ImmutableStore, Store, UIEventSource } from "../UIEventSource" -import Loc from "../../Models/Loc" - -export interface AvailableBaseLayersObj { - readonly osmCarto: BaseLayer - layerOverview: BaseLayer[] - - AvailableLayersAt(location: Store): Store - - SelectBestLayerAccordingTo( - location: Store, - preferedCategory: Store - ): Store -} - -/** - * Calculates which layers are available at the current location - * Changes the basemap - */ -export default class AvailableBaseLayers { - public static layerOverview: BaseLayer[] - public static osmCarto: BaseLayer - - private static implementation: AvailableBaseLayersObj - - static AvailableLayersAt(location: Store): Store { - return ( - AvailableBaseLayers.implementation?.AvailableLayersAt(location) ?? - new ImmutableStore([]) - ) - } - - static SelectBestLayerAccordingTo( - location: Store, - preferedCategory: UIEventSource - ): Store { - return ( - AvailableBaseLayers.implementation?.SelectBestLayerAccordingTo( - location, - preferedCategory - ) ?? new ImmutableStore(undefined) - ) - } - - public static implement(backend: AvailableBaseLayersObj) { - AvailableBaseLayers.layerOverview = backend.layerOverview - AvailableBaseLayers.osmCarto = backend.osmCarto - AvailableBaseLayers.implementation = backend - } -} diff --git a/Logic/Actors/AvailableBaseLayersImplementation.ts b/Logic/Actors/AvailableBaseLayersImplementation.ts deleted file mode 100644 index 8551db524..000000000 --- a/Logic/Actors/AvailableBaseLayersImplementation.ts +++ /dev/null @@ -1,309 +0,0 @@ -import BaseLayer from "../../Models/BaseLayer" -import { Store, Stores } from "../UIEventSource" -import Loc from "../../Models/Loc" -import { GeoOperations } from "../GeoOperations" -import * as editorlayerindex from "../../assets/editor-layer-index.json" -import * as L from "leaflet" -import { TileLayer } from "leaflet" -import * as X from "leaflet-providers" -import { Utils } from "../../Utils" -import { AvailableBaseLayersObj } from "./AvailableBaseLayers" -import { BBox } from "../BBox" - -export default class AvailableBaseLayersImplementation implements AvailableBaseLayersObj { - public readonly osmCarto: BaseLayer = { - id: "osm", - name: "OpenStreetMap", - layer: () => - AvailableBaseLayersImplementation.CreateBackgroundLayer( - "osm", - "OpenStreetMap", - "https://tile.openstreetmap.org/{z}/{x}/{y}.png", - "OpenStreetMap", - "https://openStreetMap.org/copyright", - 19, - false, - false - ), - feature: null, - max_zoom: 19, - min_zoom: 0, - isBest: true, // Of course, OpenStreetMap is the best map! - category: "osmbasedmap", - } - - public readonly layerOverview = AvailableBaseLayersImplementation.LoadRasterIndex().concat( - AvailableBaseLayersImplementation.LoadProviderIndex() - ) - public readonly globalLayers = this.layerOverview.filter( - (layer) => layer.feature?.geometry === undefined || layer.feature?.geometry === null - ) - public readonly localLayers = this.layerOverview.filter( - (layer) => layer.feature?.geometry !== undefined && layer.feature?.geometry !== null - ) - - private static LoadRasterIndex(): BaseLayer[] { - const layers: BaseLayer[] = [] - // @ts-ignore - const features = editorlayerindex.features - for (const i in features) { - const layer = features[i] - const props = layer.properties - - if (props.type === "bing") { - // A lot of work to implement - see https://github.com/pietervdvn/MapComplete/issues/648 - continue - } - - if (props.id === "MAPNIK") { - // Already added by default - continue - } - - if (props.overlay) { - continue - } - - if (props.url.toLowerCase().indexOf("apikey") > 0) { - continue - } - - if (props.max_zoom < 19) { - // We want users to zoom to level 19 when adding a point - // If they are on a layer which hasn't enough precision, they can not zoom far enough. This is confusing, so we don't use this layer - continue - } - - if (props.name === undefined) { - console.warn("Editor layer index: name not defined on ", props) - continue - } - - const leafletLayer: () => TileLayer = () => - AvailableBaseLayersImplementation.CreateBackgroundLayer( - props.id, - props.name, - props.url, - props.name, - props.license_url, - props.max_zoom, - props.type.toLowerCase() === "wms", - props.type.toLowerCase() === "wmts" - ) - - // Note: if layer.geometry is null, there is global coverage for this layer - layers.push({ - id: props.id, - max_zoom: props.max_zoom ?? 19, - min_zoom: props.min_zoom ?? 1, - name: props.name, - layer: leafletLayer, - feature: layer.geometry !== null ? layer : null, - isBest: props.best ?? false, - category: props.category, - }) - } - return layers - } - - private static LoadProviderIndex(): BaseLayer[] { - // @ts-ignore - X // Import X to make sure the namespace is not optimized away - function l(id: string, name: string): BaseLayer { - try { - const layer: any = L.tileLayer.provider(id, undefined) - return { - feature: null, - id: id, - name: name, - layer: () => - L.tileLayer.provider(id, { - maxNativeZoom: layer.options?.maxZoom, - maxZoom: Math.max(layer.options?.maxZoom ?? 19, 21), - }), - min_zoom: 1, - max_zoom: layer.options.maxZoom, - category: "osmbasedmap", - isBest: false, - } - } catch (e) { - console.error("Could not find provided layer", name, e) - return null - } - } - - const layers = [ - l("Stamen.TonerLite", "Toner Lite (by Stamen)"), - l("Stamen.TonerBackground", "Toner Background - no labels (by Stamen)"), - l("Stamen.Watercolor", "Watercolor (by Stamen)"), - l("CartoDB.Positron", "Positron (by CartoDB)"), - l("CartoDB.PositronNoLabels", "Positron - no labels (by CartoDB)"), - l("CartoDB.Voyager", "Voyager (by CartoDB)"), - l("CartoDB.VoyagerNoLabels", "Voyager - no labels (by CartoDB)"), - l("CartoDB.DarkMatter", "Dark Matter (by CartoDB)"), - l("CartoDB.DarkMatterNoLabels", "Dark Matter - no labels (by CartoDB)"), - ] - return Utils.NoNull(layers) - } - - /** - * Converts a layer from the editor-layer-index into a tilelayer usable by leaflet - */ - private static CreateBackgroundLayer( - id: string, - name: string, - url: string, - attribution: string, - attributionUrl: string, - maxZoom: number, - isWms: boolean, - isWMTS?: boolean - ): TileLayer { - url = url.replace("{zoom}", "{z}").replace("&BBOX={bbox}", "").replace("&bbox={bbox}", "") - - const subdomainsMatch = url.match(/{switch:[^}]*}/) - let domains: string[] = [] - if (subdomainsMatch !== null) { - let domainsStr = subdomainsMatch[0].substr("{switch:".length) - domainsStr = domainsStr.substr(0, domainsStr.length - 1) - domains = domainsStr.split(",") - url = url.replace(/{switch:[^}]*}/, "{s}") - } - - if (isWms) { - url = url.replace("&SRS={proj}", "") - url = url.replace("&srs={proj}", "") - const paramaters = [ - "format", - "layers", - "version", - "service", - "request", - "styles", - "transparent", - "version", - ] - const urlObj = new URL(url) - - const isUpper = urlObj.searchParams["LAYERS"] !== null - const options = { - maxZoom: Math.max(maxZoom ?? 19, 21), - maxNativeZoom: maxZoom ?? 19, - attribution: attribution + " | ", - subdomains: domains, - uppercase: isUpper, - transparent: false, - } - - for (const paramater of paramaters) { - let p = paramater - if (isUpper) { - p = paramater.toUpperCase() - } - options[paramater] = urlObj.searchParams.get(p) - } - - if (options.transparent === null) { - options.transparent = false - } - - return L.tileLayer.wms(urlObj.protocol + "//" + urlObj.host + urlObj.pathname, options) - } - - if (attributionUrl) { - attribution = `${attribution}` - } - - return L.tileLayer(url, { - attribution: attribution, - maxZoom: Math.max(21, maxZoom ?? 19), - maxNativeZoom: maxZoom ?? 19, - minZoom: 1, - // @ts-ignore - wmts: isWMTS ?? false, - subdomains: domains, - }) - } - - public AvailableLayersAt(location: Store): Store { - return Stores.ListStabilized( - location.map((currentLocation) => { - if (currentLocation === undefined) { - return this.layerOverview - } - return this.CalculateAvailableLayersAt(currentLocation?.lon, currentLocation?.lat) - }) - ) - } - - public SelectBestLayerAccordingTo( - location: Store, - preferedCategory: Store - ): Store { - return this.AvailableLayersAt(location).map( - (available) => { - // First float all 'best layers' to the top - available.sort((a, b) => { - if (a.isBest && b.isBest) { - return 0 - } - if (!a.isBest) { - return 1 - } - - return -1 - }) - - if (preferedCategory.data === undefined) { - return available[0] - } - - let prefered: string[] - if (typeof preferedCategory.data === "string") { - prefered = [preferedCategory.data] - } else { - prefered = preferedCategory.data - } - - prefered.reverse(/*New list, inplace reverse is fine*/) - for (const category of prefered) { - //Then sort all 'photo'-layers to the top. Stability of the sorting will force a 'best' photo layer on top - available.sort((a, b) => { - if (a.category === category && b.category === category) { - return 0 - } - if (a.category !== category) { - return 1 - } - - return -1 - }) - } - return available[0] - }, - [preferedCategory] - ) - } - - private CalculateAvailableLayersAt(lon: number, lat: number): BaseLayer[] { - const availableLayers = [this.osmCarto] - if (lon === undefined || lat === undefined) { - return availableLayers.concat(this.globalLayers) - } - const lonlat: [number, number] = [lon, lat] - for (const layerOverviewItem of this.localLayers) { - const layer = layerOverviewItem - const bbox = BBox.get(layer.feature) - - if (!bbox.contains(lonlat)) { - continue - } - - if (GeoOperations.inside(lonlat, layer.feature)) { - availableLayers.push(layer) - } - } - - return availableLayers.concat(this.globalLayers) - } -} diff --git a/Logic/Actors/BackgroundLayerResetter.ts b/Logic/Actors/BackgroundLayerResetter.ts index ee559b4fb..6d599827b 100644 --- a/Logic/Actors/BackgroundLayerResetter.ts +++ b/Logic/Actors/BackgroundLayerResetter.ts @@ -1,49 +1,45 @@ -import { UIEventSource } from "../UIEventSource" -import BaseLayer from "../../Models/BaseLayer" -import AvailableBaseLayers from "./AvailableBaseLayers" -import Loc from "../../Models/Loc" -import { Utils } from "../../Utils" +import {Store, UIEventSource} from "../UIEventSource" +import {Utils} from "../../Utils" +import {RasterLayerPolygon, RasterLayerUtils,} from "../../Models/RasterLayers" /** - * Sets the current background layer to a layer that is actually available + * When a user pans around on the map, they might pan out of the range of the current background raster layer. + * This actor will then quickly select a (best) raster layer of the same category which is available */ export default class BackgroundLayerResetter { constructor( - currentBackgroundLayer: UIEventSource, - location: UIEventSource, - availableLayers: UIEventSource, - defaultLayerId: string = undefined + currentBackgroundLayer: UIEventSource, + availableLayers: Store ) { if (Utils.runningFromConsole) { return } - defaultLayerId = defaultLayerId ?? AvailableBaseLayers.osmCarto.id - - // Change the baselayer back to OSM if we go out of the current range of the layer - availableLayers.addCallbackAndRun((availableLayers) => { - let defaultLayer = undefined - const currentLayer = currentBackgroundLayer.data.id - for (const availableLayer of availableLayers) { - if (availableLayer.id === currentLayer) { - if (availableLayer.max_zoom < location.data.zoom) { - break - } - - if (availableLayer.min_zoom > location.data.zoom) { - break - } - if (availableLayer.id === defaultLayerId) { - defaultLayer = availableLayer - } - return // All good - the current layer still works! - } + // Change the baseLayer back to OSM if we go out of the current range of the layer + availableLayers.addCallbackAndRunD((availableLayers) => { + // We only check on move/on change of the availableLayers + const currentBgPolygon: RasterLayerPolygon | undefined = currentBackgroundLayer.data + if (currentBackgroundLayer === undefined) { + return } + + if (availableLayers.findIndex((available) => currentBgPolygon == available) >= 0) { + // Still available! + return + } + + console.log("Current layer properties:", currentBgPolygon) // Oops, we panned out of range for this layer! - console.log( - "AvailableBaseLayers-actor: detected that the current bounds aren't sufficient anymore - reverting to OSM standard" + // What is the 'best' map of the same category which is available? + const availableInSameCat = RasterLayerUtils.SelectBestLayerAccordingTo( + availableLayers, + currentBgPolygon?.properties?.category ) - currentBackgroundLayer.setData(defaultLayer ?? AvailableBaseLayers.osmCarto) + if(!availableInSameCat){ + return + } + console.log("Selecting a different layer:", availableInSameCat.properties.id) + currentBackgroundLayer.setData(availableInSameCat) }) } } diff --git a/Logic/Actors/ChangeToElementsActor.ts b/Logic/Actors/ChangeToElementsActor.ts index 1eac44bfd..3bb0f50ad 100644 --- a/Logic/Actors/ChangeToElementsActor.ts +++ b/Logic/Actors/ChangeToElementsActor.ts @@ -1,15 +1,18 @@ -import { ElementStorage } from "../ElementStorage" import { Changes } from "../Osm/Changes" +import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore" +/** + * Applies tag changes onto the featureStore + */ export default class ChangeToElementsActor { - constructor(changes: Changes, allElements: ElementStorage) { + constructor(changes: Changes, allElements: FeaturePropertiesStore) { changes.pendingChanges.addCallbackAndRun((changes) => { for (const change of changes) { const id = change.type + "/" + change.id if (!allElements.has(id)) { continue // Ignored as the geometryFixer will introduce this } - const src = allElements.getEventSourceById(id) + const src = allElements.getStore(id) let changed = false for (const kv of change.tags ?? []) { diff --git a/Logic/Actors/GeoLocationHandler.ts b/Logic/Actors/GeoLocationHandler.ts index b458af29f..c2cb5f50a 100644 --- a/Logic/Actors/GeoLocationHandler.ts +++ b/Logic/Actors/GeoLocationHandler.ts @@ -1,11 +1,15 @@ -import { QueryParameters } from "../Web/QueryParameters" -import { BBox } from "../BBox" +import {QueryParameters} from "../Web/QueryParameters" +import {BBox} from "../BBox" import Constants from "../../Models/Constants" -import { GeoLocationPointProperties, GeoLocationState } from "../State/GeoLocationState" -import { UIEventSource } from "../UIEventSource" -import Loc from "../../Models/Loc" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import SimpleFeatureSource from "../FeatureSource/Sources/SimpleFeatureSource" +import {GeoLocationState} from "../State/GeoLocationState" +import {UIEventSource} from "../UIEventSource" +import {Feature, LineString, Point} from "geojson" +import {FeatureSource, WritableFeatureSource} from "../FeatureSource/FeatureSource" +import {LocalStorageSource} from "../Web/LocalStorageSource" +import {GeoOperations} from "../GeoOperations" +import {OsmTags} from "../../Models/OsmFeature" +import StaticFeatureSource from "../FeatureSource/Sources/StaticFeatureSource" +import {MapProperties} from "../../Models/MapProperties" /** * The geolocation-handler takes a map-location and a geolocation state. @@ -14,28 +18,43 @@ import SimpleFeatureSource from "../FeatureSource/Sources/SimpleFeatureSource" */ export default class GeoLocationHandler { public readonly geolocationState: GeoLocationState - private readonly _state: { - currentUserLocation: SimpleFeatureSource - layoutToUse: LayoutConfig - locationControl: UIEventSource - selectedElement: UIEventSource - leafletMap?: UIEventSource - } - public readonly mapHasMoved: UIEventSource = new UIEventSource(false) + + /** + * The location as delivered by the GPS, wrapped as FeatureSource + */ + public currentUserLocation: FeatureSource + + /** + * All previously visited points (as 'Point'-objects), with their metadata + */ + public historicalUserLocations: WritableFeatureSource> + + /** + * A featureSource containing a single linestring which has the GPS-history of the user. + * However, metadata (such as when every single point was visited) is lost here (but is kept in `historicalUserLocations`. + * Note that this featureSource is _derived_ from 'historicalUserLocations' + */ + public readonly historicalUserLocationsTrack: FeatureSource + + /** + * The last moment that the map has moved + */ + public readonly mapHasMoved: UIEventSource = new UIEventSource(undefined) + private readonly selectedElement: UIEventSource + private readonly mapProperties?: MapProperties + private readonly gpsLocationHistoryRetentionTime?: UIEventSource constructor( geolocationState: GeoLocationState, - state: { - locationControl: UIEventSource - currentUserLocation: SimpleFeatureSource - layoutToUse: LayoutConfig - selectedElement: UIEventSource - leafletMap?: UIEventSource - } + selectedElement: UIEventSource, + mapProperties?: MapProperties, + gpsLocationHistoryRetentionTime?: UIEventSource ) { this.geolocationState = geolocationState - this._state = state - const mapLocation = state.locationControl + const mapLocation = mapProperties.location + this.selectedElement = selectedElement + this.mapProperties = mapProperties + this.gpsLocationHistoryRetentionTime = gpsLocationHistoryRetentionTime // Did an interaction move the map? let self = this let initTime = new Date() @@ -43,7 +62,7 @@ export default class GeoLocationHandler { if (new Date().getTime() - initTime.getTime() < 250) { return } - self.mapHasMoved.setData(true) + self.mapHasMoved.setData(new Date()) return true // Unsubscribe }) @@ -51,39 +70,34 @@ export default class GeoLocationHandler { QueryParameters.wasInitialized("lat") || QueryParameters.wasInitialized("lon") if (latLonGivenViaUrl) { // The URL counts as a 'user interaction' - this.mapHasMoved.setData(true) + this.mapHasMoved.setData(new Date()) } - this.geolocationState.currentGPSLocation.addCallbackAndRunD((newLocation) => { + this.geolocationState.currentGPSLocation.addCallbackAndRunD((_) => { const timeSinceLastRequest = (new Date().getTime() - geolocationState.requestMoment.data?.getTime() ?? 0) / 1000 if (!this.mapHasMoved.data) { // The map hasn't moved yet; we received our first coordinates, so let's move there! self.MoveMapToCurrentLocation() } - if (timeSinceLastRequest < Constants.zoomToLocationTimeout) { + if (timeSinceLastRequest < Constants.zoomToLocationTimeout && + (this.mapHasMoved.data === undefined || this.mapHasMoved.data.getTime() < geolocationState.requestMoment.data?.getTime() ) + ) { + // still within request time and the map hasn't moved since requesting to jump to the current location self.MoveMapToCurrentLocation() } - if (this.geolocationState.isLocked.data) { + if (!this.geolocationState.allowMoving.data) { // Jup, the map is locked to the bound location: move automatically self.MoveMapToCurrentLocation() return } }) - geolocationState.isLocked.map( - (isLocked) => { - if (isLocked) { - state.leafletMap?.data?.dragging?.disable() - } else { - state.leafletMap?.data?.dragging?.enable() - } - }, - [state.leafletMap] - ) + geolocationState.allowMoving.syncWith(mapProperties.allowMoving, true) this.CopyGeolocationIntoMapstate() + this.historicalUserLocationsTrack = this.initUserLocationTrail() } /** @@ -95,12 +109,11 @@ export default class GeoLocationHandler { */ public MoveMapToCurrentLocation() { const newLocation = this.geolocationState.currentGPSLocation.data - const mapLocation = this._state.locationControl - const state = this._state + const mapLocation = this.mapProperties.location // We got a new location. // Do we move the map to it? - if (state.selectedElement.data !== undefined) { + if (this.selectedElement.data !== undefined) { // Nope, there is something selected, so we don't move to the current GPS-location return } @@ -110,8 +123,8 @@ export default class GeoLocationHandler { } // We check that the GPS location is not out of bounds - const bounds = state.layoutToUse.lockLocation - if (bounds && bounds !== true) { + const bounds = this.mapProperties.maxbounds.data + if (bounds !== undefined) { // B is an array with our lock-location const inRange = new BBox(bounds).contains([newLocation.longitude, newLocation.latitude]) if (!inRange) { @@ -119,45 +132,128 @@ export default class GeoLocationHandler { } } + console.trace("Moving the map to the GPS-location") mapLocation.setData({ - zoom: Math.max(mapLocation.data.zoom, 16), lon: newLocation.longitude, lat: newLocation.latitude, }) - this.mapHasMoved.setData(true) + const zoom = this.mapProperties.zoom + zoom.setData(Math.min(Math.max(zoom.data, 14), 18)) + + this.mapHasMoved.setData(new Date()) this.geolocationState.requestMoment.setData(undefined) } private CopyGeolocationIntoMapstate() { - const state = this._state - // For some weird reason, the 'Object.keys' method doesn't work for the 'location: GeolocationCoordinates'-object and will thus not copy all the properties when using {...location} - // As such, they are copied here + const features: UIEventSource = new UIEventSource([]) + this.currentUserLocation = new StaticFeatureSource(features) const keysToCopy = ["speed", "accuracy", "altitude", "altitudeAccuracy", "heading"] + let i = 0 this.geolocationState.currentGPSLocation.addCallbackAndRun((location) => { if (location === undefined) { return } - const feature = { + const properties = { + id: "gps-"+i, + "user:location": "yes", + date: new Date().toISOString(), + } + i++ + + for (const k in keysToCopy) { + // For some weird reason, the 'Object.keys' method doesn't work for the 'location: GeolocationCoordinates'-object and will thus not copy all the properties when using {...location} + // As such, they are copied here + if(location[k]){ + properties[k] = location[k] + } + } + + const feature = { type: "Feature", - properties: { - id: "gps", - "user:location": "yes", - date: new Date().toISOString(), - ...location, - }, + properties, geometry: { type: "Point", coordinates: [location.longitude, location.latitude], }, } - for (const key of keysToCopy) { - if (location[key] !== null) { - feature.properties[key] = location[key] + + features.setData([feature]) + }) + } + + private initUserLocationTrail() { + const features = LocalStorageSource.GetParsed("gps_location_history", []) + const now = new Date().getTime() + features.data = features.data.filter((ff) => { + if (ff.properties === undefined) { + return false + } + const point_time = new Date(ff.properties["date"]) + return ( + now - point_time.getTime() < + 1000 * (this.gpsLocationHistoryRetentionTime?.data ?? 24 * 60 * 60 * 1000) + ) + }) + features.ping() + let i = 0 + this.currentUserLocation?.features?.addCallbackAndRunD(([location]: [Feature]) => { + if (location === undefined) { + return + } + + const previousLocation = >features.data[features.data.length - 1] + if (previousLocation !== undefined) { + const previousLocationFreshness = new Date(previousLocation.properties.date) + const d = GeoOperations.distanceBetween( + <[number, number]>previousLocation.geometry.coordinates, + <[number, number]>location.geometry.coordinates + ) + let timeDiff = Number.MAX_VALUE // in seconds + const olderLocation = features.data[features.data.length - 2] + + if (olderLocation !== undefined) { + const olderLocationFreshness = new Date(olderLocation.properties.date) + timeDiff = + (new Date(previousLocationFreshness).getTime() - + new Date(olderLocationFreshness).getTime()) / + 1000 + } + if (d < 20 && timeDiff < 60) { + // Do not append changes less then 20m - it's probably noise anyway + return } } - state.currentUserLocation?.features?.setData([{ feature, freshness: new Date() }]) + const feature = JSON.parse(JSON.stringify(location)) + feature.properties.id = "gps/" + features.data.length + i++ + features.data.push(feature) + features.ping() }) + + this.historicalUserLocations = new StaticFeatureSource(features) + + const asLine = features.map((allPoints) => { + if (allPoints === undefined || allPoints.length < 2) { + return [] + } + + const feature: Feature = { + type: "Feature", + properties: { + id: "location_track", + "_date:now": new Date().toISOString(), + }, + geometry: { + type: "LineString", + coordinates: allPoints.map( + (ff: Feature) => <[number, number]>ff.geometry.coordinates + ), + }, + } + return [feature] + }) + return new StaticFeatureSource(asLine) } } diff --git a/Logic/Actors/InitialMapPositioning.ts b/Logic/Actors/InitialMapPositioning.ts new file mode 100644 index 000000000..a51aea6c2 --- /dev/null +++ b/Logic/Actors/InitialMapPositioning.ts @@ -0,0 +1,64 @@ +import { UIEventSource } from "../UIEventSource" +import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" +import { LocalStorageSource } from "../Web/LocalStorageSource" +import { QueryParameters } from "../Web/QueryParameters" + +/** + * This actor is responsible to set the map location. + * It will attempt to + * - Set the map to the position as passed in by the query parameters (if available) + * - Set the map to the position remembered in LocalStorage (if available) + * - Set the map to the layout default + * + * Additionally, it will save the map location to local storage + */ +export default class InitialMapPositioning { + public zoom: UIEventSource + public location: UIEventSource<{ lon: number; lat: number }> + constructor(layoutToUse: LayoutConfig) { + function localStorageSynced( + key: string, + deflt: number, + docs: string + ): UIEventSource { + const localStorage = LocalStorageSource.Get(key) + const previousValue = localStorage.data + const src = UIEventSource.asFloat( + QueryParameters.GetQueryParameter(key, "" + deflt, docs).syncWith(localStorage) + ) + + if (src.data === deflt) { + const prev = Number(previousValue) + if (!isNaN(prev)) { + src.setData(prev) + } + } + + return src + } + + // -- Location control initialization + this.zoom = localStorageSynced( + "z", + layoutToUse?.startZoom ?? 1, + "The initial/current zoom level" + ) + const lat = localStorageSynced( + "lat", + layoutToUse?.startLat ?? 0, + "The initial/current latitude" + ) + const lon = localStorageSynced( + "lon", + layoutToUse?.startLon ?? 0, + "The initial/current longitude of the app" + ) + + this.location = new UIEventSource({ lon: lon.data, lat: lat.data }) + this.location.addCallbackD((loc) => { + lat.setData(loc.lat) + lon.setData(loc.lon) + }) + // Note: this syncs only in one direction + } +} diff --git a/Logic/Actors/OverpassFeatureSource.ts b/Logic/Actors/OverpassFeatureSource.ts deleted file mode 100644 index 7560e6c03..000000000 --- a/Logic/Actors/OverpassFeatureSource.ts +++ /dev/null @@ -1,261 +0,0 @@ -import { Store, UIEventSource } from "../UIEventSource" -import { Or } from "../Tags/Or" -import { Overpass } from "../Osm/Overpass" -import FeatureSource from "../FeatureSource/FeatureSource" -import { Utils } from "../../Utils" -import { TagsFilter } from "../Tags/TagsFilter" -import SimpleMetaTagger from "../SimpleMetaTagger" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import RelationsTracker from "../Osm/RelationsTracker" -import { BBox } from "../BBox" -import Loc from "../../Models/Loc" -import LayerConfig from "../../Models/ThemeConfig/LayerConfig" -import Constants from "../../Models/Constants" -import TileFreshnessCalculator from "../FeatureSource/TileFreshnessCalculator" -import { Tiles } from "../../Models/TileRange" - -export default class OverpassFeatureSource implements FeatureSource { - public readonly name = "OverpassFeatureSource" - - /** - * The last loaded features of the geojson - */ - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = - new UIEventSource(undefined) - - public readonly runningQuery: UIEventSource = new UIEventSource(false) - public readonly timeout: UIEventSource = new UIEventSource(0) - - public readonly relationsTracker: RelationsTracker - - private readonly retries: UIEventSource = new UIEventSource(0) - - private readonly state: { - readonly locationControl: Store - readonly layoutToUse: LayoutConfig - readonly overpassUrl: Store - readonly overpassTimeout: Store - readonly currentBounds: Store - } - private readonly _isActive: Store - /** - * Callback to handle all the data - */ - private readonly onBboxLoaded: ( - bbox: BBox, - date: Date, - layers: LayerConfig[], - zoomlevel: number - ) => void - - /** - * Keeps track of how fresh the data is - * @private - */ - private readonly freshnesses: Map - - constructor( - state: { - readonly locationControl: Store - readonly layoutToUse: LayoutConfig - readonly overpassUrl: Store - readonly overpassTimeout: Store - readonly overpassMaxZoom: Store - readonly currentBounds: Store - }, - options: { - padToTiles: Store - isActive?: Store - relationTracker: RelationsTracker - onBboxLoaded?: ( - bbox: BBox, - date: Date, - layers: LayerConfig[], - zoomlevel: number - ) => void - freshnesses?: Map - } - ) { - this.state = state - this._isActive = options.isActive - this.onBboxLoaded = options.onBboxLoaded - this.relationsTracker = options.relationTracker - this.freshnesses = options.freshnesses - const self = this - state.currentBounds.addCallback((_) => { - self.update(options.padToTiles.data) - }) - } - - private GetFilter(interpreterUrl: string, layersToDownload: LayerConfig[]): Overpass { - let filters: TagsFilter[] = [] - let extraScripts: string[] = [] - for (const layer of layersToDownload) { - if (layer.source.overpassScript !== undefined) { - extraScripts.push(layer.source.overpassScript) - } else { - filters.push(layer.source.osmTags) - } - } - filters = Utils.NoNull(filters) - extraScripts = Utils.NoNull(extraScripts) - if (filters.length + extraScripts.length === 0) { - return undefined - } - return new Overpass( - new Or(filters), - extraScripts, - interpreterUrl, - this.state.overpassTimeout, - this.relationsTracker - ) - } - - private update(paddedZoomLevel: number) { - if (!this._isActive.data) { - return - } - const self = this - this.updateAsync(paddedZoomLevel).then((bboxDate) => { - if (bboxDate === undefined || self.onBboxLoaded === undefined) { - return - } - const [bbox, date, layers] = bboxDate - self.onBboxLoaded(bbox, date, layers, paddedZoomLevel) - }) - } - - private async updateAsync(padToZoomLevel: number): Promise<[BBox, Date, LayerConfig[]]> { - if (this.runningQuery.data) { - console.log("Still running a query, not updating") - return undefined - } - - if (this.timeout.data > 0) { - console.log("Still in timeout - not updating") - return undefined - } - - let data: any = undefined - let date: Date = undefined - let lastUsed = 0 - - const layersToDownload = [] - const neededTiles = this.state.currentBounds.data - .expandToTileBounds(padToZoomLevel) - .containingTileRange(padToZoomLevel) - for (const layer of this.state.layoutToUse.layers) { - if (typeof layer === "string") { - throw "A layer was not expanded!" - } - if (Constants.priviliged_layers.indexOf(layer.id) >= 0) { - continue - } - if (this.state.locationControl.data.zoom < layer.minzoom) { - continue - } - if (layer.doNotDownload) { - continue - } - if (layer.source.geojsonSource !== undefined) { - // Not our responsibility to download this layer! - continue - } - const freshness = this.freshnesses?.get(layer.id) - if (freshness !== undefined) { - const oldestDataDate = - Math.min( - ...Tiles.MapRange(neededTiles, (x, y) => { - const date = freshness.freshnessFor(padToZoomLevel, x, y) - if (date === undefined) { - return 0 - } - return date.getTime() - }) - ) / 1000 - const now = new Date().getTime() - const minRequiredAge = now / 1000 - layer.maxAgeOfCache - if (oldestDataDate >= minRequiredAge) { - // still fresh enough - not updating - continue - } - } - - layersToDownload.push(layer) - } - - if (layersToDownload.length == 0) { - console.debug("Not updating - no layers needed") - return - } - - const self = this - const overpassUrls = self.state.overpassUrl.data - if (overpassUrls === undefined || overpassUrls.length === 0) { - throw "Panic: overpassFeatureSource didn't receive any overpassUrls" - } - let bounds: BBox - do { - try { - bounds = this.state.currentBounds.data - ?.pad(this.state.layoutToUse.widenFactor) - ?.expandToTileBounds(padToZoomLevel) - - if (bounds === undefined) { - return undefined - } - - const overpass = this.GetFilter(overpassUrls[lastUsed], layersToDownload) - - if (overpass === undefined) { - return undefined - } - this.runningQuery.setData(true) - ;[data, date] = await overpass.queryGeoJson(bounds) - } catch (e) { - self.retries.data++ - self.retries.ping() - console.error(`QUERY FAILED due to`, e) - - await Utils.waitFor(1000) - - if (lastUsed + 1 < overpassUrls.length) { - lastUsed++ - console.log("Trying next time with", overpassUrls[lastUsed]) - } else { - lastUsed = 0 - self.timeout.setData(self.retries.data * 5) - - while (self.timeout.data > 0) { - await Utils.waitFor(1000) - console.log(self.timeout.data) - self.timeout.data-- - self.timeout.ping() - } - } - } - } while (data === undefined && this._isActive.data) - - try { - if (data === undefined) { - return undefined - } - data.features.forEach((feature) => - SimpleMetaTagger.objectMetaInfo.applyMetaTagsOnFeature( - feature, - date, - undefined, - this.state - ) - ) - self.features.setData(data.features.map((f) => ({ feature: f, freshness: date }))) - return [bounds, date, layersToDownload] - } catch (e) { - console.error("Got the overpass response, but could not process it: ", e, e.stack) - return undefined - } finally { - self.retries.setData(0) - self.runningQuery.setData(false) - } - } -} diff --git a/Logic/Actors/PendingChangesUploader.ts b/Logic/Actors/PendingChangesUploader.ts index cc7ebd436..e71d0bf82 100644 --- a/Logic/Actors/PendingChangesUploader.ts +++ b/Logic/Actors/PendingChangesUploader.ts @@ -2,11 +2,12 @@ import { Changes } from "../Osm/Changes" import Constants from "../../Models/Constants" import { UIEventSource } from "../UIEventSource" import { Utils } from "../../Utils" +import { Feature } from "geojson" export default class PendingChangesUploader { private lastChange: Date - constructor(changes: Changes, selectedFeature: UIEventSource) { + constructor(changes: Changes, selectedFeature: UIEventSource) { const self = this this.lastChange = new Date() changes.pendingChanges.addCallback(() => { diff --git a/Logic/Actors/SelectedElementTagsUpdater.ts b/Logic/Actors/SelectedElementTagsUpdater.ts index 3df0a4804..91078a53b 100644 --- a/Logic/Actors/SelectedElementTagsUpdater.ts +++ b/Logic/Actors/SelectedElementTagsUpdater.ts @@ -2,12 +2,16 @@ * This actor will download the latest version of the selected element from OSM and update the tags if necessary. */ import { UIEventSource } from "../UIEventSource" -import { ElementStorage } from "../ElementStorage" import { Changes } from "../Osm/Changes" -import { OsmObject } from "../Osm/OsmObject" import { OsmConnection } from "../Osm/OsmConnection" import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" import SimpleMetaTagger from "../SimpleMetaTagger" +import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore" +import { Feature } from "geojson" +import { OsmTags } from "../../Models/OsmFeature" +import OsmObjectDownloader from "../Osm/OsmObjectDownloader" +import { IndexedFeatureSource } from "../FeatureSource/FeatureSource" +import { Utils } from "../../Utils" export default class SelectedElementTagsUpdater { private static readonly metatags = new Set([ @@ -19,30 +23,43 @@ export default class SelectedElementTagsUpdater { "id", ]) - constructor(state: { - selectedElement: UIEventSource - allElements: ElementStorage + private readonly state: { + selectedElement: UIEventSource + featureProperties: FeaturePropertiesStore changes: Changes osmConnection: OsmConnection - layoutToUse: LayoutConfig + layout: LayoutConfig + osmObjectDownloader: OsmObjectDownloader + indexedFeatures: IndexedFeatureSource + } + + constructor(state: { + selectedElement: UIEventSource + featureProperties: FeaturePropertiesStore + indexedFeatures: IndexedFeatureSource + changes: Changes + osmConnection: OsmConnection + layout: LayoutConfig + osmObjectDownloader: OsmObjectDownloader }) { + this.state = state state.osmConnection.isLoggedIn.addCallbackAndRun((isLoggedIn) => { - if (isLoggedIn) { - SelectedElementTagsUpdater.installCallback(state) - return true + if (!isLoggedIn && !Utils.runningFromConsole) { + return } + this.installCallback() + // We only have to do this once... + return true }) } - public static installCallback(state: { - selectedElement: UIEventSource - allElements: ElementStorage - changes: Changes - osmConnection: OsmConnection - layoutToUse: LayoutConfig - }) { + private installCallback() { + const state = this.state state.selectedElement.addCallbackAndRunD(async (s) => { let id = s.properties?.id + if (!id) { + return + } const backendUrl = state.osmConnection._oauth_config.url if (id.startsWith(backendUrl)) { @@ -59,38 +76,36 @@ export default class SelectedElementTagsUpdater { return } try { - const latestTags = await OsmObject.DownloadPropertiesOf(id) - if (latestTags === "deleted") { - console.warn("The current selected element has been deleted upstream!") - const currentTagsSource = state.allElements.getEventSourceById(id) - if (currentTagsSource.data["_deleted"] === "yes") { - return - } + const osmObject = await state.osmObjectDownloader.DownloadObjectAsync(id) + if (osmObject === "deleted") { + console.debug("The current selected element has been deleted upstream!", id) + const currentTagsSource = state.featureProperties.getStore(id) currentTagsSource.data["_deleted"] = "yes" + currentTagsSource.addCallbackAndRun((tags) => console.trace("Tags are", tags)) currentTagsSource.ping() return } - SelectedElementTagsUpdater.applyUpdate(state, latestTags, id) + const latestTags = osmObject.tags + const newGeometry = osmObject.asGeoJson()?.geometry + const oldFeature = state.indexedFeatures.featuresById.data.get(id) + const oldGeometry = oldFeature?.geometry + if (oldGeometry !== undefined && !Utils.SameObject(newGeometry, oldGeometry)) { + console.log("Detected a difference in geometry for ", id) + oldFeature.geometry = newGeometry + state.featureProperties.getStore(id)?.ping() + } + this.applyUpdate(latestTags, id) + console.log("Updated", id) } catch (e) { console.warn("Could not update", id, " due to", e) } }) } - - public static applyUpdate( - state: { - selectedElement: UIEventSource - allElements: ElementStorage - changes: Changes - osmConnection: OsmConnection - layoutToUse: LayoutConfig - }, - latestTags: any, - id: string - ) { + private applyUpdate(latestTags: OsmTags, id: string) { + const state = this.state try { - const leftRightSensitive = state.layoutToUse.isLeftRightSensitive() + const leftRightSensitive = state.layout.isLeftRightSensitive() if (leftRightSensitive) { SimpleMetaTagger.removeBothTagging(latestTags) @@ -115,7 +130,7 @@ export default class SelectedElementTagsUpdater { // With the changes applied, we merge them onto the upstream object let somethingChanged = false - const currentTagsSource = state.allElements.getEventSourceById(id) + const currentTagsSource = state.featureProperties.getStore(id) const currentTags = currentTagsSource.data for (const key in latestTags) { let osmValue = latestTags[key] @@ -135,7 +150,7 @@ export default class SelectedElementTagsUpdater { if (currentKey.startsWith("_")) { continue } - if (this.metatags.has(currentKey)) { + if (SelectedElementTagsUpdater.metatags.has(currentKey)) { continue } if (currentKey in latestTags) { diff --git a/Logic/Actors/SelectedFeatureHandler.ts b/Logic/Actors/SelectedFeatureHandler.ts deleted file mode 100644 index 3591bc4eb..000000000 --- a/Logic/Actors/SelectedFeatureHandler.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { UIEventSource } from "../UIEventSource" -import { OsmObject } from "../Osm/OsmObject" -import Loc from "../../Models/Loc" -import { ElementStorage } from "../ElementStorage" -import FeaturePipeline from "../FeatureSource/FeaturePipeline" -import { GeoOperations } from "../GeoOperations" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" - -/** - * Makes sure the hash shows the selected element and vice-versa. - */ -export default class SelectedFeatureHandler { - private static readonly _no_trigger_on = new Set([ - "welcome", - "copyright", - "layers", - "new", - "filters", - "location_track", - "", - undefined, - ]) - private readonly hash: UIEventSource - private readonly state: { - selectedElement: UIEventSource - allElements: ElementStorage - locationControl: UIEventSource - layoutToUse: LayoutConfig - } - - constructor( - hash: UIEventSource, - state: { - selectedElement: UIEventSource - allElements: ElementStorage - featurePipeline: FeaturePipeline - locationControl: UIEventSource - layoutToUse: LayoutConfig - } - ) { - this.hash = hash - this.state = state - - // If the hash changes, set the selected element correctly - - const self = this - hash.addCallback(() => self.setSelectedElementFromHash()) - this.initialLoad() - } - - /** - * On startup: check if the hash is loaded and eventually zoom to it - * @private - */ - private initialLoad() { - const hash = this.hash.data - if (hash === undefined || hash === "" || hash.indexOf("-") >= 0) { - return - } - if (SelectedFeatureHandler._no_trigger_on.has(hash)) { - return - } - - if (!(hash.startsWith("node") || hash.startsWith("way") || hash.startsWith("relation"))) { - return - } - - OsmObject.DownloadObjectAsync(hash).then((obj) => { - try { - console.log("Downloaded selected object from OSM-API for initial load: ", hash) - const geojson = obj.asGeoJson() - this.state.allElements.addOrGetElement(geojson) - this.state.selectedElement.setData(geojson) - this.zoomToSelectedFeature() - } catch (e) { - console.error(e) - } - }) - } - - private setSelectedElementFromHash() { - const state = this.state - const h = this.hash.data - if (h === undefined || h === "") { - // Hash has been cleared - we clear the selected element - state.selectedElement.setData(undefined) - } else { - // we search the element to select - const feature = state.allElements.ContainingFeatures.get(h) - if (feature === undefined) { - return - } - const currentlySelected = state.selectedElement.data - if (currentlySelected === undefined) { - state.selectedElement.setData(feature) - return - } - if (currentlySelected.properties?.id === feature.properties.id) { - // We already have the right feature - return - } - state.selectedElement.setData(feature) - } - } - - // If a feature is selected via the hash, zoom there - private zoomToSelectedFeature() { - const selected = this.state.selectedElement.data - if (selected === undefined) { - return - } - - const centerpoint = GeoOperations.centerpointCoordinates(selected) - const location = this.state.locationControl - location.data.lon = centerpoint[0] - location.data.lat = centerpoint[1] - - const minZoom = Math.max( - 14, - ...(this.state.layoutToUse?.layers?.map((l) => l.minzoomVisible) ?? []) - ) - if (location.data.zoom < minZoom) { - location.data.zoom = minZoom - } - - location.ping() - } -} diff --git a/Logic/Actors/StrayClickHandler.ts b/Logic/Actors/StrayClickHandler.ts deleted file mode 100644 index c4fac415b..000000000 --- a/Logic/Actors/StrayClickHandler.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { UIEventSource } from "../UIEventSource" -import FilteredLayer from "../../Models/FilteredLayer" -import ScrollableFullScreen from "../../UI/Base/ScrollableFullScreen" -import BaseUIElement from "../../UI/BaseUIElement" - -/** - * The stray-click-handler adds a marker to the map if no feature was clicked. - * Shows the given uiToShow-element in the messagebox - * - * Note: the actual implementation is in StrayClickHandlerImplementation - */ -export default class StrayClickHandler { - public static construct = ( - state: { - LastClickLocation: UIEventSource<{ lat: number; lon: number }> - selectedElement: UIEventSource - filteredLayers: UIEventSource - leafletMap: UIEventSource - }, - uiToShow: ScrollableFullScreen, - iconToShow: BaseUIElement - ) => { - return undefined - } -} diff --git a/Logic/Actors/TitleHandler.ts b/Logic/Actors/TitleHandler.ts index 729f172c1..c5b8dfea0 100644 --- a/Logic/Actors/TitleHandler.ts +++ b/Logic/Actors/TitleHandler.ts @@ -1,45 +1,49 @@ import { Store, UIEventSource } from "../UIEventSource" import Locale from "../../UI/i18n/Locale" -import TagRenderingAnswer from "../../UI/Popup/TagRenderingAnswer" import Combine from "../../UI/Base/Combine" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import { ElementStorage } from "../ElementStorage" import { Utils } from "../../Utils" +import LayerConfig from "../../Models/ThemeConfig/LayerConfig" +import { Feature } from "geojson" +import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore" +import SvelteUIElement from "../../UI/Base/SvelteUIElement" +import TagRenderingAnswer from "../../UI/Popup/TagRendering/TagRenderingAnswer.svelte" +import { SpecialVisualizationState } from "../../UI/SpecialVisualization" export default class TitleHandler { - constructor(state: { - selectedElement: Store - layoutToUse: LayoutConfig - allElements: ElementStorage - }) { - const currentTitle: Store = state.selectedElement.map( + constructor( + selectedElement: Store, + selectedLayer: Store, + allElements: FeaturePropertiesStore, + state: SpecialVisualizationState + ) { + const currentTitle: Store = selectedElement.map( (selected) => { - const layout = state.layoutToUse - const defaultTitle = layout?.title?.txt ?? "MapComplete" + const defaultTitle = state.layout?.title?.txt ?? "MapComplete" - if (selected === undefined) { + if (selected === undefined || selectedLayer.data === undefined) { return defaultTitle } const tags = selected.properties - for (const layer of layout.layers) { - if (layer.title === undefined) { - continue - } - if (layer.source.osmTags.matchesProperties(tags)) { - const tagsSource = - state.allElements.getEventSourceById(tags.id) ?? - new UIEventSource(tags) - const title = new TagRenderingAnswer(tagsSource, layer.title, {}) - return ( - new Combine([defaultTitle, " | ", title]).ConstructElement() - ?.textContent ?? defaultTitle - ) - } + const layer = selectedLayer.data + if (layer.title === undefined) { + return defaultTitle } - return defaultTitle + const tagsSource = + allElements.getStore(tags.id) ?? new UIEventSource>(tags) + const title = new SvelteUIElement(TagRenderingAnswer, { + tags: tagsSource, + state, + config: layer.title, + selectedElement: selectedElement.data, + layer, + }) + return ( + new Combine([defaultTitle, " | ", title]).ConstructElement()?.textContent ?? + defaultTitle + ) }, - [Locale.language] + [Locale.language, selectedLayer] ) currentTitle.addCallbackAndRunD((title) => { diff --git a/Logic/BBox.ts b/Logic/BBox.ts index 9f1cbceab..58d918d96 100644 --- a/Logic/BBox.ts +++ b/Logic/BBox.ts @@ -105,7 +105,7 @@ export class BBox { * Constructs a tilerange which fully contains this bbox (thus might be a bit larger) * @param zoomlevel */ - public containingTileRange(zoomlevel): TileRange { + public containingTileRange(zoomlevel: number): TileRange { return Tiles.TileRangeBetween(zoomlevel, this.minLat, this.minLon, this.maxLat, this.maxLon) } @@ -138,6 +138,45 @@ export class BBox { return true } + squarify(): BBox { + const w = this.maxLon - this.minLon + const h = this.maxLat - this.minLat + const s = Math.sqrt(w * h) + const lon = (this.maxLon + this.minLon) / 2 + const lat = (this.maxLat + this.minLat) / 2 + // we want to have a more-or-less equal surface, so the new side 's' should be + // w * h = s * s + // The ratio for w is: + + return new BBox([ + [lon - s / 2, lat - s / 2], + [lon + s / 2, lat + s / 2], + ]) + } + + isNearby(location: [number, number], maxRange: number): boolean { + if (this.contains(location)) { + return true + } + const [lon, lat] = location + // We 'project' the point onto the near edges. If they are close to a horizontal _and_ vertical edge, it is nearby + // Vertically nearby: either wihtin minLat range or at most maxRange away + const nearbyVertical = + (this.minLat <= lat && + this.maxLat >= lat && + GeoOperations.distanceBetween(location, [lon, this.minLat]) <= maxRange) || + GeoOperations.distanceBetween(location, [lon, this.maxLat]) <= maxRange + if (!nearbyVertical) { + return false + } + const nearbyHorizontal = + (this.minLon <= lon && + this.maxLon >= lon && + GeoOperations.distanceBetween(location, [this.minLon, lat]) <= maxRange) || + GeoOperations.distanceBetween(location, [this.maxLon, lat]) <= maxRange + return nearbyHorizontal + } + getEast() { return this.maxLon } @@ -179,14 +218,21 @@ export class BBox { ]) } - toLeaflet(): [[number, number], [number, number]] { + toLngLat(): [[number, number], [number, number]] { return [ - [this.minLat, this.minLon], - [this.maxLat, this.maxLon], + [this.minLon, this.minLat], + [this.maxLon, this.maxLat], ] } - public asGeoJson(properties: T): Feature { + public asGeojsonCached() { + if (this["geojsonCache"] === undefined) { + this["geojsonCache"] = this.asGeoJson({}) + } + return this["geojsonCache"] + } + + public asGeoJson(properties?: T): Feature { return { type: "Feature", properties: properties, @@ -214,6 +260,9 @@ export class BBox { * @param zoomlevel */ expandToTileBounds(zoomlevel: number): BBox { + if (zoomlevel === undefined) { + return this + } const ul = Tiles.embedded_tile(this.minLat, this.minLon, zoomlevel) const lr = Tiles.embedded_tile(this.maxLat, this.maxLon, zoomlevel) const boundsul = Tiles.tile_bounds_lon_lat(ul.z, ul.x, ul.y) diff --git a/Logic/ContributorCount.ts b/Logic/ContributorCount.ts index ef827585d..a3095a2f3 100644 --- a/Logic/ContributorCount.ts +++ b/Logic/ContributorCount.ts @@ -1,39 +1,31 @@ /// Given a feature source, calculates a list of OSM-contributors who mapped the latest versions import { Store, UIEventSource } from "./UIEventSource" -import FeaturePipeline from "./FeatureSource/FeaturePipeline" -import Loc from "../Models/Loc" import { BBox } from "./BBox" +import GeoIndexedStore from "./FeatureSource/Actors/GeoIndexedStore" export default class ContributorCount { public readonly Contributors: UIEventSource> = new UIEventSource< Map >(new Map()) - private readonly state: { - featurePipeline: FeaturePipeline - currentBounds: Store - locationControl: Store - } + private readonly perLayer: ReadonlyMap private lastUpdate: Date = undefined constructor(state: { - featurePipeline: FeaturePipeline - currentBounds: Store - locationControl: Store + mapProperties: { bounds: Store } + dataIsLoading: Store + perLayer: ReadonlyMap }) { - this.state = state + this.perLayer = state.perLayer const self = this - state.currentBounds.map((bbox) => { - self.update(bbox) - }) - state.featurePipeline.runningQuery.addCallbackAndRun((_) => - self.update(state.currentBounds.data) + state.mapProperties.bounds.mapD( + (bbox) => { + self.update(bbox) + }, + [state.dataIsLoading] ) } private update(bbox: BBox) { - if (bbox === undefined) { - return - } const now = new Date() if ( this.lastUpdate !== undefined && @@ -42,7 +34,9 @@ export default class ContributorCount { return } this.lastUpdate = now - const featuresList = this.state.featurePipeline.GetAllFeaturesWithin(bbox) + const featuresList = [].concat( + Array.from(this.perLayer.values()).map((fs) => fs.GetFeaturesWithin(bbox)) + ) const hist = new Map() for (const list of featuresList) { for (const feature of list) { diff --git a/Logic/DetermineLayout.ts b/Logic/DetermineLayout.ts index 020467758..3b0e11ae6 100644 --- a/Logic/DetermineLayout.ts +++ b/Logic/DetermineLayout.ts @@ -20,9 +20,14 @@ import { FixImages } from "../Models/ThemeConfig/Conversion/FixImages" import Svg from "../Svg" import { DoesImageExist, - PrevalidateTheme, + PrevalidateTheme, ValidateTagRenderings, ValidateThemeAndLayers, } from "../Models/ThemeConfig/Conversion/Validation" +import {DesugaringContext, Each, On} from "../Models/ThemeConfig/Conversion/Conversion"; +import {PrepareLayer, RewriteSpecial} from "../Models/ThemeConfig/Conversion/PrepareLayer"; +import {AllSharedLayers} from "../Customizations/AllSharedLayers"; +import {TagRenderingConfigJson} from "../Models/ThemeConfig/Json/TagRenderingConfigJson"; +import questions from "../assets/tagRenderings/questions.json"; export default class DetermineLayout { private static readonly _knownImages = new Set(Array.from(licenses).map((l) => l.path)) @@ -62,7 +67,11 @@ export default class DetermineLayout { layoutId, "The layout to load into MapComplete" ).data - return AllKnownLayouts.allKnownLayouts.get(layoutId?.toLowerCase()) + const layout = AllKnownLayouts.allKnownLayouts.get(layoutId?.toLowerCase()) + if (layout === undefined) { + throw "No builtin map theme with name " + layoutId + " exists" + } + return layout } public static LoadLayoutFromHash(userLayoutParam: UIEventSource): LayoutConfig | null { @@ -142,9 +151,41 @@ export default class DetermineLayout { : undefined, ]) .SetClass("flex flex-col clickable") - .AttachTo("centermessage") + .AttachTo("maindiv") } + private static getSharedTagRenderings(): Map { + const dict = new Map() + + const prep = new RewriteSpecial() + const validator = new ValidateTagRenderings() + for (const key in questions) { + if (key === "id") { + continue + } + questions[key].id = key + questions[key]["source"] = "shared-questions" + const config = prep.convertStrict( + questions[key], + "questions.json:" + key + ) + delete config["#"] + validator.convertStrict( + config, + "generate-layer-overview:tagRenderings/questions.json:" + key + ) + dict.set(key, config) + } + + dict.forEach((value, key) => { + if (key === "id") { + return + } + value.id = value.id ?? key + }) + + return dict + } private static prepCustomTheme(json: any, sourceUrl?: string, forceId?: string): LayoutConfig { if (json.layers === undefined && json.tagRenderings !== undefined) { const iconTr = json.mapRendering.map((mr) => mr.icon).find((icon) => icon !== undefined) @@ -166,8 +207,8 @@ export default class DetermineLayout { const layer = known_layers.layers[key] knownLayersDict.set(layer.id, layer) } - const converState = { - tagRenderings: SharedTagRenderings.SharedTagRenderingJson, + const convertState: DesugaringContext = { + tagRenderings: DetermineLayout.getSharedTagRenderings(), sharedLayers: knownLayersDict, publicLayers: new Set(), } @@ -179,7 +220,7 @@ export default class DetermineLayout { "While fixing the images" ) json.enableNoteImports = json.enableNoteImports ?? false - json = new PrepareTheme(converState).convertStrict(json, "While preparing a dynamic theme") + json = new PrepareTheme(convertState).convertStrict(json, "While preparing a dynamic theme") console.log("The layoutconfig is ", json) json.id = forceId ?? json.id @@ -210,7 +251,7 @@ export default class DetermineLayout { console.log("Downloading map theme from ", link) new FixedUiElement(`Downloading the theme from the link...`).AttachTo( - "centermessage" + "maindiv" ) try { diff --git a/Logic/ElementStorage.ts b/Logic/ElementStorage.ts deleted file mode 100644 index 8d9723f8e..000000000 --- a/Logic/ElementStorage.ts +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Keeps track of a dictionary 'elementID' -> UIEventSource - */ -import { UIEventSource } from "./UIEventSource" -import { GeoJSONObject } from "@turf/turf" -import { Feature, Geometry, Point } from "geojson" -import { OsmTags } from "../Models/OsmFeature" - -export class ElementStorage { - public ContainingFeatures = new Map>() - private _elements = new Map>() - - constructor() {} - - addElementById(id: string, eventSource: UIEventSource) { - this._elements.set(id, eventSource) - } - - /** - * Creates a UIEventSource for the tags of the given feature. - * If an UIEventsource has been created previously, the same UIEventSource will be returned - * - * Note: it will cleverly merge the tags, if needed - */ - addOrGetElement(feature: Feature): UIEventSource { - const elementId = feature.properties.id - const newProperties = feature.properties - - const es = this.addOrGetById(elementId, newProperties) - - // At last, we overwrite the tag of the new feature to use the tags in the already existing event source - feature.properties = es.data - - if (!this.ContainingFeatures.has(elementId)) { - this.ContainingFeatures.set(elementId, feature) - } - - return es - } - - getEventSourceById(elementId): UIEventSource | undefined { - if (elementId === undefined) { - return undefined - } - return this._elements.get(elementId) - } - - has(id) { - return this._elements.has(id) - } - - addAlias(oldId: string, newId: string) { - if (newId === undefined) { - // We removed the node/way/relation with type 'type' and id 'oldId' on openstreetmap! - const element = this.getEventSourceById(oldId) - element.data._deleted = "yes" - element.ping() - return - } - - if (oldId == newId) { - return undefined - } - const element = this.getEventSourceById(oldId) - if (element === undefined) { - // Element to rewrite not found, probably a node or relation that is not rendered - return undefined - } - element.data.id = newId - this.addElementById(newId, element) - this.ContainingFeatures.set(newId, this.ContainingFeatures.get(oldId)) - element.ping() - } - - private addOrGetById(elementId: string, newProperties: any): UIEventSource { - if (!this._elements.has(elementId)) { - const eventSource = new UIEventSource(newProperties, "tags of " + elementId) - this._elements.set(elementId, eventSource) - return eventSource - } - - const es = this._elements.get(elementId) - if (es.data == newProperties) { - // Reference comparison gives the same object! we can just return the event source - return es - } - const keptKeys = es.data - // The element already exists - // We use the new feature to overwrite all the properties in the already existing eventsource - const debug_msg = [] - let somethingChanged = false - for (const k in newProperties) { - if (!newProperties.hasOwnProperty(k)) { - continue - } - const v = newProperties[k] - - if (keptKeys[k] !== v) { - if (v === undefined) { - // The new value is undefined; the tag might have been removed - // It might be a metatag as well - // In the latter case, we do keep the tag! - if (!k.startsWith("_")) { - delete keptKeys[k] - debug_msg.push("Erased " + k) - } - } else { - keptKeys[k] = v - debug_msg.push(k + " --> " + v) - } - - somethingChanged = true - } - } - if (somethingChanged) { - es.ping() - } - return es - } -} diff --git a/Logic/ExtraFunctions.ts b/Logic/ExtraFunctions.ts index dd568cab4..7da38b9af 100644 --- a/Logic/ExtraFunctions.ts +++ b/Logic/ExtraFunctions.ts @@ -1,11 +1,11 @@ -import { GeoOperations } from "./GeoOperations" +import {GeoOperations} from "./GeoOperations" import Combine from "../UI/Base/Combine" -import RelationsTracker from "./Osm/RelationsTracker" import BaseUIElement from "../UI/BaseUIElement" import List from "../UI/Base/List" import Title from "../UI/Base/Title" -import { BBox } from "./BBox" -import { Feature, Geometry, MultiPolygon, Polygon } from "@turf/turf" +import {BBox} from "./BBox" +import {Feature, Geometry, MultiPolygon, Polygon} from "geojson" +import {GeoJSONFeature} from "maplibre-gl"; export interface ExtraFuncParams { /** @@ -13,9 +13,8 @@ export interface ExtraFuncParams { * Note that more features then requested can be given back. * Format: [ [ geojson, geojson, geojson, ... ], [geojson, ...], ...] */ - getFeaturesWithin: (layerId: string, bbox: BBox) => Feature[][] - memberships: RelationsTracker - getFeatureById: (id: string) => Feature + getFeaturesWithin: (layerId: string, bbox: BBox) => Feature>[][] + getFeatureById: (id: string) => Feature> } /** @@ -56,6 +55,7 @@ class EnclosingFunc implements ExtraFunction { } for (const otherFeatures of otherFeaturess) { for (const otherFeature of otherFeatures) { + if (seenIds.has(otherFeature.properties.id)) { continue } @@ -68,11 +68,11 @@ class EnclosingFunc implements ExtraFunction { } if ( GeoOperations.completelyWithin( - feat, + feat, >otherFeature ) ) { - result.push({ feat: otherFeature }) + result.push({feat: otherFeature}) } } } @@ -92,7 +92,7 @@ class OverlapFunc implements ExtraFunction { "The returned value is `{ feat: GeoJSONFeature, overlap: number}[]` where `overlap` is the overlapping surface are (in m²) for areas, the overlapping length (in meter) if the current feature is a line or `undefined` if the current feature is a point.", "The resulting list is sorted in descending order by overlap. The feature with the most overlap will thus be the first in the list.", "", - "For example to get all objects which overlap or embed from a layer, use `_contained_climbing_routes_properties=feat.overlapWith('climbing_route')`", + "For example to get all objects which overlap or embed from a layer, use `_contained_climbing_routes_properties=overlapWith(feat)('climbing_route')`", "", "Also see [enclosingFeatures](#enclosingFeatures) which can be used to get all objects which fully contain this feature", ].join("\n") @@ -156,13 +156,13 @@ class IntersectionFunc implements ExtraFunction { if (otherLayers.length === 0) { continue } - for (const tile of otherLayers) { - for (const otherFeature of tile) { - const intersections = GeoOperations.LineIntersections(feat, otherFeature) + for (const otherFeatures of otherLayers) { + for (const otherFeature of otherFeatures) { + const intersections = GeoOperations.LineIntersections(feat, >>otherFeature) if (intersections.length === 0) { continue } - result.push({ feat: otherFeature, intersections }) + result.push({feat: otherFeature, intersections}) } } } @@ -247,20 +247,22 @@ class ClosestNObjectFunc implements ExtraFunction { static GetClosestNFeatures( params: ExtraFuncParams, feature: any, - features: string | any[], + features: string | Feature[], options?: { maxFeatures?: number; uniqueTag?: string | undefined; maxDistance?: number } ): { feat: any; distance: number }[] { const maxFeatures = options?.maxFeatures ?? 1 const maxDistance = options?.maxDistance ?? 500 const uniqueTag: string | undefined = options?.uniqueTag + let allFeatures: Feature[][] + console.log("Calculating closest", options?.maxFeatures, "features around", feature, "in layer", features) if (typeof features === "string") { const name = features const bbox = GeoOperations.bbox( GeoOperations.buffer(GeoOperations.bbox(feature), maxDistance) ) - features = params.getFeaturesWithin(name, new BBox(bbox.geometry.coordinates)) + allFeatures = params.getFeaturesWithin(name, new BBox(bbox.geometry.coordinates)) } else { - features = [features] + allFeatures = [features] } if (features === undefined) { return @@ -269,9 +271,9 @@ class ClosestNObjectFunc implements ExtraFunction { const selfCenter = GeoOperations.centerpointCoordinates(feature) let closestFeatures: { feat: any; distance: number }[] = [] - for (const featureList of features) { - // Features is provided by 'getFeaturesWithin' which returns a list of lists of features, hence the double loop here - for (const otherFeature of featureList) { + for (const feats of allFeatures) { + + for (const otherFeature of feats) { if ( otherFeature === feature || otherFeature.properties.id === feature.properties.id @@ -331,7 +333,7 @@ class ClosestNObjectFunc implements ExtraFunction { const uniqueTagsMatch = otherFeature.properties[uniqueTag] !== undefined && closestFeature.feat.properties[uniqueTag] === - otherFeature.properties[uniqueTag] + otherFeature.properties[uniqueTag] if (uniqueTagsMatch) { targetIndex = -1 if (closestFeature.distance > distance) { @@ -339,7 +341,7 @@ class ClosestNObjectFunc implements ExtraFunction { // We want to see the tag `uniquetag=some_value` only once in the entire list (e.g. to prevent road segements of identical names to fill up the list of 'names of nearby roads') // AT this point, we have found a closer segment with the same, identical tag // so we replace directly - closestFeatures[i] = { feat: otherFeature, distance: distance } + closestFeatures[i] = {feat: otherFeature, distance: distance} } break } @@ -401,19 +403,6 @@ class ClosestNObjectFunc implements ExtraFunction { } } -class Memberships implements ExtraFunction { - _name = "memberships" - _doc = - "Gives a list of `{role: string, relation: Relation}`-objects, containing all the relations that this feature is part of. " + - "\n\n" + - "For example: `_part_of_walking_routes=feat.memberships().map(r => r.relation.tags.name).join(';')`" - _args = [] - - _f(params, feat) { - return () => params.memberships.knownRelations.data.get(feat.properties.id) ?? [] - } -} - class GetParsed implements ExtraFunction { _name = "get" _doc = @@ -426,6 +415,9 @@ class GetParsed implements ExtraFunction { if (value === undefined) { return undefined } + if (typeof value !== "string") { + return value + } try { const parsed = JSON.parse(value) if (parsed === null) { @@ -442,6 +434,8 @@ class GetParsed implements ExtraFunction { } } +export type ExtraFuncType = typeof ExtraFunctions.types[number] + export class ExtraFunctions { static readonly intro = new Combine([ new Title("Calculating tags with Javascript", 2), @@ -459,7 +453,7 @@ export class ExtraFunctions { '"calculatedTags": [', ' "_someKey=javascript-expression",', ' "name=feat.properties.name ?? feat.properties.ref ?? feat.properties.operator",', - " \"_distanceCloserThen3Km=feat.distanceTo( some_lon, some_lat) < 3 ? 'yes' : 'no'\" ", + " \"_distanceCloserThen3Km=distanceTo(feat)( some_lon, some_lat) < 3 ? 'yes' : 'no'\" ", " ]", "````", "", @@ -469,30 +463,32 @@ export class ExtraFunctions { "`area` contains the surface area (in square meters) of the object", "`lat` and `lon` contain the latitude and longitude", ]), - "Some advanced functions are available on **feat** as well:", + "Some advanced functions are available as well. Due to technical reasons, they should be used as `funcname(feat)(arguments)`.", ]) .SetClass("flex-col") .AsMarkdown() - private static readonly allFuncs: ExtraFunction[] = [ + static readonly types = ["distanceTo", "overlapWith", "enclosingFeatures", "intersectionsWith", "closest", "closestn", "get"] as const + private static readonly allFuncs = [ new DistanceToFunc(), new OverlapFunc(), new EnclosingFunc(), new IntersectionFunc(), new ClosestObjectFunc(), new ClosestNObjectFunc(), - new Memberships(), new GetParsed(), ] - public static FullPatchFeature(params: ExtraFuncParams, feature) { - if (feature._is_patched) { - return - } - feature._is_patched = true - for (const func of ExtraFunctions.allFuncs) { - feature[func._name] = func._f(params, feature) + + public static constructHelpers(params: ExtraFuncParams): Record Function> { + const record: Record Function> = {} + for (const f of ExtraFunctions.allFuncs) { + if (this.types.indexOf(f._name) < 0) { + throw "Invalid extraFunc-type: " + f._name + } + record[f._name] = (feat) => f._f(params, feat) } + return record } public static HelpText(): BaseUIElement { diff --git a/Logic/FeatureSource/Actors/FeaturePropertiesStore.ts b/Logic/FeatureSource/Actors/FeaturePropertiesStore.ts new file mode 100644 index 000000000..3ff9dd6e0 --- /dev/null +++ b/Logic/FeatureSource/Actors/FeaturePropertiesStore.ts @@ -0,0 +1,112 @@ +import {FeatureSource} from "../FeatureSource" +import {UIEventSource} from "../../UIEventSource" + +/** + * Constructs a UIEventStore for the properties of every Feature, indexed by id + */ +export default class FeaturePropertiesStore { + private readonly _elements = new Map>>() + + constructor(...sources: FeatureSource[]) { + for (const source of sources) { + this.trackFeatureSource(source) + } + } + + public getStore(id: string): UIEventSource> { + return this._elements.get(id) + } + + public trackFeatureSource(source: FeatureSource) { + const self = this + source.features.addCallbackAndRunD((features) => { + for (const feature of features) { + const id = feature.properties.id + if (id === undefined) { + console.trace("Error: feature without ID:", feature) + throw "Error: feature without ID" + } + + const source = self._elements.get(id) + if (source === undefined) { + self._elements.set(id, new UIEventSource(feature.properties)) + continue + } + + if (source.data === feature.properties) { + continue + } + + // Update the tags in the old store and link them + const changeMade = FeaturePropertiesStore.mergeTags(source.data, feature.properties) + feature.properties = source.data + if (changeMade) { + source.ping() + } + } + }) + } + + /** + * Overwrites the tags of the old properties object, returns true if a change was made. + * Metatags are overriden if they are in the new properties, but not removed + * @param oldProperties + * @param newProperties + * @private + */ + private static mergeTags( + oldProperties: Record, + newProperties: Record + ): boolean { + let changeMade = false + + for (const oldPropertiesKey in oldProperties) { + // Delete properties from the old record if it is not in the new store anymore + if (oldPropertiesKey.startsWith("_")) { + continue + } + if (newProperties[oldPropertiesKey] === undefined) { + changeMade = true + delete oldProperties[oldPropertiesKey] + } + } + + // Copy all properties from the new record into the old + for (const newPropertiesKey in newProperties) { + const v = newProperties[newPropertiesKey] + if (oldProperties[newPropertiesKey] !== v) { + oldProperties[newPropertiesKey] = v + changeMade = true + } + } + + return changeMade + } + + // noinspection JSUnusedGlobalSymbols + public addAlias(oldId: string, newId: string): void { + if (newId === undefined) { + // We removed the node/way/relation with type 'type' and id 'oldId' on openstreetmap! + const element = this._elements.get(oldId) + element.data._deleted = "yes" + element.ping() + return + } + + if (oldId == newId) { + return + } + const element = this._elements.get(oldId) + if (element === undefined) { + // Element to rewrite not found, probably a node or relation that is not rendered + return + } + element.data.id = newId + this._elements.set(newId, element) + element.ping() + } + + has(id: string) { + return this._elements.has(id) + } +} diff --git a/Logic/FeatureSource/Actors/GeoIndexedStore.ts b/Logic/FeatureSource/Actors/GeoIndexedStore.ts new file mode 100644 index 000000000..15bc28fdf --- /dev/null +++ b/Logic/FeatureSource/Actors/GeoIndexedStore.ts @@ -0,0 +1,53 @@ +import { FeatureSource, FeatureSourceForLayer } from "../FeatureSource" +import { Feature } from "geojson" +import { BBox } from "../../BBox" +import { GeoOperations } from "../../GeoOperations" +import { Store } from "../../UIEventSource" +import FilteredLayer from "../../../Models/FilteredLayer" + +/** + * Allows the retrieval of all features in the requested BBox; useful for one-shot queries; + * + * Use a ClippedFeatureSource for a continuously updating featuresource + */ +export default class GeoIndexedStore implements FeatureSource { + public features: Store + + constructor(features: FeatureSource | Store) { + this.features = features["features"] ?? features + } + + /** + * Gets the current features within the given bbox. + * + * @param bbox + * @constructor + */ + public GetFeaturesWithin(bbox: BBox): Feature[] { + const bboxFeature = bbox.asGeojsonCached() + return this.features.data.filter((f) => { + if (f.geometry.type === "Point") { + return bbox.contains(<[number, number]>f.geometry.coordinates) + } + if (f.geometry.type === "LineString") { + const intersection = GeoOperations.intersect( + BBox.get(f).asGeojsonCached(), + bboxFeature + ) + return intersection !== undefined + } + if (f.geometry.type === "Polygon" || f.geometry.type === "MultiPolygon") { + return GeoOperations.intersect(f, bboxFeature) !== undefined + } + return GeoOperations.intersect(f, bboxFeature) !== undefined + }) + } +} + +export class GeoIndexedStoreForLayer extends GeoIndexedStore implements FeatureSourceForLayer { + readonly layer: FilteredLayer + constructor(features: FeatureSource | Store, layer: FilteredLayer) { + super(features) + this.layer = layer + } +} diff --git a/Logic/FeatureSource/Actors/MetaTagRecalculator.ts b/Logic/FeatureSource/Actors/MetaTagRecalculator.ts deleted file mode 100644 index 982939d4a..000000000 --- a/Logic/FeatureSource/Actors/MetaTagRecalculator.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { FeatureSourceForLayer, Tiled } from "../FeatureSource" -import MetaTagging from "../../MetaTagging" -import { ElementStorage } from "../../ElementStorage" -import { ExtraFuncParams } from "../../ExtraFunctions" -import FeaturePipeline from "../FeaturePipeline" -import { BBox } from "../../BBox" -import { UIEventSource } from "../../UIEventSource" - -/**** - * Concerned with the logic of updating the right layer at the right time - */ -class MetatagUpdater { - public readonly neededLayerBboxes = new Map() - private source: FeatureSourceForLayer & Tiled - private readonly params: ExtraFuncParams - private state: { allElements?: ElementStorage } - - private readonly isDirty = new UIEventSource(false) - - constructor( - source: FeatureSourceForLayer & Tiled, - state: { allElements?: ElementStorage }, - featurePipeline: FeaturePipeline - ) { - this.state = state - this.source = source - const self = this - this.params = { - getFeatureById(id) { - return state.allElements.ContainingFeatures.get(id) - }, - getFeaturesWithin(layerId, bbox) { - // We keep track of the BBOX that this source needs - let oldBbox: BBox = self.neededLayerBboxes.get(layerId) - if (oldBbox === undefined) { - self.neededLayerBboxes.set(layerId, bbox) - } else if (!bbox.isContainedIn(oldBbox)) { - self.neededLayerBboxes.set(layerId, oldBbox.unionWith(bbox)) - } - return featurePipeline.GetFeaturesWithin(layerId, bbox) - }, - memberships: featurePipeline.relationTracker, - } - this.isDirty.stabilized(100).addCallback((dirty) => { - if (dirty) { - self.updateMetaTags() - } - }) - this.source.features.addCallbackAndRunD((_) => self.isDirty.setData(true)) - } - - public requestUpdate() { - this.isDirty.setData(true) - } - - public updateMetaTags() { - const features = this.source.features.data - - if (features.length === 0) { - this.isDirty.setData(false) - return - } - MetaTagging.addMetatags(features, this.params, this.source.layer.layerDef, this.state) - this.isDirty.setData(false) - } -} - -export default class MetaTagRecalculator { - private _state: { - allElements?: ElementStorage - } - private _featurePipeline: FeaturePipeline - private readonly _alreadyRegistered: Set = new Set< - FeatureSourceForLayer & Tiled - >() - private readonly _notifiers: MetatagUpdater[] = [] - - /** - * The meta tag recalculator receives tiles of layers via the 'registerSource'-function. - * It keeps track of which sources have had their share calculated, and which should be re-updated if some other data is loaded - */ - constructor( - state: { allElements?: ElementStorage; currentView: FeatureSourceForLayer & Tiled }, - featurePipeline: FeaturePipeline - ) { - this._featurePipeline = featurePipeline - this._state = state - - if (state.currentView !== undefined) { - const currentViewUpdater = new MetatagUpdater( - state.currentView, - this._state, - this._featurePipeline - ) - this._alreadyRegistered.add(state.currentView) - this._notifiers.push(currentViewUpdater) - state.currentView.features.addCallback((_) => { - console.debug("Requesting an update for currentView") - currentViewUpdater.updateMetaTags() - }) - } - } - - public registerSource(source: FeatureSourceForLayer & Tiled, recalculateOnEveryChange = false) { - if (source === undefined) { - return - } - if (this._alreadyRegistered.has(source)) { - return - } - this._alreadyRegistered.add(source) - this._notifiers.push(new MetatagUpdater(source, this._state, this._featurePipeline)) - const self = this - source.features.addCallbackAndRunD((_) => { - const layerName = source.layer.layerDef.id - for (const updater of self._notifiers) { - const neededBbox = updater.neededLayerBboxes.get(layerName) - if (neededBbox == undefined) { - continue - } - if (source.bbox === undefined || neededBbox.overlapsWith(source.bbox)) { - updater.requestUpdate() - } - } - }) - } -} diff --git a/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts b/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts deleted file mode 100644 index 01ad3917b..000000000 --- a/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts +++ /dev/null @@ -1,21 +0,0 @@ -import FeatureSource from "../FeatureSource" -import { Store } from "../../UIEventSource" -import { ElementStorage } from "../../ElementStorage" - -/** - * Makes sure that every feature is added to the ElementsStorage, so that the tags-eventsource can be retrieved - */ -export default class RegisteringAllFromFeatureSourceActor { - public readonly features: Store<{ feature: any; freshness: Date }[]> - public readonly name - - constructor(source: FeatureSource, allElements: ElementStorage) { - this.features = source.features - this.name = "RegisteringSource of " + source.name - this.features.addCallbackAndRunD((features) => { - for (const feature of features) { - allElements.addOrGetElement(feature.feature) - } - }) - } -} diff --git a/Logic/FeatureSource/Actors/SaveFeatureSourceToLocalStorage.ts b/Logic/FeatureSource/Actors/SaveFeatureSourceToLocalStorage.ts new file mode 100644 index 000000000..fdfa4e21d --- /dev/null +++ b/Logic/FeatureSource/Actors/SaveFeatureSourceToLocalStorage.ts @@ -0,0 +1,83 @@ +import { FeatureSource } from "../FeatureSource" +import { Feature } from "geojson" +import TileLocalStorage from "./TileLocalStorage" +import { GeoOperations } from "../../GeoOperations" +import FeaturePropertiesStore from "./FeaturePropertiesStore" +import { UIEventSource } from "../../UIEventSource" +import { Utils } from "../../../Utils" + +class SingleTileSaver { + private readonly _storage: UIEventSource + private readonly _registeredIds = new Set() + private readonly _featureProperties: FeaturePropertiesStore + private readonly _isDirty = new UIEventSource(false) + constructor( + storage: UIEventSource & { flush: () => void }, + featureProperties: FeaturePropertiesStore + ) { + this._storage = storage + this._featureProperties = featureProperties + this._isDirty.stabilized(1000).addCallbackD((isDirty) => { + if (!isDirty) { + return + } + // 'isDirty' is set when tags of some object have changed + storage.flush() + this._isDirty.setData(false) + }) + } + + public saveFeatures(features: Feature[]) { + if (Utils.sameList(features, this._storage.data)) { + return + } + for (const feature of features) { + const id = feature.properties.id + if (this._registeredIds.has(id)) { + continue + } + this._featureProperties.getStore(id)?.addCallbackAndRunD(() => { + this._isDirty.setData(true) + }) + this._registeredIds.add(id) + } + + this._storage.setData(features) + } +} + +/*** + * Saves all the features that are passed in to localstorage, so they can be retrieved on the next run + * + * The data is saved in a tiled way on a fixed zoomlevel and is retrievable per layer. + * + * Also see the sibling class + */ +export default class SaveFeatureSourceToLocalStorage { + constructor( + backend: string, + layername: string, + zoomlevel: number, + features: FeatureSource, + featureProperties: FeaturePropertiesStore, + maxCacheAge: number + ) { + const storage = TileLocalStorage.construct(backend, layername, maxCacheAge) + const singleTileSavers: Map = new Map() + features.features.addCallbackAndRunD((features) => { + const sliced = GeoOperations.slice(zoomlevel, features) + + sliced.forEach((features, tileIndex) => { + let tileSaver = singleTileSavers.get(tileIndex) + if (tileSaver === undefined) { + const src = storage.getTileSource(tileIndex) + tileSaver = new SingleTileSaver(src, featureProperties) + singleTileSavers.set(tileIndex, tileSaver) + } + // Don't cache not-uploaded features yet - they'll be cached when the receive their id + features = features.filter((f) => !f.properties.id.match(/(node|way)\/-[0-9]+/)) + tileSaver.saveFeatures(features) + }) + }) + } +} diff --git a/Logic/FeatureSource/Actors/SaveTileToLocalStorageActor.ts b/Logic/FeatureSource/Actors/SaveTileToLocalStorageActor.ts deleted file mode 100644 index 12ef0e574..000000000 --- a/Logic/FeatureSource/Actors/SaveTileToLocalStorageActor.ts +++ /dev/null @@ -1,148 +0,0 @@ -import FeatureSource, { Tiled } from "../FeatureSource" -import { Tiles } from "../../../Models/TileRange" -import { IdbLocalStorage } from "../../Web/IdbLocalStorage" -import { UIEventSource } from "../../UIEventSource" -import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" -import { BBox } from "../../BBox" -import SimpleFeatureSource from "../Sources/SimpleFeatureSource" -import FilteredLayer from "../../../Models/FilteredLayer" -import Loc from "../../../Models/Loc" - -/*** - * Saves all the features that are passed in to localstorage, so they can be retrieved on the next run - * - * Technically, more an Actor then a featuresource, but it fits more neatly this way - */ -export default class SaveTileToLocalStorageActor { - private readonly visitedTiles: UIEventSource> - private readonly _layer: LayerConfig - private readonly _flayer: FilteredLayer - private readonly initializeTime = new Date() - - constructor(layer: FilteredLayer) { - this._flayer = layer - this._layer = layer.layerDef - this.visitedTiles = IdbLocalStorage.Get("visited_tiles_" + this._layer.id, { - defaultValue: new Map(), - }) - this.visitedTiles.stabilized(100).addCallbackAndRunD((tiles) => { - for (const key of Array.from(tiles.keys())) { - const tileFreshness = tiles.get(key) - - const toOld = - this.initializeTime.getTime() - tileFreshness.getTime() > - 1000 * this._layer.maxAgeOfCache - if (toOld) { - // Purge this tile - this.SetIdb(key, undefined) - console.debug("Purging tile", this._layer.id, key) - tiles.delete(key) - } - } - this.visitedTiles.ping() - return true - }) - } - - public LoadTilesFromDisk( - currentBounds: UIEventSource, - location: UIEventSource, - registerFreshness: (tileId: number, freshness: Date) => void, - registerTile: (src: FeatureSource & Tiled) => void - ) { - const self = this - const loadedTiles = new Set() - this.visitedTiles.addCallbackD((tiles) => { - if (tiles.size === 0) { - // We don't do anything yet as probably not yet loaded from disk - // We'll unregister later on - return - } - currentBounds.addCallbackAndRunD((bbox) => { - if (self._layer.minzoomVisible > location.data.zoom) { - // Not enough zoom - return - } - - // Iterate over all available keys in the local storage, check which are needed and fresh enough - for (const key of Array.from(tiles.keys())) { - const tileFreshness = tiles.get(key) - if (tileFreshness > self.initializeTime) { - // This tile is loaded by another source - continue - } - - registerFreshness(key, tileFreshness) - const tileBbox = BBox.fromTileIndex(key) - if (!bbox.overlapsWith(tileBbox)) { - continue - } - if (loadedTiles.has(key)) { - // Already loaded earlier - continue - } - loadedTiles.add(key) - this.GetIdb(key).then((features: { feature: any; freshness: Date }[]) => { - if (features === undefined) { - return - } - console.debug("Loaded tile " + self._layer.id + "_" + key + " from disk") - const src = new SimpleFeatureSource( - self._flayer, - key, - new UIEventSource<{ feature: any; freshness: Date }[]>(features) - ) - registerTile(src) - }) - } - }) - - return true // Remove the callback - }) - } - - public addTile(tile: FeatureSource & Tiled) { - const self = this - tile.features.addCallbackAndRunD((features) => { - const now = new Date() - - if (features.length > 0) { - self.SetIdb(tile.tileIndex, features) - } - // We _still_ write the time to know that this tile is empty! - this.MarkVisited(tile.tileIndex, now) - }) - } - - public poison(lon: number, lat: number) { - for (let z = 0; z < 25; z++) { - const { x, y } = Tiles.embedded_tile(lat, lon, z) - const tileId = Tiles.tile_index(z, x, y) - this.visitedTiles.data.delete(tileId) - } - } - - public MarkVisited(tileId: number, freshness: Date) { - this.visitedTiles.data.set(tileId, freshness) - this.visitedTiles.ping() - } - - private SetIdb(tileIndex, data) { - try { - IdbLocalStorage.SetDirectly(this._layer.id + "_" + tileIndex, data) - } catch (e) { - console.error( - "Could not save tile to indexed-db: ", - e, - "tileIndex is:", - tileIndex, - "for layer", - this._layer.id - ) - } - } - - private GetIdb(tileIndex) { - return IdbLocalStorage.GetDirectly(this._layer.id + "_" + tileIndex) - } -} diff --git a/Logic/FeatureSource/Actors/TileLocalStorage.ts b/Logic/FeatureSource/Actors/TileLocalStorage.ts new file mode 100644 index 000000000..97feb53d3 --- /dev/null +++ b/Logic/FeatureSource/Actors/TileLocalStorage.ts @@ -0,0 +1,99 @@ +import {IdbLocalStorage} from "../../Web/IdbLocalStorage" +import {UIEventSource} from "../../UIEventSource" + +/** + * A class which allows to read/write a tile to local storage. + * + * Does the heavy lifting for LocalStorageFeatureSource and SaveFeatureToLocalStorage. + * + * Note: OSM-features with a negative id are ignored + */ +export default class TileLocalStorage { + private static perLayer: Record> = {} + private static readonly useIndexedDb = typeof indexedDB !== "undefined" + private readonly _layername: string + private readonly inUse = new UIEventSource(false) + private readonly cachedSources: Record & { flush: () => void }> = {} + private readonly _maxAgeSeconds: number; + + private constructor(layername: string, maxAgeSeconds: number) { + this._layername = layername + this._maxAgeSeconds = maxAgeSeconds; + } + + public static construct(backend: string, layername: string, maxAgeS: number): TileLocalStorage { + const key = backend + "_" + layername + const cached = TileLocalStorage.perLayer[key] + if (cached) { + return cached + } + + const tls = new TileLocalStorage(key, maxAgeS) + TileLocalStorage.perLayer[key] = tls + return tls + } + + /** + * Constructs a UIEventSource element which is synced with localStorage. + * Supports 'flush' + */ + public getTileSource(tileIndex: number): UIEventSource & { flush: () => void } { + const cached = this.cachedSources[tileIndex] + if (cached) { + return cached + } + const src = & { flush: () => void }>( + UIEventSource.FromPromise(this.GetIdb(tileIndex)) + ) + src.flush = () => this.SetIdb(tileIndex, src.data) + src.addCallbackD((data) => this.SetIdb(tileIndex, data)) + this.cachedSources[tileIndex] = src + return src + } + + private async SetIdb(tileIndex: number, data: any): Promise { + if (!TileLocalStorage.useIndexedDb) { + return + } + try { + await this.inUse.AsPromise((inUse) => !inUse) + this.inUse.setData(true) + await IdbLocalStorage.SetDirectly(this._layername + "_" + tileIndex, data) + await IdbLocalStorage.SetDirectly(this._layername + "_" + tileIndex + "_date", Date.now()) + + this.inUse.setData(false) + } catch (e) { + console.error( + "Could not save tile to indexed-db: ", + e, + "tileIndex is:", + tileIndex, + "for layer", + this._layername, + "data is", + data + ) + } + } + + private async GetIdb(tileIndex: number): Promise { + if (!TileLocalStorage.useIndexedDb) { + return undefined + } + const date = await IdbLocalStorage.GetDirectly(this._layername + "_" + tileIndex + "_date") + const maxAge = this._maxAgeSeconds + const timeDiff = Date.now() - date + if (timeDiff >= maxAge) { + console.debug("Dropping cache for", this._layername, tileIndex, "out of date") + await IdbLocalStorage.SetDirectly(this._layername + "_" + tileIndex, undefined) + + return undefined + } + const data = await IdbLocalStorage.GetDirectly(this._layername + "_" + tileIndex) + return data + } + + invalidate(zoomlevel: number, tileIndex) { + this.getTileSource(tileIndex).setData(undefined) + } +} diff --git a/Logic/FeatureSource/FeaturePipeline.ts b/Logic/FeatureSource/FeaturePipeline.ts deleted file mode 100644 index e398294d6..000000000 --- a/Logic/FeatureSource/FeaturePipeline.ts +++ /dev/null @@ -1,648 +0,0 @@ -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import FilteringFeatureSource from "./Sources/FilteringFeatureSource" -import PerLayerFeatureSourceSplitter from "./PerLayerFeatureSourceSplitter" -import FeatureSource, { FeatureSourceForLayer, IndexedFeatureSource, Tiled } from "./FeatureSource" -import TiledFeatureSource from "./TiledFeatureSource/TiledFeatureSource" -import { Store, UIEventSource } from "../UIEventSource" -import { TileHierarchyTools } from "./TiledFeatureSource/TileHierarchy" -import RememberingSource from "./Sources/RememberingSource" -import OverpassFeatureSource from "../Actors/OverpassFeatureSource" -import GeoJsonSource from "./Sources/GeoJsonSource" -import Loc from "../../Models/Loc" -import RegisteringAllFromFeatureSourceActor from "./Actors/RegisteringAllFromFeatureSourceActor" -import SaveTileToLocalStorageActor from "./Actors/SaveTileToLocalStorageActor" -import DynamicGeoJsonTileSource from "./TiledFeatureSource/DynamicGeoJsonTileSource" -import { TileHierarchyMerger } from "./TiledFeatureSource/TileHierarchyMerger" -import RelationsTracker from "../Osm/RelationsTracker" -import { NewGeometryFromChangesFeatureSource } from "./Sources/NewGeometryFromChangesFeatureSource" -import ChangeGeometryApplicator from "./Sources/ChangeGeometryApplicator" -import { BBox } from "../BBox" -import OsmFeatureSource from "./TiledFeatureSource/OsmFeatureSource" -import { Tiles } from "../../Models/TileRange" -import TileFreshnessCalculator from "./TileFreshnessCalculator" -import FullNodeDatabaseSource from "./TiledFeatureSource/FullNodeDatabaseSource" -import MapState from "../State/MapState" -import { ElementStorage } from "../ElementStorage" -import { OsmFeature } from "../../Models/OsmFeature" -import LayerConfig from "../../Models/ThemeConfig/LayerConfig" -import { FilterState } from "../../Models/FilteredLayer" -import { GeoOperations } from "../GeoOperations" -import { Utils } from "../../Utils" - -/** - * The features pipeline ties together a myriad of various datasources: - * - * - The Overpass-API - * - The OSM-API - * - Third-party geojson files, either sliced or directly. - * - * In order to truly understand this class, please have a look at the following diagram: https://cdn-images-1.medium.com/fit/c/800/618/1*qTK1iCtyJUr4zOyw4IFD7A.jpeg - * - * - */ -export default class FeaturePipeline { - public readonly sufficientlyZoomed: Store - public readonly runningQuery: Store - public readonly timeout: UIEventSource - public readonly somethingLoaded: UIEventSource = new UIEventSource(false) - public readonly newDataLoadedSignal: UIEventSource = - new UIEventSource(undefined) - public readonly relationTracker: RelationsTracker - /** - * Keeps track of all raw OSM-nodes. - * Only initialized if 'type_node' is defined as layer - */ - public readonly fullNodeDatabase?: FullNodeDatabaseSource - private readonly overpassUpdater: OverpassFeatureSource - private state: MapState - private readonly perLayerHierarchy: Map - /** - * Keeps track of the age of the loaded data. - * Has one freshness-Calculator for every layer - * @private - */ - private readonly freshnesses = new Map() - private readonly oldestAllowedDate: Date - private readonly osmSourceZoomLevel - private readonly localStorageSavers = new Map() - - private readonly newGeometryHandler: NewGeometryFromChangesFeatureSource - - constructor( - handleFeatureSource: (source: FeatureSourceForLayer & Tiled) => void, - state: MapState, - options?: { - /*Used for metatagging - will receive all the sources with changeGeometry applied but without filtering*/ - handleRawFeatureSource: (source: FeatureSourceForLayer) => void - } - ) { - this.state = state - - const self = this - const expiryInSeconds = Math.min( - ...(state.layoutToUse?.layers?.map((l) => l.maxAgeOfCache) ?? []) - ) - this.oldestAllowedDate = new Date(new Date().getTime() - expiryInSeconds) - this.osmSourceZoomLevel = state.osmApiTileSize.data - const useOsmApi = state.locationControl.map( - (l) => l.zoom > (state.overpassMaxZoom.data ?? 12) - ) - this.relationTracker = new RelationsTracker() - - state.changes.allChanges.addCallbackAndRun((allChanges) => { - allChanges - .filter((ch) => ch.id < 0 && ch.changes !== undefined) - .map((ch) => ch.changes) - .filter((coor) => coor["lat"] !== undefined && coor["lon"] !== undefined) - .forEach((coor) => { - state.layoutToUse.layers.forEach((l) => - self.localStorageSavers.get(l.id)?.poison(coor["lon"], coor["lat"]) - ) - }) - }) - - this.sufficientlyZoomed = state.locationControl.map((location) => { - if (location?.zoom === undefined) { - return false - } - let minzoom = Math.min( - ...state.filteredLayers.data.map((layer) => layer.layerDef.minzoom ?? 18) - ) - return location.zoom >= minzoom - }) - - const neededTilesFromOsm = this.getNeededTilesFromOsm(this.sufficientlyZoomed) - - const perLayerHierarchy = new Map() - this.perLayerHierarchy = perLayerHierarchy - - // Given a tile, wraps it and passes it on to render (handled by 'handleFeatureSource' - function patchedHandleFeatureSource( - src: FeatureSourceForLayer & IndexedFeatureSource & Tiled - ) { - // This will already contain the merged features for this tile. In other words, this will only be triggered once for every tile - const withChanges = new ChangeGeometryApplicator(src, state.changes) - const srcFiltered = new FilteringFeatureSource(state, src.tileIndex, withChanges) - - handleFeatureSource(srcFiltered) - if (options?.handleRawFeatureSource) { - options.handleRawFeatureSource(withChanges) - } - self.somethingLoaded.setData(true) - // We do not mark as visited here, this is the responsability of the code near the actual loader (e.g. overpassLoader and OSMApiFeatureLoader) - } - - function handlePriviligedFeatureSource(src: FeatureSourceForLayer & Tiled) { - // Passthrough to passed function, except that it registers as well - handleFeatureSource(src) - src.features.addCallbackAndRunD((fs) => { - fs.forEach((ff) => state.allElements.addOrGetElement(ff.feature)) - }) - } - - for (const filteredLayer of state.filteredLayers.data) { - const id = filteredLayer.layerDef.id - const source = filteredLayer.layerDef.source - - const hierarchy = new TileHierarchyMerger(filteredLayer, (tile, _) => - patchedHandleFeatureSource(tile) - ) - perLayerHierarchy.set(id, hierarchy) - - this.freshnesses.set(id, new TileFreshnessCalculator()) - - if (id === "type_node") { - this.fullNodeDatabase = new FullNodeDatabaseSource(filteredLayer, (tile) => { - new RegisteringAllFromFeatureSourceActor(tile, state.allElements) - perLayerHierarchy.get(tile.layer.layerDef.id).registerTile(tile) - tile.features.addCallbackAndRunD((_) => self.onNewDataLoaded(tile)) - }) - continue - } - - if (id === "selected_element") { - handlePriviligedFeatureSource(state.selectedElementsLayer) - continue - } - - if (id === "gps_location") { - handlePriviligedFeatureSource(state.currentUserLocation) - continue - } - - if (id === "gps_location_history") { - handlePriviligedFeatureSource(state.historicalUserLocations) - continue - } - - if (id === "gps_track") { - handlePriviligedFeatureSource(state.historicalUserLocationsTrack) - continue - } - - if (id === "home_location") { - handlePriviligedFeatureSource(state.homeLocation) - continue - } - - if (id === "current_view") { - handlePriviligedFeatureSource(state.currentView) - continue - } - - const localTileSaver = new SaveTileToLocalStorageActor(filteredLayer) - this.localStorageSavers.set(filteredLayer.layerDef.id, localTileSaver) - - if (source.geojsonSource === undefined) { - // This is an OSM layer - // We load the cached values and register them - // Getting data from upstream happens a bit lower - localTileSaver.LoadTilesFromDisk( - state.currentBounds, - state.locationControl, - (tileIndex, freshness) => - self.freshnesses.get(id).addTileLoad(tileIndex, freshness), - (tile) => { - console.debug("Loaded tile ", id, tile.tileIndex, "from local cache") - new RegisteringAllFromFeatureSourceActor(tile, state.allElements) - hierarchy.registerTile(tile) - tile.features.addCallbackAndRunD((_) => self.onNewDataLoaded(tile)) - } - ) - - continue - } - - if (source.geojsonZoomLevel === undefined) { - // This is a 'load everything at once' geojson layer - const src = new GeoJsonSource(filteredLayer) - - if (source.isOsmCacheLayer) { - // We split them up into tiles anyway as it is an OSM source - TiledFeatureSource.createHierarchy(src, { - layer: src.layer, - minZoomLevel: this.osmSourceZoomLevel, - noDuplicates: true, - registerTile: (tile) => { - new RegisteringAllFromFeatureSourceActor(tile, state.allElements) - perLayerHierarchy.get(id).registerTile(tile) - tile.features.addCallbackAndRunD((_) => self.onNewDataLoaded(tile)) - }, - }) - } else { - new RegisteringAllFromFeatureSourceActor(src, state.allElements) - perLayerHierarchy.get(id).registerTile(src) - src.features.addCallbackAndRunD((_) => self.onNewDataLoaded(src)) - } - } else { - new DynamicGeoJsonTileSource( - filteredLayer, - (tile) => { - new RegisteringAllFromFeatureSourceActor(tile, state.allElements) - perLayerHierarchy.get(id).registerTile(tile) - tile.features.addCallbackAndRunD((_) => self.onNewDataLoaded(tile)) - }, - state - ) - } - } - - const osmFeatureSource = new OsmFeatureSource({ - isActive: useOsmApi, - neededTiles: neededTilesFromOsm, - handleTile: (tile) => { - new RegisteringAllFromFeatureSourceActor(tile, state.allElements) - if (tile.layer.layerDef.maxAgeOfCache > 0) { - const saver = self.localStorageSavers.get(tile.layer.layerDef.id) - if (saver === undefined) { - console.error( - "No localStorageSaver found for layer ", - tile.layer.layerDef.id - ) - } - saver?.addTile(tile) - } - perLayerHierarchy.get(tile.layer.layerDef.id).registerTile(tile) - tile.features.addCallbackAndRunD((_) => self.onNewDataLoaded(tile)) - }, - state: state, - markTileVisited: (tileId) => - state.filteredLayers.data.forEach((flayer) => { - const layer = flayer.layerDef - if (layer.maxAgeOfCache > 0) { - const saver = self.localStorageSavers.get(layer.id) - if (saver === undefined) { - console.error("No local storage saver found for ", layer.id) - } else { - saver.MarkVisited(tileId, new Date()) - } - } - self.freshnesses.get(layer.id).addTileLoad(tileId, new Date()) - }), - }) - - if (this.fullNodeDatabase !== undefined) { - osmFeatureSource.rawDataHandlers.push((osmJson, tileId) => - this.fullNodeDatabase.handleOsmJson(osmJson, tileId) - ) - } - - const updater = this.initOverpassUpdater(state, useOsmApi) - this.overpassUpdater = updater - this.timeout = updater.timeout - - // Actually load data from the overpass source - new PerLayerFeatureSourceSplitter( - state.filteredLayers, - (source) => - TiledFeatureSource.createHierarchy(source, { - layer: source.layer, - minZoomLevel: source.layer.layerDef.minzoom, - noDuplicates: true, - maxFeatureCount: state.layoutToUse.clustering.minNeededElements, - maxZoomLevel: state.layoutToUse.clustering.maxZoom, - registerTile: (tile) => { - // We save the tile data for the given layer to local storage - data sourced from overpass - self.localStorageSavers.get(tile.layer.layerDef.id)?.addTile(tile) - perLayerHierarchy - .get(source.layer.layerDef.id) - .registerTile(new RememberingSource(tile)) - tile.features.addCallbackAndRunD((f) => { - if (f.length === 0) { - return - } - self.onNewDataLoaded(tile) - }) - }, - }), - updater, - { - handleLeftovers: (leftOvers) => { - console.warn("Overpass returned a few non-matched features:", leftOvers) - }, - } - ) - - // Also load points/lines that are newly added. - const newGeometry = new NewGeometryFromChangesFeatureSource( - state.changes, - state.allElements, - state.osmConnection._oauth_config.url - ) - this.newGeometryHandler = newGeometry - newGeometry.features.addCallbackAndRun((geometries) => { - console.debug("New geometries are:", geometries) - }) - - new RegisteringAllFromFeatureSourceActor(newGeometry, state.allElements) - // A NewGeometryFromChangesFeatureSource does not split per layer, so we do this next - new PerLayerFeatureSourceSplitter( - state.filteredLayers, - (perLayer) => { - // We don't bother to split them over tiles as it'll contain little features by default, so we simply add them like this - perLayerHierarchy.get(perLayer.layer.layerDef.id).registerTile(perLayer) - // AT last, we always apply the metatags whenever possible - perLayer.features.addCallbackAndRunD((_) => { - self.onNewDataLoaded(perLayer) - }) - }, - newGeometry, - { - handleLeftovers: (leftOvers) => { - console.warn("Got some leftovers from the filteredLayers: ", leftOvers) - }, - } - ) - - this.runningQuery = updater.runningQuery.map( - (overpass) => { - console.log( - "FeaturePipeline: runningQuery state changed: Overpass", - overpass ? "is querying," : "is idle,", - "osmFeatureSource is", - osmFeatureSource.isRunning - ? "is running and needs " + - neededTilesFromOsm.data?.length + - " tiles (already got " + - osmFeatureSource.downloadedTiles.size + - " tiles )" - : "is idle" - ) - return overpass || osmFeatureSource.isRunning.data - }, - [osmFeatureSource.isRunning] - ) - } - - public GetAllFeaturesWithin(bbox: BBox): OsmFeature[][] { - const self = this - const tiles: OsmFeature[][] = [] - Array.from(this.perLayerHierarchy.keys()).forEach((key) => { - const fetched: OsmFeature[][] = self.GetFeaturesWithin(key, bbox) - tiles.push(...fetched) - }) - return tiles - } - - public GetAllFeaturesAndMetaWithin( - bbox: BBox, - layerIdWhitelist?: Set - ): { features: OsmFeature[]; layer: string }[] { - const self = this - const tiles: { features: any[]; layer: string }[] = [] - Array.from(this.perLayerHierarchy.keys()).forEach((key) => { - if (layerIdWhitelist !== undefined && !layerIdWhitelist.has(key)) { - return - } - return tiles.push({ - layer: key, - features: [].concat(...self.GetFeaturesWithin(key, bbox)), - }) - }) - return tiles - } - - /** - * Gets all the tiles which overlap with the given BBOX. - * This might imply that extra features might be shown - */ - public GetFeaturesWithin(layerId: string, bbox: BBox): OsmFeature[][] { - if (layerId === "*") { - return this.GetAllFeaturesWithin(bbox) - } - const requestedHierarchy = this.perLayerHierarchy.get(layerId) - if (requestedHierarchy === undefined) { - console.warn( - "Layer ", - layerId, - "is not defined. Try one of ", - Array.from(this.perLayerHierarchy.keys()) - ) - return undefined - } - return TileHierarchyTools.getTiles(requestedHierarchy, bbox) - .filter((featureSource) => featureSource.features?.data !== undefined) - .map((featureSource) => featureSource.features.data.map((fs) => fs.feature)) - } - - public GetTilesPerLayerWithin( - bbox: BBox, - handleTile: (tile: FeatureSourceForLayer & Tiled) => void - ) { - Array.from(this.perLayerHierarchy.values()).forEach((hierarchy) => { - TileHierarchyTools.getTiles(hierarchy, bbox).forEach(handleTile) - }) - } - - private onNewDataLoaded(src: FeatureSource) { - this.newDataLoadedSignal.setData(src) - } - - private freshnessForVisibleLayers(z: number, x: number, y: number): Date { - let oldestDate = undefined - for (const flayer of this.state.filteredLayers.data) { - if (!flayer.isDisplayed.data && !flayer.layerDef.forceLoad) { - continue - } - if (this.state.locationControl.data.zoom < flayer.layerDef.minzoom) { - continue - } - if (flayer.layerDef.maxAgeOfCache === 0) { - return undefined - } - const freshnessCalc = this.freshnesses.get(flayer.layerDef.id) - if (freshnessCalc === undefined) { - console.warn("No freshness tracker found for ", flayer.layerDef.id) - return undefined - } - const freshness = freshnessCalc.freshnessFor(z, x, y) - if (freshness === undefined) { - // SOmething is undefined --> we return undefined as we have to download - return undefined - } - if (oldestDate === undefined || oldestDate > freshness) { - oldestDate = freshness - } - } - return oldestDate - } - - /* - * Gives an UIEventSource containing the tileIndexes of the tiles that should be loaded from OSM - * */ - private getNeededTilesFromOsm(isSufficientlyZoomed: Store): Store { - const self = this - return this.state.currentBounds.map( - (bbox) => { - if (bbox === undefined) { - return [] - } - if (!isSufficientlyZoomed.data) { - return [] - } - const osmSourceZoomLevel = self.osmSourceZoomLevel - const range = bbox.containingTileRange(osmSourceZoomLevel) - const tileIndexes = [] - if (range.total >= 100) { - // Too much tiles! - return undefined - } - Tiles.MapRange(range, (x, y) => { - const i = Tiles.tile_index(osmSourceZoomLevel, x, y) - const oldestDate = self.freshnessForVisibleLayers(osmSourceZoomLevel, x, y) - if (oldestDate !== undefined && oldestDate > this.oldestAllowedDate) { - console.debug( - "Skipping tile", - osmSourceZoomLevel, - x, - y, - "as a decently fresh one is available" - ) - // The cached tiles contain decently fresh data - return undefined - } - tileIndexes.push(i) - }) - return tileIndexes - }, - [isSufficientlyZoomed] - ) - } - - private initOverpassUpdater( - state: { - allElements: ElementStorage - layoutToUse: LayoutConfig - currentBounds: Store - locationControl: Store - readonly overpassUrl: Store - readonly overpassTimeout: Store - readonly overpassMaxZoom: Store - }, - useOsmApi: Store - ): OverpassFeatureSource { - const minzoom = Math.min(...state.layoutToUse.layers.map((layer) => layer.minzoom)) - const overpassIsActive = state.currentBounds.map( - (bbox) => { - if (bbox === undefined) { - console.debug("Disabling overpass source: no bbox") - return false - } - let zoom = state.locationControl.data.zoom - if (zoom < minzoom) { - // We are zoomed out over the zoomlevel of any layer - console.debug("Disabling overpass source: zoom < minzoom") - return false - } - - const range = bbox.containingTileRange(zoom) - if (range.total >= 5000) { - // Let's assume we don't have so much data cached - return true - } - const self = this - const allFreshnesses = Tiles.MapRange(range, (x, y) => - self.freshnessForVisibleLayers(zoom, x, y) - ) - return allFreshnesses.some( - (freshness) => freshness === undefined || freshness < this.oldestAllowedDate - ) - }, - [state.locationControl] - ) - - const self = this - const updater = new OverpassFeatureSource(state, { - padToTiles: state.locationControl.map((l) => Math.min(15, l.zoom + 1)), - relationTracker: this.relationTracker, - isActive: useOsmApi.map((b) => !b && overpassIsActive.data, [overpassIsActive]), - freshnesses: this.freshnesses, - onBboxLoaded: (bbox, date, downloadedLayers, paddedToZoomLevel) => { - Tiles.MapRange(bbox.containingTileRange(paddedToZoomLevel), (x, y) => { - const tileIndex = Tiles.tile_index(paddedToZoomLevel, x, y) - downloadedLayers.forEach((layer) => { - self.freshnesses.get(layer.id).addTileLoad(tileIndex, date) - self.localStorageSavers.get(layer.id)?.MarkVisited(tileIndex, date) - }) - }) - }, - }) - - // Register everything in the state' 'AllElements' - new RegisteringAllFromFeatureSourceActor(updater, state.allElements) - return updater - } - - /** - * Builds upon 'GetAllFeaturesAndMetaWithin', but does stricter BBOX-checking and applies the filters - */ - public getAllVisibleElementsWithmeta( - bbox: BBox - ): { center: [number, number]; element: OsmFeature; layer: LayerConfig }[] { - if (bbox === undefined) { - console.warn("No bbox") - return [] - } - - const layers = Utils.toIdRecord(this.state.layoutToUse.layers) - const elementsWithMeta: { features: OsmFeature[]; layer: string }[] = - this.GetAllFeaturesAndMetaWithin(bbox) - - let elements: { center: [number, number]; element: OsmFeature; layer: LayerConfig }[] = [] - let seenElements = new Set() - for (const elementsWithMetaElement of elementsWithMeta) { - const layer = layers[elementsWithMetaElement.layer] - if (layer.title === undefined) { - continue - } - const filtered = this.state.filteredLayers.data.find((fl) => fl.layerDef == layer) - for (let i = 0; i < elementsWithMetaElement.features.length; i++) { - const element = elementsWithMetaElement.features[i] - if (!filtered.isDisplayed.data) { - continue - } - if (seenElements.has(element.properties.id)) { - continue - } - seenElements.add(element.properties.id) - if (!bbox.overlapsWith(BBox.get(element))) { - continue - } - if (layer?.isShown !== undefined && !layer.isShown.matchesProperties(element)) { - continue - } - const activeFilters: FilterState[] = Array.from( - filtered.appliedFilters.data.values() - ) - if ( - !activeFilters.every( - (filter) => - filter?.currentFilter === undefined || - filter?.currentFilter?.matchesProperties(element.properties) - ) - ) { - continue - } - const center = GeoOperations.centerpointCoordinates(element) - elements.push({ - element, - center, - layer: layers[elementsWithMetaElement.layer], - }) - } - } - - return elements - } - - /** - * Inject a new point - */ - InjectNewPoint(geojson) { - this.newGeometryHandler.features.data.push({ - feature: geojson, - freshness: new Date(), - }) - this.newGeometryHandler.features.ping() - } -} diff --git a/Logic/FeatureSource/FeatureSource.ts b/Logic/FeatureSource/FeatureSource.ts index c5460ff68..3b9798dbb 100644 --- a/Logic/FeatureSource/FeatureSource.ts +++ b/Logic/FeatureSource/FeatureSource.ts @@ -1,26 +1,18 @@ import { Store, UIEventSource } from "../UIEventSource" import FilteredLayer from "../../Models/FilteredLayer" -import { BBox } from "../BBox" -import { Feature, Geometry } from "@turf/turf" -import { OsmFeature } from "../../Models/OsmFeature" +import { Feature } from "geojson" -export default interface FeatureSource { - features: Store<{ feature: OsmFeature; freshness: Date }[]> - /** - * Mainly used for debuging - */ - name: string +export interface FeatureSource { + features: Store } - -export interface Tiled { - tileIndex: number - bbox: BBox +export interface WritableFeatureSource extends FeatureSource { + features: UIEventSource } /** * A feature source which only contains features for the defined layer */ -export interface FeatureSourceForLayer extends FeatureSource { +export interface FeatureSourceForLayer extends FeatureSource { readonly layer: FilteredLayer } @@ -28,5 +20,5 @@ export interface FeatureSourceForLayer extends FeatureSource { * A feature source which is aware of the indexes it contains */ export interface IndexedFeatureSource extends FeatureSource { - readonly containedIds: Store> + readonly featuresById: Store> } diff --git a/Logic/FeatureSource/PerLayerFeatureSourceSplitter.ts b/Logic/FeatureSource/PerLayerFeatureSourceSplitter.ts index 6b6bfd330..4e782b5e1 100644 --- a/Logic/FeatureSource/PerLayerFeatureSourceSplitter.ts +++ b/Logic/FeatureSource/PerLayerFeatureSourceSplitter.ts @@ -1,49 +1,74 @@ -import FeatureSource, { FeatureSourceForLayer, Tiled } from "./FeatureSource" -import { Store } from "../UIEventSource" +import {FeatureSource} from "./FeatureSource" import FilteredLayer from "../../Models/FilteredLayer" import SimpleFeatureSource from "./Sources/SimpleFeatureSource" +import {Feature} from "geojson" +import {UIEventSource} from "../UIEventSource" /** * In some rare cases, some elements are shown on multiple layers (when 'passthrough' is enabled) * If this is the case, multiple objects with a different _matching_layer_id are generated. * In any case, this featureSource marks the objects with _matching_layer_id */ -export default class PerLayerFeatureSourceSplitter { +export default class PerLayerFeatureSourceSplitter { + public readonly perLayer: ReadonlyMap constructor( - layers: Store, - handleLayerData: (source: FeatureSourceForLayer & Tiled) => void, + layers: FilteredLayer[], upstream: FeatureSource, options?: { - tileIndex?: number - handleLeftovers?: (featuresWithoutLayer: any[]) => void + constructStore?: (features: UIEventSource, layer: FilteredLayer) => T + handleLeftovers?: (featuresWithoutLayer: Feature[]) => void } ) { - const knownLayers = new Map() + const knownLayers = new Map() + /** + * Keeps track of the ids that are included per layer. + * Used to know if the downstream feature source needs to be pinged + */ + let layerIndexes: ReadonlySet[] = layers.map((_) => new Set()) + this.perLayer = knownLayers + const layerSources = new Map>() + const constructStore = + options?.constructStore ?? ((store, layer) => new SimpleFeatureSource(layer, store)) + for (const layer of layers) { + const src = new UIEventSource([]) + layerSources.set(layer.layerDef.id, src) + knownLayers.set(layer.layerDef.id, constructStore(src, layer)) + } - function update() { - const features = upstream.features?.data - if (features === undefined) { - return - } - if (layers.data === undefined || layers.data.length === 0) { + upstream.features.addCallbackAndRunD((features) => { + if (layers === undefined) { return } // We try to figure out (for each feature) in which feature store it should be saved. - // Note that this splitter is only run when it is invoked by the overpass feature source, so we can't be sure in which layer it should go - const featuresPerLayer = new Map() - const noLayerFound = [] + const featuresPerLayer = new Map() + /** + * Indexed on layer-position + * Will be true if a new id pops up + */ + const hasChanged: boolean[] = layers.map((_) => false) + const newIndices: Set[] = layers.map((_) => new Set()) + const noLayerFound: Feature[] = [] - for (const layer of layers.data) { + for (const layer of layers) { featuresPerLayer.set(layer.layerDef.id, []) } for (const f of features) { let foundALayer = false - for (const layer of layers.data) { - if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) { + for (let i = 0; i < layers.length; i++) { + const layer = layers[i] + if(!layer.layerDef?.source){ + console.error("PerLayerFeatureSourceSplitter got a layer without a source:", layer.layerDef.id) + continue + } + if (layer.layerDef.source.osmTags.matchesProperties(f.properties)) { + const id = f.properties.id // We have found our matching layer! + const previousIndex = layerIndexes[i] + hasChanged[i] = hasChanged[i] || !previousIndex.has(id) + newIndices[i].add(id) featuresPerLayer.get(layer.layerDef.id).push(f) foundALayer = true if (!layer.layerDef.passAllFeatures) { @@ -59,7 +84,8 @@ export default class PerLayerFeatureSourceSplitter { // At this point, we have our features per layer as a list // We assign them to the correct featureSources - for (const layer of layers.data) { + for (let i = 0; i < layers.length; i++) { + const layer = layers[i] const id = layer.layerDef.id const features = featuresPerLayer.get(id) if (features === undefined) { @@ -67,25 +93,27 @@ export default class PerLayerFeatureSourceSplitter { continue } - let featureSource = knownLayers.get(id) - if (featureSource === undefined) { - // Not yet initialized - now is a good time - featureSource = new SimpleFeatureSource(layer, options?.tileIndex) - featureSource.features.setData(features) - knownLayers.set(id, featureSource) - handleLayerData(featureSource) - } else { - featureSource.features.setData(features) + if (!hasChanged[i] && layerIndexes[i].size === newIndices[i].size) { + // No new id has been added and the sizes are the same (thus: nothing has been removed as well) + // We can safely assume that no changes were made + continue } + + layerSources.get(id).setData(features) } + layerIndexes = newIndices + // AT last, the leftovers are handled if (options?.handleLeftovers !== undefined && noLayerFound.length > 0) { options.handleLeftovers(noLayerFound) } - } + }) + } - layers.addCallback((_) => update()) - upstream.features.addCallbackAndRunD((_) => update()) + public forEach(f: (featureSource: T) => void) { + for (const fs of this.perLayer.values()) { + f(fs) + } } } diff --git a/Logic/FeatureSource/Sources/ChangeGeometryApplicator.ts b/Logic/FeatureSource/Sources/ChangeGeometryApplicator.ts index 0bac2ab6d..5fd93fcd7 100644 --- a/Logic/FeatureSource/Sources/ChangeGeometryApplicator.ts +++ b/Logic/FeatureSource/Sources/ChangeGeometryApplicator.ts @@ -3,25 +3,21 @@ */ import { Changes } from "../../Osm/Changes" import { UIEventSource } from "../../UIEventSource" -import { FeatureSourceForLayer, IndexedFeatureSource } from "../FeatureSource" -import FilteredLayer from "../../../Models/FilteredLayer" +import { FeatureSource, IndexedFeatureSource } from "../FeatureSource" import { ChangeDescription, ChangeDescriptionTools } from "../../Osm/Actions/ChangeDescription" +import { Feature } from "geojson" +import {Utils} from "../../../Utils"; -export default class ChangeGeometryApplicator implements FeatureSourceForLayer { - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = - new UIEventSource<{ feature: any; freshness: Date }[]>([]) - public readonly name: string - public readonly layer: FilteredLayer +export default class ChangeGeometryApplicator implements FeatureSource { + public readonly features: UIEventSource = new UIEventSource([]) private readonly source: IndexedFeatureSource private readonly changes: Changes - constructor(source: IndexedFeatureSource & FeatureSourceForLayer, changes: Changes) { + constructor(source: IndexedFeatureSource, changes: Changes) { this.source = source this.changes = changes - this.layer = source.layer - this.name = "ChangesApplied(" + source.name + ")" - this.features = new UIEventSource<{ feature: any; freshness: Date }[]>(undefined) + this.features = new UIEventSource(undefined) const self = this source.features.addCallbackAndRunD((_) => self.update()) @@ -31,10 +27,10 @@ export default class ChangeGeometryApplicator implements FeatureSourceForLayer { private update() { const upstreamFeatures = this.source.features.data - const upstreamIds = this.source.containedIds.data + const upstreamIds = this.source.featuresById.data const changesToApply = this.changes.allChanges.data?.filter( (ch) => - // Does upsteram have this element? If not, we skip + // Does upstream have this element? If not, we skip upstreamIds.has(ch.type + "/" + ch.id) && // Are any (geometry) changes defined? ch.changes !== undefined && @@ -58,11 +54,11 @@ export default class ChangeGeometryApplicator implements FeatureSourceForLayer { changesPerId.set(key, [ch]) } } - const newFeatures: { feature: any; freshness: Date }[] = [] + const newFeatures: Feature[] = [] for (const feature of upstreamFeatures) { - const changesForFeature = changesPerId.get(feature.feature.properties.id) + const changesForFeature = changesPerId.get(feature.properties.id) if (changesForFeature === undefined) { - // No changes for this element + // No changes for this element - simply pass it along to downstream newFeatures.push(feature) continue } @@ -73,7 +69,12 @@ export default class ChangeGeometryApplicator implements FeatureSourceForLayer { } // We only apply the last change as that one'll have the latest geometry const change = changesForFeature[changesForFeature.length - 1] - copy.feature.geometry = ChangeDescriptionTools.getGeojsonGeometry(change) + copy.geometry = ChangeDescriptionTools.getGeojsonGeometry(change) + if(Utils.SameObject(copy.geometry, feature.geometry)){ + // No actual changes: pass along the original + newFeatures.push(feature) + continue + } console.log( "Applying a geometry change onto:", feature, diff --git a/Logic/FeatureSource/Sources/ClippedFeatureSource.ts b/Logic/FeatureSource/Sources/ClippedFeatureSource.ts new file mode 100644 index 000000000..a07b17895 --- /dev/null +++ b/Logic/FeatureSource/Sources/ClippedFeatureSource.ts @@ -0,0 +1,17 @@ +import { FeatureSource } from "../FeatureSource" +import { Feature, Polygon } from "geojson" +import StaticFeatureSource from "./StaticFeatureSource" +import { GeoOperations } from "../../GeoOperations" + +/** + * Returns a clipped version of the original geojson. Ways which partially intersect the given feature will be split up + */ +export default class ClippedFeatureSource extends StaticFeatureSource { + constructor(features: FeatureSource, clipTo: Feature) { + super( + features.features.mapD((features) => { + return [].concat(features.map((feature) => GeoOperations.clipWith(feature, clipTo))) + }) + ) + } +} diff --git a/Logic/FeatureSource/Sources/FeatureSourceMerger.ts b/Logic/FeatureSource/Sources/FeatureSourceMerger.ts index 248a9d9d9..8b0292b7d 100644 --- a/Logic/FeatureSource/Sources/FeatureSourceMerger.ts +++ b/Logic/FeatureSource/Sources/FeatureSourceMerger.ts @@ -1,84 +1,60 @@ -import { UIEventSource } from "../../UIEventSource" -import FeatureSource, { FeatureSourceForLayer, IndexedFeatureSource, Tiled } from "../FeatureSource" -import FilteredLayer from "../../../Models/FilteredLayer" -import { Tiles } from "../../../Models/TileRange" -import { BBox } from "../../BBox" +import { Store, UIEventSource } from "../../UIEventSource" +import { FeatureSource, IndexedFeatureSource } from "../FeatureSource" +import { Feature } from "geojson" +import { Utils } from "../../../Utils" -export default class FeatureSourceMerger - implements FeatureSourceForLayer, Tiled, IndexedFeatureSource -{ - public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource< - { feature: any; freshness: Date }[] - >([]) - public readonly name - public readonly layer: FilteredLayer - public readonly tileIndex: number - public readonly bbox: BBox - public readonly containedIds: UIEventSource> = new UIEventSource>( - new Set() - ) - private readonly _sources: UIEventSource +/** + * + */ +export default class FeatureSourceMerger implements IndexedFeatureSource { + public features: UIEventSource = new UIEventSource([]) + public readonly featuresById: Store> + private readonly _featuresById: UIEventSource> + private readonly _sources: FeatureSource[] = [] /** - * Merges features from different featureSources for a single layer - * Uses the freshest feature available in the case multiple sources offer data with the same identifier + * Merges features from different featureSources. + * In case that multiple features have the same id, the latest `_version_number` will be used. Otherwise, we will take the last one */ - constructor( - layer: FilteredLayer, - tileIndex: number, - bbox: BBox, - sources: UIEventSource - ) { - this.tileIndex = tileIndex - this.bbox = bbox - this._sources = sources - this.layer = layer - this.name = - "FeatureSourceMerger(" + - layer.layerDef.id + - ", " + - Tiles.tile_from_index(tileIndex).join(",") + - ")" + constructor(...sources: FeatureSource[]) { + this._featuresById = new UIEventSource>(new Map()) + this.featuresById = this._featuresById const self = this + sources = Utils.NoNull(sources) + for (let source of sources) { + source.features.addCallback(() => { + self.addData(sources.map((s) => s.features.data)) + }) + } + this.addData(sources.map((s) => s.features.data)) + this._sources = sources + } - const handledSources = new Set() - - sources.addCallbackAndRunD((sources) => { - let newSourceRegistered = false - for (let i = 0; i < sources.length; i++) { - let source = sources[i] - if (handledSources.has(source)) { - continue - } - handledSources.add(source) - newSourceRegistered = true - source.features.addCallback(() => { - self.Update() - }) - if (newSourceRegistered) { - self.Update() - } - } + public addSource(source: FeatureSource) { + if(!source){ + return + } + this._sources.push(source) + source.features.addCallbackAndRun(() => { + this.addData(this._sources.map((s) => s.features.data)) }) } - private Update() { + protected addData(featuress: Feature[][]) { + featuress = Utils.NoNull(featuress) let somethingChanged = false - const all: Map = new Map< - string, - { feature: any; freshness: Date } - >() + const all: Map = new Map() + const unseen = new Set() // We seed the dictionary with the previously loaded features const oldValues = this.features.data ?? [] for (const oldValue of oldValues) { - all.set(oldValue.feature.id, oldValue) + all.set(oldValue.properties.id, oldValue) + unseen.add(oldValue.properties.id) } - for (const source of this._sources.data) { - if (source?.features?.data === undefined) { - continue - } - for (const f of source.features.data) { - const id = f.feature.properties.id + for (const features of featuress) { + for (const f of features) { + const id = f.properties.id + unseen.delete(id) if (!all.has(id)) { // This is a new feature somethingChanged = true @@ -89,24 +65,27 @@ export default class FeatureSourceMerger // This value has been seen already, either in a previous run or by a previous datasource // Let's figure out if something changed const oldV = all.get(id) - if (oldV.freshness < f.freshness) { - // Jup, this feature is fresher - all.set(id, f) - somethingChanged = true + if (oldV == f) { + continue } + all.set(id, f) + somethingChanged = true } } + somethingChanged ||= unseen.size > 0 + unseen.forEach((id) => all.delete(id)) + if (!somethingChanged) { // We don't bother triggering an update return } const newList = [] - all.forEach((value, _) => { + all.forEach((value, key) => { newList.push(value) }) - this.containedIds.setData(new Set(all.keys())) this.features.setData(newList) + this._featuresById.setData(all) } } diff --git a/Logic/FeatureSource/Sources/FilteringFeatureSource.ts b/Logic/FeatureSource/Sources/FilteringFeatureSource.ts index 9bb354625..9a55a51d1 100644 --- a/Logic/FeatureSource/Sources/FilteringFeatureSource.ts +++ b/Logic/FeatureSource/Sources/FilteringFeatureSource.ts @@ -1,57 +1,41 @@ import { Store, UIEventSource } from "../../UIEventSource" -import FilteredLayer, { FilterState } from "../../../Models/FilteredLayer" -import { FeatureSourceForLayer, Tiled } from "../FeatureSource" -import { BBox } from "../../BBox" -import { ElementStorage } from "../../ElementStorage" -import { TagsFilter } from "../../Tags/TagsFilter" -import { OsmFeature } from "../../../Models/OsmFeature" +import FilteredLayer from "../../../Models/FilteredLayer" +import { FeatureSource } from "../FeatureSource" +import { Feature } from "geojson" +import { GlobalFilter } from "../../../Models/GlobalFilter" -export default class FilteringFeatureSource implements FeatureSourceForLayer, Tiled { - public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource< - { feature: any; freshness: Date }[] - >([]) - public readonly name - public readonly layer: FilteredLayer - public readonly tileIndex: number - public readonly bbox: BBox - private readonly upstream: FeatureSourceForLayer - private readonly state: { - locationControl: Store<{ zoom: number }> - selectedElement: Store - globalFilters?: Store<{ filter: FilterState }[]> - allElements: ElementStorage - } - private readonly _alreadyRegistered = new Set>() +export default class FilteringFeatureSource implements FeatureSource { + public features: UIEventSource = new UIEventSource([]) + private readonly upstream: FeatureSource + private readonly _fetchStore?: (id: string) => Store> + private readonly _globalFilters?: Store + private readonly _alreadyRegistered = new Set>() private readonly _is_dirty = new UIEventSource(false) + private readonly _layer: FilteredLayer private previousFeatureSet: Set = undefined constructor( - state: { - locationControl: Store<{ zoom: number }> - selectedElement: Store - allElements: ElementStorage - globalFilters?: Store<{ filter: FilterState }[]> - }, - tileIndex, - upstream: FeatureSourceForLayer, - metataggingUpdated?: UIEventSource + layer: FilteredLayer, + upstream: FeatureSource, + fetchStore?: (id: string) => Store>, + globalFilters?: Store, + metataggingUpdated?: Store ) { - this.name = "FilteringFeatureSource(" + upstream.name + ")" - this.tileIndex = tileIndex - this.bbox = tileIndex === undefined ? undefined : BBox.fromTileIndex(tileIndex) this.upstream = upstream - this.state = state + this._fetchStore = fetchStore + this._layer = layer + this._globalFilters = globalFilters - this.layer = upstream.layer - const layer = upstream.layer const self = this upstream.features.addCallback(() => { self.update() }) - layer.appliedFilters.addCallback((_) => { - self.update() - }) + layer.appliedFilters.forEach((value) => + value.addCallback((_) => { + self.update() + }) + ) this._is_dirty.stabilized(1000).addCallbackAndRunD((dirty) => { if (dirty) { @@ -63,7 +47,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti self._is_dirty.setData(true) }) - state.globalFilters?.addCallback((_) => { + globalFilters?.addCallback((_) => { self.update() }) @@ -72,47 +56,18 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti private update() { const self = this - const layer = this.upstream.layer - const features: { feature: OsmFeature; freshness: Date }[] = - this.upstream.features.data ?? [] + const layer = this._layer + const features: Feature[] = this.upstream.features.data ?? [] const includedFeatureIds = new Set() - const globalFilters = self.state.globalFilters?.data?.map((f) => f.filter) + const globalFilters = self._globalFilters?.data?.map((f) => f) const newFeatures = (features ?? []).filter((f) => { - self.registerCallback(f.feature) + self.registerCallback(f.properties.id) - const isShown: TagsFilter = layer.layerDef.isShown - const tags = f.feature.properties - if (isShown !== undefined && !isShown.matchesProperties(tags)) { - return false - } - if (tags._deleted === "yes") { + if (!layer.isShown(f.properties, globalFilters)) { return false } - const tagsFilter = Array.from(layer.appliedFilters?.data?.values() ?? []) - for (const filter of tagsFilter) { - const neededTags: TagsFilter = filter?.currentFilter - if ( - neededTags !== undefined && - !neededTags.matchesProperties(f.feature.properties) - ) { - // Hidden by the filter on the layer itself - we want to hide it no matter what - return false - } - } - - for (const filter of globalFilters ?? []) { - const neededTags: TagsFilter = filter?.currentFilter - if ( - neededTags !== undefined && - !neededTags.matchesProperties(f.feature.properties) - ) { - // Hidden by the filter on the layer itself - we want to hide it no matter what - return false - } - } - - includedFeatureIds.add(f.feature.properties.id) + includedFeatureIds.add(f.properties.id) return true }) @@ -132,12 +87,15 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti } } - // Something new has been found! + // Something new has been found (or something was deleted)! this.features.setData(newFeatures) } - private registerCallback(feature: any) { - const src = this.state?.allElements?.addOrGetElement(feature) + private registerCallback(featureId: string) { + if (this._fetchStore === undefined) { + return + } + const src = this._fetchStore(featureId) if (src == undefined) { return } @@ -147,7 +105,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti this._alreadyRegistered.add(src) const self = this - // Add a callback as a changed tag migh change the filter + // Add a callback as a changed tag might change the filter src.addCallbackAndRunD((_) => { self._is_dirty.setData(true) }) diff --git a/Logic/FeatureSource/Sources/GeoJsonSource.ts b/Logic/FeatureSource/Sources/GeoJsonSource.ts index 5c0ecb9e9..4a244683b 100644 --- a/Logic/FeatureSource/Sources/GeoJsonSource.ts +++ b/Logic/FeatureSource/Sources/GeoJsonSource.ts @@ -1,58 +1,53 @@ /** * Fetches a geojson file somewhere and passes it along */ -import { UIEventSource } from "../../UIEventSource" -import FilteredLayer from "../../../Models/FilteredLayer" -import { Utils } from "../../../Utils" -import { FeatureSourceForLayer, Tiled } from "../FeatureSource" -import { Tiles } from "../../../Models/TileRange" -import { BBox } from "../../BBox" -import { GeoOperations } from "../../GeoOperations" +import {Store, UIEventSource} from "../../UIEventSource" +import {Utils} from "../../../Utils" +import {FeatureSource} from "../FeatureSource" +import {BBox} from "../../BBox" +import {GeoOperations} from "../../GeoOperations" +import {Feature} from "geojson" +import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" +import {Tiles} from "../../../Models/TileRange" -export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> - public readonly state = new UIEventSource(undefined) - public readonly name - public readonly isOsmCache: boolean - public readonly layer: FilteredLayer - public readonly tileIndex - public readonly bbox +export default class GeoJsonSource implements FeatureSource { + public readonly features: Store private readonly seenids: Set private readonly idKey?: string public constructor( - flayer: FilteredLayer, - zxy?: [number, number, number] | BBox, + layer: LayerConfig, options?: { + zxy?: number | [number, number, number] | BBox featureIdBlacklist?: Set + isActive?: Store } ) { - if (flayer.layerDef.source.geojsonZoomLevel !== undefined && zxy === undefined) { + if (layer.source.geojsonZoomLevel !== undefined && options?.zxy === undefined) { throw "Dynamic layers are not supported. Use 'DynamicGeoJsonTileSource instead" } - this.layer = flayer - this.idKey = flayer.layerDef.source.idKey + this.idKey = layer.source.idKey this.seenids = options?.featureIdBlacklist ?? new Set() - let url = flayer.layerDef.source.geojsonSource.replace("{layer}", flayer.layerDef.id) + let url = layer.source.geojsonSource.replace("{layer}", layer.id) + let zxy = options?.zxy if (zxy !== undefined) { let tile_bbox: BBox + if (typeof zxy === "number") { + zxy = Tiles.tile_from_index(zxy) + } if (zxy instanceof BBox) { tile_bbox = zxy } else { const [z, x, y] = zxy tile_bbox = BBox.fromTile(z, x, y) - - this.tileIndex = Tiles.tile_index(z, x, y) - this.bbox = BBox.fromTile(z, x, y) url = url .replace("{z}", "" + z) .replace("{x}", "" + x) .replace("{y}", "" + y) } - let bounds: { minLat: number; maxLat: number; minLon: number; maxLon: number } = - tile_bbox - if (this.layer.layerDef.source.mercatorCrs) { + let bounds: Record<"minLat" | "maxLat" | "minLon" | "maxLon", number> = tile_bbox + if (layer.source.mercatorCrs) { bounds = tile_bbox.toMercator() } @@ -61,103 +56,95 @@ export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { .replace("{y_max}", "" + bounds.maxLat) .replace("{x_min}", "" + bounds.minLon) .replace("{x_max}", "" + bounds.maxLon) - } else { - this.tileIndex = Tiles.tile_index(0, 0, 0) - this.bbox = BBox.global } - this.name = "GeoJsonSource of " + url - - this.isOsmCache = flayer.layerDef.source.isOsmCacheLayer - this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([]) - this.LoadJSONFrom(url) + const eventsource = new UIEventSource([]) + if (options?.isActive !== undefined) { + options.isActive.addCallbackAndRunD(async (active) => { + if (!active) { + return + } + this.LoadJSONFrom(url, eventsource, layer) + .then((fs) => console.debug("Loaded",fs.length, "features from", url)) + .catch((err) => console.warn("Could not load ", url, "due to", err)) + return true // data is loaded, we can safely unregister + }) + } else { + this.LoadJSONFrom(url, eventsource, layer) + .then((fs) => console.debug("Loaded",fs.length, "features from", url)) + .catch((err) => console.warn("Could not load ", url, "due to", err)) + } + this.features = eventsource } - private LoadJSONFrom(url: string) { - const eventSource = this.features + /** + * Init the download, write into the specified event source for the given layer. + * Note this method caches the requested geojson for five minutes + */ + private async LoadJSONFrom( + url: string, + eventSource: UIEventSource, + layer: LayerConfig, + options?: { + maxCacheAgeSec?: number | 300 + } + ): Promise { const self = this - Utils.downloadJsonCached(url, 60 * 60) - .then((json) => { - self.state.setData("loaded") - // TODO: move somewhere else, just for testing - // Check for maproulette data - if (url.startsWith("https://maproulette.org/api/v2/tasks/box/")) { - console.log("MapRoulette data detected") - const data = json - let maprouletteFeatures: any[] = [] - data.forEach((element) => { - maprouletteFeatures.push({ - type: "Feature", - geometry: { - type: "Point", - coordinates: [element.point.lng, element.point.lat], - }, - properties: { - // Map all properties to the feature - ...element, - }, - }) - }) - json.features = maprouletteFeatures + let json = await Utils.downloadJsonCached(url, (options?.maxCacheAgeSec ?? 300) * 1000) + + if (json.features === undefined || json.features === null) { + json.features = [] + } + + if (layer.source.mercatorCrs) { + json = GeoOperations.GeoJsonToWGS84(json) + } + + const time = new Date() + const newFeatures: Feature[] = [] + let i = 0 + let skipped = 0 + for (const feature of json.features) { + if(feature.geometry.type === "Point"){ + // See https://github.com/maproulette/maproulette-backend/issues/242 + feature.geometry.coordinates = feature.geometry.coordinates.map(Number) + } + const props = feature.properties + for (const key in props) { + if (props[key] === null) { + delete props[key] } - if (json.features === undefined || json.features === null) { - return + if (typeof props[key] !== "string") { + // Make sure all the values are string, it crashes stuff otherwise + props[key] = JSON.stringify(props[key]) } + } - if (self.layer.layerDef.source.mercatorCrs) { - json = GeoOperations.GeoJsonToWGS84(json) - } + if (self.idKey !== undefined) { + props.id = props[self.idKey] + } - const time = new Date() - const newFeatures: { feature: any; freshness: Date }[] = [] - let i = 0 - let skipped = 0 - for (const feature of json.features) { - const props = feature.properties - for (const key in props) { - if (props[key] === null) { - delete props[key] - } + if (props.id === undefined) { + props.id = url + "/" + i + feature.id = url + "/" + i + i++ + } + if (self.seenids.has(props.id)) { + skipped++ + continue + } + self.seenids.add(props.id) - if (typeof props[key] !== "string") { - // Make sure all the values are string, it crashes stuff otherwise - props[key] = JSON.stringify(props[key]) - } - } + let freshness: Date = time + if (feature.properties["_last_edit:timestamp"] !== undefined) { + freshness = new Date(props["_last_edit:timestamp"]) + } - if (self.idKey !== undefined) { - props.id = props[self.idKey] - } + newFeatures.push(feature) + } - if (props.id === undefined) { - props.id = url + "/" + i - feature.id = url + "/" + i - i++ - } - if (self.seenids.has(props.id)) { - skipped++ - continue - } - self.seenids.add(props.id) - - let freshness: Date = time - if (feature.properties["_last_edit:timestamp"] !== undefined) { - freshness = new Date(props["_last_edit:timestamp"]) - } - - newFeatures.push({ feature: feature, freshness: freshness }) - } - - if (newFeatures.length == 0) { - return - } - - eventSource.setData(eventSource.data.concat(newFeatures)) - }) - .catch((msg) => { - console.debug("Could not load geojson layer", url, "due to", msg) - self.state.setData({ error: msg }) - }) + eventSource.setData(newFeatures) + return newFeatures } } diff --git a/Logic/FeatureSource/Sources/LastClickFeatureSource.ts b/Logic/FeatureSource/Sources/LastClickFeatureSource.ts new file mode 100644 index 000000000..796ba3722 --- /dev/null +++ b/Logic/FeatureSource/Sources/LastClickFeatureSource.ts @@ -0,0 +1,60 @@ +import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig" +import { WritableFeatureSource } from "../FeatureSource" +import { ImmutableStore, Store, UIEventSource } from "../../UIEventSource" +import { Feature, Point } from "geojson" +import { TagUtils } from "../../Tags/TagUtils" +import BaseUIElement from "../../../UI/BaseUIElement" +import { Utils } from "../../../Utils" + +/** + * Highly specialized feature source. + * Based on a lon/lat UIEVentSource, will generate the corresponding feature with the correct properties + */ +export class LastClickFeatureSource implements WritableFeatureSource { + public readonly features: UIEventSource = new UIEventSource([]) + + /** + * Must be public: passed as tags into the selected view + */ + public properties: Record + + constructor(location: Store<{ lon: number; lat: number }>, layout: LayoutConfig) { + const allPresets: BaseUIElement[] = [] + for (const layer of layout.layers) + for (let i = 0; i < (layer.presets ?? []).length; i++) { + const preset = layer.presets[i] + const tags = new ImmutableStore(TagUtils.KVtoProperties(preset.tags)) + const { html } = layer.mapRendering[0].RenderIcon(tags, false, { + noSize: true, + includeBadges: false, + }) + allPresets.push(html) + } + + const renderings = Utils.Dedup( + allPresets.map((uiElem) => Utils.runningFromConsole ? "" : uiElem.ConstructElement().innerHTML) + ) + + const properties = { + lastclick: "yes", + id: "last_click", + has_note_layer: layout.layers.some((l) => l.id === "note") ? "yes" : "no", + has_presets: layout.layers.some((l) => l.presets?.length > 0) ? "yes" : "no", + renderings: renderings.join(""), + number_of_presets: "" + renderings.length, + first_preset: renderings[0], + } + this.properties = properties + location.addCallbackAndRunD(({ lon, lat }) => { + const point = >{ + type: "Feature", + properties, + geometry: { + type: "Point", + coordinates: [lon, lat], + }, + } + this.features.setData([point]) + }) + } +} diff --git a/Logic/FeatureSource/Sources/LayoutSource.ts b/Logic/FeatureSource/Sources/LayoutSource.ts new file mode 100644 index 000000000..de1c25c51 --- /dev/null +++ b/Logic/FeatureSource/Sources/LayoutSource.ts @@ -0,0 +1,171 @@ +import GeoJsonSource from "./GeoJsonSource" +import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" +import {FeatureSource} from "../FeatureSource" +import {Or} from "../../Tags/Or" +import FeatureSwitchState from "../../State/FeatureSwitchState" +import OverpassFeatureSource from "./OverpassFeatureSource" +import {Store, UIEventSource} from "../../UIEventSource" +import OsmFeatureSource from "./OsmFeatureSource" +import FeatureSourceMerger from "./FeatureSourceMerger" +import DynamicGeoJsonTileSource from "../TiledFeatureSource/DynamicGeoJsonTileSource" +import {BBox} from "../../BBox" +import LocalStorageFeatureSource from "../TiledFeatureSource/LocalStorageFeatureSource" +import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource"; + +/** + * This source will fetch the needed data from various sources for the given layout. + * + * Note that special layers (with `source=null` will be ignored) + */ +export default class LayoutSource extends FeatureSourceMerger { + private readonly _isLoading: UIEventSource = new UIEventSource(false) + /** + * Indicates if a data source is loading something + */ + public readonly isLoading: Store = this._isLoading + constructor( + layers: LayerConfig[], + featureSwitches: FeatureSwitchState, + mapProperties: { bounds: Store; zoom: Store }, + backend: string, + isDisplayed: (id: string) => Store, + fullNodeDatabaseSource?: FullNodeDatabaseSource + ) { + const { bounds, zoom } = mapProperties + // remove all 'special' layers + layers = layers.filter((layer) => layer.source !== null && layer.source !== undefined) + + const geojsonlayers = layers.filter((layer) => layer.source.geojsonSource !== undefined) + const osmLayers = layers.filter((layer) => layer.source.geojsonSource === undefined) + const fromCache = osmLayers.map( + (l) => + new LocalStorageFeatureSource(backend, l.id, 15, mapProperties, { + isActive: isDisplayed(l.id), + maxAge: l.maxAgeOfCache + }) + ) + + const overpassSource = LayoutSource.setupOverpass( + backend, + osmLayers, + bounds, + zoom, + featureSwitches + ) + + const osmApiSource = LayoutSource.setupOsmApiSource( + osmLayers, + bounds, + zoom, + backend, + featureSwitches, + fullNodeDatabaseSource + ) + const geojsonSources: FeatureSource[] = geojsonlayers.map((l) => + LayoutSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id)) + ) + + super(overpassSource, osmApiSource, ...geojsonSources, ...fromCache) + + const self = this + function setIsLoading() { + const loading = overpassSource?.runningQuery?.data && osmApiSource?.isRunning?.data + self._isLoading.setData(loading) + } + + overpassSource?.runningQuery?.addCallbackAndRun((_) => setIsLoading()) + osmApiSource?.isRunning?.addCallbackAndRun((_) => setIsLoading()) + } + + private static setupGeojsonSource( + layer: LayerConfig, + mapProperties: { zoom: Store; bounds: Store }, + isActive?: Store + ): FeatureSource { + const source = layer.source + isActive = mapProperties.zoom.map( + (z) => (isActive?.data ?? true) && z >= layer.minzoom, + [isActive] + ) + if (source.geojsonZoomLevel === undefined) { + // This is a 'load everything at once' geojson layer + return new GeoJsonSource(layer, { isActive }) + } else { + return new DynamicGeoJsonTileSource(layer, mapProperties, { isActive }) + } + } + + private static setupOsmApiSource( + osmLayers: LayerConfig[], + bounds: Store, + zoom: Store, + backend: string, + featureSwitches: FeatureSwitchState, + fullNodeDatabase: FullNodeDatabaseSource + ): OsmFeatureSource | undefined { + if (osmLayers.length == 0) { + return undefined + } + const minzoom = Math.min(...osmLayers.map((layer) => layer.minzoom)) + const isActive = zoom.mapD((z) => { + if (z < minzoom) { + // We are zoomed out over the zoomlevel of any layer + console.debug("Disabling overpass source: zoom < minzoom") + return false + } + + // Overpass should handle this if zoomed out a bit + return z > featureSwitches.overpassMaxZoom.data + }) + const allowedFeatures = new Or(osmLayers.map((l) => l.source.osmTags)).optimize() + if (typeof allowedFeatures === "boolean") { + throw "Invalid filter to init OsmFeatureSource: it optimizes away to " + allowedFeatures + } + return new OsmFeatureSource({ + allowedFeatures, + bounds, + backend, + isActive, + patchRelations: true, + fullNodeDatabase + }) + } + + private static setupOverpass( + backend: string, + osmLayers: LayerConfig[], + bounds: Store, + zoom: Store, + featureSwitches: FeatureSwitchState + ): OverpassFeatureSource | undefined { + if (osmLayers.length == 0) { + return undefined + } + const minzoom = Math.min(...osmLayers.map((layer) => layer.minzoom)) + const isActive = zoom.mapD((z) => { + if (z < minzoom) { + // We are zoomed out over the zoomlevel of any layer + console.debug("Disabling overpass source: zoom < minzoom") + return false + } + + return z <= featureSwitches.overpassMaxZoom.data + }) + + return new OverpassFeatureSource( + { + zoom, + bounds, + layers: osmLayers, + widenFactor: featureSwitches.layoutToUse.widenFactor, + overpassUrl: featureSwitches.overpassUrl, + overpassTimeout: featureSwitches.overpassTimeout, + overpassMaxZoom: featureSwitches.overpassMaxZoom, + }, + { + padToTiles: zoom.map((zoom) => Math.min(15, zoom + 1)), + isActive, + } + ) + } +} diff --git a/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts b/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts index 6829a25a4..a9b884167 100644 --- a/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts +++ b/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts @@ -1,12 +1,13 @@ import { Changes } from "../../Osm/Changes" -import { OsmNode, OsmObject, OsmRelation, OsmWay } from "../../Osm/OsmObject" -import FeatureSource from "../FeatureSource" +import { OsmNode, OsmRelation, OsmWay } from "../../Osm/OsmObject" +import { IndexedFeatureSource, WritableFeatureSource } from "../FeatureSource" import { UIEventSource } from "../../UIEventSource" import { ChangeDescription } from "../../Osm/Actions/ChangeDescription" -import { ElementStorage } from "../../ElementStorage" import { OsmId, OsmTags } from "../../../Models/OsmFeature" +import { Feature } from "geojson" +import OsmObjectDownloader from "../../Osm/OsmObjectDownloader" -export class NewGeometryFromChangesFeatureSource implements FeatureSource { +export class NewGeometryFromChangesFeatureSource implements WritableFeatureSource { // This class name truly puts the 'Java' into 'Javascript' /** @@ -15,29 +16,23 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { * These elements are probably created by the 'SimpleAddUi' which generates a new point, but the import functionality might create a line or polygon too. * Other sources of new points are e.g. imports from nodes */ - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = - new UIEventSource<{ feature: any; freshness: Date }[]>([]) - public readonly name: string = "newFeatures" + public readonly features: UIEventSource = new UIEventSource([]) - constructor(changes: Changes, allElementStorage: ElementStorage, backendUrl: string) { + constructor(changes: Changes, allElementStorage: IndexedFeatureSource, backendUrl: string) { const seenChanges = new Set() const features = this.features.data const self = this - - changes.pendingChanges.stabilized(100).addCallbackAndRunD((changes) => { + const backend = changes.backend + changes.pendingChanges.addCallbackAndRunD((changes) => { if (changes.length === 0) { return } - const now = new Date() let somethingChanged = false function add(feature) { feature.id = feature.properties.id - features.push({ - feature: feature, - freshness: now, - }) + features.push(feature) somethingChanged = true } @@ -53,33 +48,36 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { continue } + console.log("Handling pending change") if (change.id > 0) { // This is an already existing object // In _most_ of the cases, this means that this _isn't_ a new object // However, when a point is snapped to an already existing point, we have to create a representation for this point! // For this, we introspect the change - if (allElementStorage.has(change.type + "/" + change.id)) { + if (allElementStorage.featuresById.data.has(change.type + "/" + change.id)) { // The current point already exists, we don't have to do anything here continue } console.debug("Detected a reused point") // The 'allElementsStore' does _not_ have this point yet, so we have to create it - OsmObject.DownloadObjectAsync(change.type + "/" + change.id).then((feat) => { - console.log("Got the reused point:", feat) - for (const kv of change.tags) { - feat.tags[kv.k] = kv.v - } - const geojson = feat.asGeoJson() - allElementStorage.addOrGetElement(geojson) - self.features.data.push({ feature: geojson, freshness: new Date() }) - self.features.ping() - }) + new OsmObjectDownloader(backend) + .DownloadObjectAsync(change.type + "/" + change.id) + .then((feat) => { + console.log("Got the reused point:", feat) + if (feat === "deleted") { + throw "Panic: snapping to a point, but this point has been deleted in the meantime" + } + for (const kv of change.tags) { + feat.tags[kv.k] = kv.v + } + const geojson = feat.asGeoJson() + self.features.data.push(geojson) + self.features.ping() + }) continue - } else if (change.id < 0 && change.changes === undefined) { - // The geometry is not described - not a new point - if (change.id < 0) { - console.error("WARNING: got a new point without geometry!") - } + } else if (change.changes === undefined) { + // The geometry is not described - not a new point or geometry change, but probably a tagchange to a newly created point + // Not something that should be handled here continue } diff --git a/Logic/FeatureSource/Sources/OsmFeatureSource.ts b/Logic/FeatureSource/Sources/OsmFeatureSource.ts new file mode 100644 index 000000000..8ae25dc80 --- /dev/null +++ b/Logic/FeatureSource/Sources/OsmFeatureSource.ts @@ -0,0 +1,212 @@ +import { Utils } from "../../../Utils" +import OsmToGeoJson from "osmtogeojson" +import { ImmutableStore, Store, UIEventSource } from "../../UIEventSource" +import { Tiles } from "../../../Models/TileRange" +import { BBox } from "../../BBox" +import { TagsFilter } from "../../Tags/TagsFilter" +import { Feature } from "geojson" +import FeatureSourceMerger from "../Sources/FeatureSourceMerger" +import OsmObjectDownloader from "../../Osm/OsmObjectDownloader" +import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource"; + +/** + * If a tile is needed (requested via the UIEventSource in the constructor), will download the appropriate tile and pass it via 'handleTile' + */ +export default class OsmFeatureSource extends FeatureSourceMerger { + private readonly _bounds: Store + private readonly isActive: Store + private readonly _backend: string + private readonly allowedTags: TagsFilter + private options: { + bounds: Store + readonly allowedFeatures: TagsFilter + backend?: "https://openstreetmap.org/" | string + /** + * If given: this featureSwitch will not update if the store contains 'false' + */ + isActive?: Store, + patchRelations?: true | boolean, + fullNodeDatabase?: FullNodeDatabaseSource + }; + + public readonly isRunning: UIEventSource = new UIEventSource(false) + + private readonly _downloadedTiles: Set = new Set() + private readonly _downloadedData: Feature[][] = [] + private readonly _patchRelations: boolean; + /** + * Downloads data directly from the OSM-api within the given bounds. + * All features which match the TagsFilter 'allowedFeatures' are kept and converted into geojson + */ + constructor(options: { + bounds: Store + readonly allowedFeatures: TagsFilter + backend?: "https://openstreetmap.org/" | string + /** + * If given: this featureSwitch will not update if the store contains 'false' + */ + isActive?: Store, + patchRelations?: true | boolean, + fullNodeDatabase?: FullNodeDatabaseSource + }) { + super() + this.options = options; + this._bounds = options.bounds + this.allowedTags = options.allowedFeatures + this.isActive = options.isActive ?? new ImmutableStore(true) + this._backend = options.backend ?? "https://www.openstreetmap.org" + this._bounds.addCallbackAndRunD((bbox) => this.loadData(bbox)) + this._patchRelations = options?.patchRelations ?? true + } + + private async loadData(bbox: BBox) { + if (this.isActive?.data === false) { + console.log("OsmFeatureSource: not triggering: inactive") + return + } + + const z = 15 + const neededTiles = Tiles.tileRangeFrom(bbox, z) + + if (neededTiles.total == 0) { + return + } + + this.isRunning.setData(true) + try { + const tileNumbers = Tiles.MapRange(neededTiles, (x, y) => { + return Tiles.tile_index(z, x, y) + }) + await Promise.all(tileNumbers.map((i) => this.LoadTile(...Tiles.tile_from_index(i)))) + } catch (e) { + console.error(e) + } finally { + this.isRunning.setData(false) + } + } + + private registerFeatures(features: Feature[]): void { + this._downloadedData.push(features) + super.addData(this._downloadedData) + } + + /** + * The requested tile might only contain part of the relation. + * + * This method will download the full relation and return it as geojson if it was incomplete. + * If the feature is already complete (or is not a relation), the feature will be returned as is + */ + private async patchIncompleteRelations( + feature: { properties: { id: string } }, + originalJson: { elements: { type: "node" | "way" | "relation"; id: number }[] } + ): Promise { + if (!feature.properties.id.startsWith("relation") || !this._patchRelations) { + return feature + } + const relationSpec = originalJson.elements.find( + (f) => "relation/" + f.id === feature.properties.id + ) + const members: { type: string; ref: number }[] = relationSpec["members"] + for (const member of members) { + const isFound = originalJson.elements.some( + (f) => f.id === member.ref && f.type === member.type + ) + if (isFound) { + continue + } + + // This member is missing. We redownload the entire relation instead + console.debug("Fetching incomplete relation " + feature.properties.id) + const dfeature = await new OsmObjectDownloader(this._backend).DownloadObjectAsync( + feature.properties.id + ) + if (dfeature === "deleted") { + console.warn( + "This relation has been deleted in the meantime: ", + feature.properties.id + ) + return + } + return dfeature.asGeoJson() + } + return feature + } + + private async LoadTile(z: number, x: number, y: number): Promise { + console.log("OsmFeatureSource: loading ", z, x, y, "from", this._backend) + if (z >= 22) { + throw "This is an absurd high zoom level" + } + + if (z < 15) { + throw `Zoom ${z} is too much for OSM to handle! Use a higher zoom level!` + } + const index = Tiles.tile_index(z, x, y) + if (this._downloadedTiles.has(index)) { + return + } + this._downloadedTiles.add(index) + + const bbox = BBox.fromTile(z, x, y) + const url = `${this._backend}/api/0.6/map?bbox=${bbox.minLon},${bbox.minLat},${bbox.maxLon},${bbox.maxLat}` + + let error = undefined + try { + const osmJson = await Utils.downloadJsonCached(url, 2000) + try { + this.options?.fullNodeDatabase?.handleOsmJson(osmJson, z, x, y) + let features = []>OsmToGeoJson( + osmJson, + // @ts-ignore + { + flatProperties: true, + } + ).features + + // The geojson contains _all_ features at the given location + // We only keep what is needed + + features = features.filter((feature) => + this.allowedTags.matchesProperties(feature.properties) + ) + + for (let i = 0; i < features.length; i++) { + features[i] = await this.patchIncompleteRelations(features[i], osmJson) + } + features = Utils.NoNull(features) + features.forEach((f) => { + f.properties["_backend"] = this._backend + }) + this.registerFeatures(features) + } catch (e) { + console.error( + "PANIC: got the tile from the OSM-api, but something crashed handling this tile" + ) + error = e + } + } catch (e) { + console.error( + "Could not download tile", + z, + x, + y, + "due to", + e, + e === "rate limited" ? "; stopping now" : "; retrying with smaller bounds" + ) + if (e === "rate limited") { + return + } + await Promise.all([ + this.LoadTile(z + 1, x * 2, y * 2), + this.LoadTile(z + 1, 1 + x * 2, y * 2), + this.LoadTile(z + 1, x * 2, 1 + y * 2), + this.LoadTile(z + 1, 1 + x * 2, 1 + y * 2), + ]) + } + + if (error !== undefined) { + throw error + } + } +} diff --git a/Logic/FeatureSource/Sources/OverpassFeatureSource.ts b/Logic/FeatureSource/Sources/OverpassFeatureSource.ts new file mode 100644 index 000000000..0188263eb --- /dev/null +++ b/Logic/FeatureSource/Sources/OverpassFeatureSource.ts @@ -0,0 +1,218 @@ +import { Feature } from "geojson" +import { FeatureSource } from "../FeatureSource" +import { ImmutableStore, Store, UIEventSource } from "../../UIEventSource" +import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" +import { Or } from "../../Tags/Or" +import { Overpass } from "../../Osm/Overpass" +import { Utils } from "../../../Utils" +import { TagsFilter } from "../../Tags/TagsFilter" +import { BBox } from "../../BBox" + +/** + * A wrapper around the 'Overpass'-object. + * It has more logic and will automatically fetch the data for the right bbox and the active layers + */ +export default class OverpassFeatureSource implements FeatureSource { + /** + * The last loaded features, as geojson + */ + public readonly features: UIEventSource = new UIEventSource(undefined) + + public readonly runningQuery: UIEventSource = new UIEventSource(false) + public readonly timeout: UIEventSource = new UIEventSource(0) + + private readonly retries: UIEventSource = new UIEventSource(0) + + private readonly state: { + readonly zoom: Store + readonly layers: LayerConfig[] + readonly widenFactor: number + readonly overpassUrl: Store + readonly overpassTimeout: Store + readonly bounds: Store + } + private readonly _isActive: Store + private readonly padToZoomLevel?: Store + private _lastQueryBBox: BBox + + constructor( + state: { + readonly layers: LayerConfig[] + readonly widenFactor: number + readonly zoom: Store + readonly overpassUrl: Store + readonly overpassTimeout: Store + readonly overpassMaxZoom: Store + readonly bounds: Store + }, + options?: { + padToTiles?: Store + isActive?: Store + } + ) { + this.state = state + this._isActive = options?.isActive ?? new ImmutableStore(true) + this.padToZoomLevel = options?.padToTiles + const self = this + state.bounds.addCallbackD((_) => { + self.updateAsyncIfNeeded() + }) + } + + /** + * Creates the 'Overpass'-object for the given layers + * @param interpreterUrl + * @param layersToDownload + * @constructor + * @private + */ + private GetFilter(interpreterUrl: string, layersToDownload: LayerConfig[]): Overpass { + let filters: TagsFilter[] = layersToDownload.map((layer) => layer.source.osmTags) + filters = Utils.NoNull(filters) + if (filters.length === 0) { + return undefined + } + return new Overpass(new Or(filters), [], interpreterUrl, this.state.overpassTimeout) + } + + /** + * + * @private + */ + private async updateAsyncIfNeeded(): Promise { + if (!this._isActive?.data) { + console.log("OverpassFeatureSource: not triggering as not active") + return + } + if (this.runningQuery.data) { + console.log("Still running a query, not updating") + return undefined + } + + if (this.timeout.data > 0) { + console.log("Still in timeout - not updating") + return undefined + } + const requestedBounds = this.state.bounds.data + if ( + this._lastQueryBBox !== undefined && + requestedBounds.isContainedIn(this._lastQueryBBox) + ) { + return undefined + } + const result = await this.updateAsync() + if (!result) { + return + } + const [bounds, date, updatedLayers] = result + this._lastQueryBBox = bounds + } + + /** + * Download the relevant data from overpass. Attempt to use a different server; only downloads the relevant layers + * @private + */ + private async updateAsync(): Promise<[BBox, Date, LayerConfig[]]> { + let data: any = undefined + let date: Date = undefined + let lastUsed = 0 + + const layersToDownload = [] + for (const layer of this.state.layers) { + if (typeof layer === "string") { + throw "A layer was not expanded!" + } + if (layer.source === undefined) { + continue + } + if (this.state.zoom.data < layer.minzoom) { + continue + } + if (layer.doNotDownload) { + continue + } + if (layer.source === null) { + // This is a special layer. Should not have been here + console.warn( + "OverpassFeatureSource received a layer for which the source is null:", + layer.id + ) + continue + } + if (layer.source.geojsonSource !== undefined) { + // Not our responsibility to download this layer! + continue + } + layersToDownload.push(layer) + } + + if (layersToDownload.length == 0) { + return + } + + const self = this + const overpassUrls = self.state.overpassUrl.data + if (overpassUrls === undefined || overpassUrls.length === 0) { + throw "Panic: overpassFeatureSource didn't receive any overpassUrls" + } + // Note: the bounds are updated between attempts, in case that the user zoomed around + let bounds: BBox + do { + try { + bounds = this.state.bounds.data + ?.pad(this.state.widenFactor) + ?.expandToTileBounds(this.padToZoomLevel?.data) + + if (bounds === undefined) { + return undefined + } + + const overpass = this.GetFilter(overpassUrls[lastUsed], layersToDownload) + + if (overpass === undefined) { + return undefined + } + this.runningQuery.setData(true) + ;[data, date] = await overpass.queryGeoJson(bounds) + } catch (e) { + self.retries.data++ + self.retries.ping() + console.error(`QUERY FAILED due to`, e) + + await Utils.waitFor(1000) + + if (lastUsed + 1 < overpassUrls.length) { + lastUsed++ + console.log("Trying next time with", overpassUrls[lastUsed]) + } else { + lastUsed = 0 + self.timeout.setData(self.retries.data * 5) + + while (self.timeout.data > 0) { + await Utils.waitFor(1000) + self.timeout.data-- + self.timeout.ping() + } + } + } + } while (data === undefined && this._isActive.data) + + try { + if (data === undefined) { + return undefined + } + // Some metatags are delivered by overpass _without_ underscore-prefix; we fix them below + // TODO FIXME re-enable this data.features.forEach((f) => SimpleMetaTaggers.objectMetaInfo.applyMetaTagsOnFeature(f)) + + console.log("Overpass returned", data.features.length, "features") + self.features.setData(data.features) + return [bounds, date, layersToDownload] + } catch (e) { + console.error("Got the overpass response, but could not process it: ", e, e.stack) + return undefined + } finally { + self.retries.setData(0) + self.runningQuery.setData(false) + } + } +} diff --git a/Logic/FeatureSource/Sources/RememberingSource.ts b/Logic/FeatureSource/Sources/RememberingSource.ts deleted file mode 100644 index 5d71541c4..000000000 --- a/Logic/FeatureSource/Sources/RememberingSource.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Every previously added point is remembered, but new points are added. - * Data coming from upstream will always overwrite a previous value - */ -import FeatureSource, { Tiled } from "../FeatureSource" -import { Store, UIEventSource } from "../../UIEventSource" -import { BBox } from "../../BBox" - -export default class RememberingSource implements FeatureSource, Tiled { - public readonly features: Store<{ feature: any; freshness: Date }[]> - public readonly name - public readonly tileIndex: number - public readonly bbox: BBox - - constructor(source: FeatureSource & Tiled) { - const self = this - this.name = "RememberingSource of " + source.name - this.tileIndex = source.tileIndex - this.bbox = source.bbox - - const empty = [] - const featureSource = new UIEventSource<{ feature: any; freshness: Date }[]>(empty) - this.features = featureSource - source.features.addCallbackAndRunD((features) => { - const oldFeatures = self.features?.data ?? empty - // Then new ids - const ids = new Set( - features.map((f) => f.feature.properties.id + f.feature.geometry.type) - ) - // the old data - const oldData = oldFeatures.filter( - (old) => !ids.has(old.feature.properties.id + old.feature.geometry.type) - ) - featureSource.setData([...features, ...oldData]) - }) - } -} diff --git a/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts b/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts deleted file mode 100644 index 6a07fb7aa..000000000 --- a/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts +++ /dev/null @@ -1,170 +0,0 @@ -/** - * This feature source helps the ShowDataLayer class: it introduces the necessary extra features and indicates with what renderConfig it should be rendered. - */ -import { Store } from "../../UIEventSource" -import { GeoOperations } from "../../GeoOperations" -import FeatureSource from "../FeatureSource" -import PointRenderingConfig from "../../../Models/ThemeConfig/PointRenderingConfig" -import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" -import LineRenderingConfig from "../../../Models/ThemeConfig/LineRenderingConfig" - -export default class RenderingMultiPlexerFeatureSource { - public readonly features: Store< - (any & { - pointRenderingIndex: number | undefined - lineRenderingIndex: number | undefined - })[] - > - private readonly pointRenderings: { rendering: PointRenderingConfig; index: number }[] - private readonly centroidRenderings: { rendering: PointRenderingConfig; index: number }[] - private readonly projectedCentroidRenderings: { - rendering: PointRenderingConfig - index: number - }[] - private readonly startRenderings: { rendering: PointRenderingConfig; index: number }[] - private readonly endRenderings: { rendering: PointRenderingConfig; index: number }[] - private readonly hasCentroid: boolean - private lineRenderObjects: LineRenderingConfig[] - - constructor(upstream: FeatureSource, layer: LayerConfig) { - const pointRenderObjects: { rendering: PointRenderingConfig; index: number }[] = - layer.mapRendering.map((r, i) => ({ - rendering: r, - index: i, - })) - this.pointRenderings = pointRenderObjects.filter((r) => r.rendering.location.has("point")) - this.centroidRenderings = pointRenderObjects.filter((r) => - r.rendering.location.has("centroid") - ) - this.projectedCentroidRenderings = pointRenderObjects.filter((r) => - r.rendering.location.has("projected_centerpoint") - ) - this.startRenderings = pointRenderObjects.filter((r) => r.rendering.location.has("start")) - this.endRenderings = pointRenderObjects.filter((r) => r.rendering.location.has("end")) - this.hasCentroid = - this.centroidRenderings.length > 0 || this.projectedCentroidRenderings.length > 0 - this.lineRenderObjects = layer.lineRendering - - this.features = upstream.features.map((features) => { - if (features === undefined) { - return undefined - } - - const withIndex: any[] = [] - - function addAsPoint(feat, rendering, coordinate) { - const patched = { - ...feat, - pointRenderingIndex: rendering.index, - } - patched.geometry = { - type: "Point", - coordinates: coordinate, - } - withIndex.push(patched) - } - - for (const f of features) { - const feat = f.feature - if (feat === undefined) { - continue - } - this.inspectFeature(feat, addAsPoint, withIndex) - } - - return withIndex - }) - } - - /** - * For every source feature, adds the necessary rendering-features - */ - private inspectFeature( - feat, - addAsPoint: (feat, rendering, centerpoint: [number, number]) => void, - withIndex: any[] - ) { - if (feat.geometry.type === "Point") { - for (const rendering of this.pointRenderings) { - withIndex.push({ - ...feat, - pointRenderingIndex: rendering.index, - }) - } - } else if (feat.geometry.type === "MultiPolygon") { - if (this.centroidRenderings.length > 0 || this.projectedCentroidRenderings.length > 0) { - const centerpoints: [number, number][] = (<[number, number][][][]>( - feat.geometry.coordinates - )).map((rings) => - GeoOperations.centerpointCoordinates({ - type: "Feature", - properties: {}, - geometry: { type: "Polygon", coordinates: rings }, - }) - ) - for (const centroidRendering of this.centroidRenderings) { - for (const centerpoint of centerpoints) { - addAsPoint(feat, centroidRendering, centerpoint) - } - } - - for (const centroidRendering of this.projectedCentroidRenderings) { - for (const centerpoint of centerpoints) { - addAsPoint(feat, centroidRendering, centerpoint) - } - } - } - - // AT last, add it 'as is' to what we should render - for (let i = 0; i < this.lineRenderObjects.length; i++) { - withIndex.push({ - ...feat, - lineRenderingIndex: i, - }) - } - } else { - // This is a a line or polygon: add the centroids - let centerpoint: [number, number] = undefined - let projectedCenterPoint: [number, number] = undefined - if (this.hasCentroid) { - centerpoint = GeoOperations.centerpointCoordinates(feat) - if (this.projectedCentroidRenderings.length > 0) { - projectedCenterPoint = <[number, number]>( - GeoOperations.nearestPoint(feat, centerpoint).geometry.coordinates - ) - } - } - for (const rendering of this.centroidRenderings) { - addAsPoint(feat, rendering, centerpoint) - } - - if (feat.geometry.type === "LineString") { - for (const rendering of this.projectedCentroidRenderings) { - addAsPoint(feat, rendering, projectedCenterPoint) - } - - // Add start- and endpoints - const coordinates = feat.geometry.coordinates - for (const rendering of this.startRenderings) { - addAsPoint(feat, rendering, coordinates[0]) - } - for (const rendering of this.endRenderings) { - const coordinate = coordinates[coordinates.length - 1] - addAsPoint(feat, rendering, coordinate) - } - } else { - for (const rendering of this.projectedCentroidRenderings) { - addAsPoint(feat, rendering, centerpoint) - } - } - - // AT last, add it 'as is' to what we should render - for (let i = 0; i < this.lineRenderObjects.length; i++) { - withIndex.push({ - ...feat, - lineRenderingIndex: i, - }) - } - } - } -} diff --git a/Logic/FeatureSource/Sources/SimpleFeatureSource.ts b/Logic/FeatureSource/Sources/SimpleFeatureSource.ts index f2dfec678..c280bebcb 100644 --- a/Logic/FeatureSource/Sources/SimpleFeatureSource.ts +++ b/Logic/FeatureSource/Sources/SimpleFeatureSource.ts @@ -1,24 +1,14 @@ import { UIEventSource } from "../../UIEventSource" import FilteredLayer from "../../../Models/FilteredLayer" -import { FeatureSourceForLayer, Tiled } from "../FeatureSource" -import { BBox } from "../../BBox" +import { FeatureSourceForLayer } from "../FeatureSource" +import { Feature } from "geojson" -export default class SimpleFeatureSource implements FeatureSourceForLayer, Tiled { - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> - public readonly name: string = "SimpleFeatureSource" +export default class SimpleFeatureSource implements FeatureSourceForLayer { + public readonly features: UIEventSource public readonly layer: FilteredLayer - public readonly bbox: BBox = BBox.global - public readonly tileIndex: number - constructor( - layer: FilteredLayer, - tileIndex: number, - featureSource?: UIEventSource<{ feature: any; freshness: Date }[]> - ) { - this.name = "SimpleFeatureSource(" + layer.layerDef.id + ")" + constructor(layer: FilteredLayer, featureSource?: UIEventSource) { this.layer = layer - this.tileIndex = tileIndex ?? 0 - this.bbox = BBox.fromTileIndex(this.tileIndex) - this.features = featureSource ?? new UIEventSource<{ feature: any; freshness: Date }[]>([]) + this.features = featureSource ?? new UIEventSource([]) } } diff --git a/Logic/FeatureSource/Sources/SnappingFeatureSource.ts b/Logic/FeatureSource/Sources/SnappingFeatureSource.ts new file mode 100644 index 000000000..6cc85858f --- /dev/null +++ b/Logic/FeatureSource/Sources/SnappingFeatureSource.ts @@ -0,0 +1,105 @@ +import { FeatureSource } from "../FeatureSource" +import { Store, UIEventSource } from "../../UIEventSource" +import { Feature, Point } from "geojson" +import { GeoOperations } from "../../GeoOperations" +import { BBox } from "../../BBox" + +export interface SnappingOptions { + /** + * If the distance is bigger then this amount, don't snap. + * In meter + */ + maxDistance: number + + allowUnsnapped?: false | boolean + + /** + * The snapped-to way will be written into this + */ + snappedTo?: UIEventSource + + /** + * The resulting snap coordinates will be written into this UIEventSource + */ + snapLocation?: UIEventSource<{ lon: number; lat: number }> + + /** + * If the projected point is within `reusePointWithin`-meter of an already existing point + */ + reusePointWithin?: number +} + +export default class SnappingFeatureSource implements FeatureSource { + public readonly features: Store[]> + /*Contains the id of the way it snapped to*/ + public readonly snappedTo: Store + private readonly _snappedTo: UIEventSource + + constructor( + snapTo: FeatureSource, + location: Store<{ lon: number; lat: number }>, + options: SnappingOptions + ) { + const maxDistance = options?.maxDistance + this._snappedTo = options.snappedTo ?? new UIEventSource(undefined) + this.snappedTo = this._snappedTo + const simplifiedFeatures = snapTo.features + .mapD((features) => + features + .filter((feature) => feature.geometry.type !== "Point") + .map((f) => GeoOperations.forceLineString(f)) + ) + .map( + (features) => { + const { lon, lat } = location.data + const loc: [number, number] = [lon, lat] + return features.filter((f) => BBox.get(f).isNearby(loc, maxDistance)) + }, + [location] + ) + + this.features = location.mapD( + ({ lon, lat }) => { + const features = simplifiedFeatures.data + const loc: [number, number] = [lon, lat] + const maxDistance = (options?.maxDistance ?? 1000) / 1000 + let bestSnap: Feature = undefined + for (const feature of features) { + if (feature.geometry.type !== "LineString") { + // TODO handle Polygons with holes + continue + } + const snapped = GeoOperations.nearestPoint(feature, loc) + if (snapped.properties.dist > maxDistance) { + continue + } + if ( + bestSnap === undefined || + bestSnap.properties.dist > snapped.properties.dist + ) { + snapped.properties["snapped-to"] = feature.properties.id + bestSnap = snapped + } + } + this._snappedTo.setData(bestSnap?.properties?.["snapped-to"]) + if (bestSnap === undefined && options?.allowUnsnapped) { + bestSnap = { + type: "Feature", + geometry: { + type: "Point", + coordinates: [lon, lat], + }, + properties: { + "snapped-to": undefined, + dist: -1, + }, + } + } + const c = bestSnap.geometry.coordinates + options?.snapLocation?.setData({ lon: c[0], lat: c[1] }) + return [bestSnap] + }, + [snapTo.features] + ) + } +} diff --git a/Logic/FeatureSource/Sources/StaticFeatureSource.ts b/Logic/FeatureSource/Sources/StaticFeatureSource.ts index d99304a47..4811d3612 100644 --- a/Logic/FeatureSource/Sources/StaticFeatureSource.ts +++ b/Logic/FeatureSource/Sources/StaticFeatureSource.ts @@ -1,89 +1,38 @@ -import FeatureSource, { FeatureSourceForLayer, Tiled } from "../FeatureSource" -import { ImmutableStore, Store } from "../../UIEventSource" -import FilteredLayer from "../../../Models/FilteredLayer" -import { BBox } from "../../BBox" -import { Feature } from "geojson" +import {FeatureSource} from "../FeatureSource" +import {ImmutableStore, Store} from "../../UIEventSource" +import {Feature} from "geojson" /** * A simple, read only feature store. */ -export default class StaticFeatureSource implements FeatureSource { - public readonly features: Store<{ feature: any; freshness: Date }[]> - public readonly name: string +export default class StaticFeatureSource implements FeatureSource { + public readonly features: Store constructor( - features: Store<{ feature: Feature; freshness: Date }[]>, - name = "StaticFeatureSource" + features: + | Store + | T[] + | { features: T[] } + | { features: Store } ) { if (features === undefined) { throw "Static feature source received undefined as source" } - this.name = name - this.features = features + let feats: T[] | Store + if (features["features"]) { + feats = features["features"] + } else { + feats = >features + } + + if (Array.isArray(feats)) { + this.features = new ImmutableStore(feats) + } else { + this.features = feats + } } - public static fromGeojsonAndDate( - features: { feature: Feature; freshness: Date }[], - name = "StaticFeatureSourceFromGeojsonAndDate" - ): StaticFeatureSource { - return new StaticFeatureSource(new ImmutableStore(features), name) - } - - public static fromGeojson( - geojson: Feature[], - name = "StaticFeatureSourceFromGeojson" - ): StaticFeatureSource { - const now = new Date() - return StaticFeatureSource.fromGeojsonAndDate( - geojson.map((feature) => ({ feature, freshness: now })), - name - ) - } - - public static fromGeojsonStore( - geojson: Store, - name = "StaticFeatureSourceFromGeojson" - ): StaticFeatureSource { - const now = new Date() - const mapped: Store<{ feature: Feature; freshness: Date }[]> = geojson.map((features) => - features.map((feature) => ({ feature, freshness: now })) - ) - return new StaticFeatureSource(mapped, name) - } - - static fromDateless( - featureSource: Store<{ feature: Feature }[]>, - name = "StaticFeatureSourceFromDateless" - ) { - const now = new Date() - return new StaticFeatureSource( - featureSource.map((features) => - features.map((feature) => ({ - feature: feature.feature, - freshness: now, - })) - ), - name - ) - } -} - -export class TiledStaticFeatureSource - extends StaticFeatureSource - implements Tiled, FeatureSourceForLayer -{ - public readonly bbox: BBox = BBox.global - public readonly tileIndex: number - public readonly layer: FilteredLayer - - constructor( - features: Store<{ feature: any; freshness: Date }[]>, - layer: FilteredLayer, - tileIndex: number = 0 - ) { - super(features) - this.tileIndex = tileIndex - this.layer = layer - this.bbox = BBox.fromTileIndex(this.tileIndex) + public static fromGeojson(geojson: T[]): StaticFeatureSource { + return new StaticFeatureSource(geojson) } } diff --git a/Logic/FeatureSource/Sources/TouchesBboxFeatureSource.ts b/Logic/FeatureSource/Sources/TouchesBboxFeatureSource.ts new file mode 100644 index 000000000..182187da8 --- /dev/null +++ b/Logic/FeatureSource/Sources/TouchesBboxFeatureSource.ts @@ -0,0 +1,40 @@ +import {FeatureSource, FeatureSourceForLayer} from "../FeatureSource" +import StaticFeatureSource from "./StaticFeatureSource" +import {BBox} from "../../BBox" +import FilteredLayer from "../../../Models/FilteredLayer" +import {Store} from "../../UIEventSource" +import {Feature} from "geojson"; + +/** + * Results in a feature source which has all the elements that touch the given features + */ +export default class BBoxFeatureSource extends StaticFeatureSource { + constructor(features: FeatureSource, mustTouch: Store) { + super( + features.features.mapD( + (features) => { + if (mustTouch.data === undefined) { + return features + } + const box = mustTouch.data + return features.filter((feature) => { + if (feature.geometry.type === "Point") { + return box.contains(<[number, number]>feature.geometry.coordinates) + } + return box.overlapsWith(BBox.get(feature)) + }) + }, + [mustTouch] + ) + ) + } +} + +export class BBoxFeatureSourceForLayer extends BBoxFeatureSource implements FeatureSourceForLayer { + readonly layer: FilteredLayer + + constructor(features: FeatureSourceForLayer, mustTouch: Store) { + super(features, mustTouch) + this.layer = features.layer + } +} diff --git a/Logic/FeatureSource/TileFreshnessCalculator.ts b/Logic/FeatureSource/TileFreshnessCalculator.ts deleted file mode 100644 index 3d1adde97..000000000 --- a/Logic/FeatureSource/TileFreshnessCalculator.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Tiles } from "../../Models/TileRange" - -export default class TileFreshnessCalculator { - /** - * All the freshnesses per tile index - * @private - */ - private readonly freshnesses = new Map() - - /** - * Marks that some data got loaded for this layer - * @param tileId - * @param freshness - */ - public addTileLoad(tileId: number, freshness: Date) { - const existingFreshness = this.freshnessFor(...Tiles.tile_from_index(tileId)) - if (existingFreshness >= freshness) { - return - } - this.freshnesses.set(tileId, freshness) - - // Do we have freshness for the neighbouring tiles? If so, we can mark the tile above as loaded too! - let [z, x, y] = Tiles.tile_from_index(tileId) - if (z === 0) { - return - } - x = x - (x % 2) // Make the tiles always even - y = y - (y % 2) - - const ul = this.freshnessFor(z, x, y)?.getTime() - if (ul === undefined) { - return - } - const ur = this.freshnessFor(z, x + 1, y)?.getTime() - if (ur === undefined) { - return - } - const ll = this.freshnessFor(z, x, y + 1)?.getTime() - if (ll === undefined) { - return - } - const lr = this.freshnessFor(z, x + 1, y + 1)?.getTime() - if (lr === undefined) { - return - } - - const leastFresh = Math.min(ul, ur, ll, lr) - const date = new Date() - date.setTime(leastFresh) - this.addTileLoad(Tiles.tile_index(z - 1, Math.floor(x / 2), Math.floor(y / 2)), date) - } - - public freshnessFor(z: number, x: number, y: number): Date { - if (z < 0) { - return undefined - } - const tileId = Tiles.tile_index(z, x, y) - if (this.freshnesses.has(tileId)) { - return this.freshnesses.get(tileId) - } - // recurse up - return this.freshnessFor(z - 1, Math.floor(x / 2), Math.floor(y / 2)) - } -} diff --git a/Logic/FeatureSource/TiledFeatureSource/DynamicGeoJsonTileSource.ts b/Logic/FeatureSource/TiledFeatureSource/DynamicGeoJsonTileSource.ts index dd2b69ffe..0a3e77d90 100644 --- a/Logic/FeatureSource/TiledFeatureSource/DynamicGeoJsonTileSource.ts +++ b/Logic/FeatureSource/TiledFeatureSource/DynamicGeoJsonTileSource.ts @@ -1,36 +1,38 @@ -import FilteredLayer from "../../../Models/FilteredLayer" -import { FeatureSourceForLayer, Tiled } from "../FeatureSource" -import { UIEventSource } from "../../UIEventSource" +import { Store } from "../../UIEventSource" import DynamicTileSource from "./DynamicTileSource" import { Utils } from "../../../Utils" import GeoJsonSource from "../Sources/GeoJsonSource" import { BBox } from "../../BBox" +import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" export default class DynamicGeoJsonTileSource extends DynamicTileSource { private static whitelistCache = new Map() constructor( - layer: FilteredLayer, - registerLayer: (layer: FeatureSourceForLayer & Tiled) => void, - state: { - locationControl?: UIEventSource<{ zoom?: number }> - currentBounds: UIEventSource + layer: LayerConfig, + mapProperties: { + zoom: Store + bounds: Store + }, + options?: { + isActive?: Store } ) { - const source = layer.layerDef.source + const source = layer.source if (source.geojsonZoomLevel === undefined) { throw "Invalid layer: geojsonZoomLevel expected" } if (source.geojsonSource === undefined) { throw "Invalid layer: geojsonSource expected" } + console.log("Creating a dynamic geojson source for", layer.source.geojsonSource) let whitelist = undefined if (source.geojsonSource.indexOf("{x}_{y}.geojson") > 0) { const whitelistUrl = source.geojsonSource .replace("{z}", "" + source.geojsonZoomLevel) .replace("{x}_{y}.geojson", "overview.json") - .replace("{layer}", layer.layerDef.id) + .replace("{layer}", layer.id) if (DynamicGeoJsonTileSource.whitelistCache.has(whitelistUrl)) { whitelist = DynamicGeoJsonTileSource.whitelistCache.get(whitelistUrl) @@ -56,14 +58,13 @@ export default class DynamicGeoJsonTileSource extends DynamicTileSource { DynamicGeoJsonTileSource.whitelistCache.set(whitelistUrl, whitelist) }) .catch((err) => { - console.warn("No whitelist found for ", layer.layerDef.id, err) + console.warn("No whitelist found for ", layer.id, err) }) } } const blackList = new Set() super( - layer, source.geojsonZoomLevel, (zxy) => { if (whitelist !== undefined) { @@ -71,32 +72,23 @@ export default class DynamicGeoJsonTileSource extends DynamicTileSource { if (!isWhiteListed) { console.debug( "Not downloading tile", - ...zxy, + zxy,"for layer",layer.id, "as it is not on the whitelist" ) return undefined } } - const src = new GeoJsonSource(layer, zxy, { + return new GeoJsonSource(layer, { + zxy, featureIdBlacklist: blackList, + isActive: options?.isActive, }) - - registerLayer(src) - return src }, - state + mapProperties, + { + isActive: options?.isActive, + } ) } - - public static RegisterWhitelist(url: string, json: any) { - const data = new Map>() - for (const x in json) { - if (x === "zoom") { - continue - } - data.set(Number(x), new Set(json[x])) - } - DynamicGeoJsonTileSource.whitelistCache.set(url, data) - } } diff --git a/Logic/FeatureSource/TiledFeatureSource/DynamicTileSource.ts b/Logic/FeatureSource/TiledFeatureSource/DynamicTileSource.ts index 78f759818..024d86574 100644 --- a/Logic/FeatureSource/TiledFeatureSource/DynamicTileSource.ts +++ b/Logic/FeatureSource/TiledFeatureSource/DynamicTileSource.ts @@ -1,87 +1,62 @@ -import FilteredLayer from "../../../Models/FilteredLayer" -import { FeatureSourceForLayer, Tiled } from "../FeatureSource" -import { UIEventSource } from "../../UIEventSource" -import TileHierarchy from "./TileHierarchy" +import { Store, Stores } from "../../UIEventSource" import { Tiles } from "../../../Models/TileRange" import { BBox } from "../../BBox" +import { FeatureSource } from "../FeatureSource" +import FeatureSourceMerger from "../Sources/FeatureSourceMerger" /*** - * A tiled source which dynamically loads the required tiles at a fixed zoom level + * A tiled source which dynamically loads the required tiles at a fixed zoom level. + * A single featureSource will be initiliased for every tile in view; which will alter be merged into this featureSource */ -export default class DynamicTileSource implements TileHierarchy { - public readonly loadedTiles: Map - private readonly _loadedTiles = new Set() - +export default class DynamicTileSource extends FeatureSourceMerger { constructor( - layer: FilteredLayer, zoomlevel: number, - constructTile: (zxy: [number, number, number]) => FeatureSourceForLayer & Tiled, - state: { - currentBounds: UIEventSource - locationControl?: UIEventSource<{ zoom?: number }> + constructSource: (tileIndex) => FeatureSource, + mapProperties: { + bounds: Store + zoom: Store + }, + options?: { + isActive?: Store } ) { - const self = this - - this.loadedTiles = new Map() - const neededTiles = state.currentBounds - .map( - (bounds) => { - if (bounds === undefined) { - // We'll retry later - return undefined - } - - if (!layer.isDisplayed.data && !layer.layerDef.forceLoad) { - // No need to download! - the layer is disabled - return undefined - } - - if ( - state.locationControl?.data?.zoom !== undefined && - state.locationControl.data.zoom < layer.layerDef.minzoom - ) { - // No need to download! - the layer is disabled - return undefined - } - - const tileRange = Tiles.TileRangeBetween( - zoomlevel, - bounds.getNorth(), - bounds.getEast(), - bounds.getSouth(), - bounds.getWest() - ) - if (tileRange.total > 10000) { - console.error( - "Got a really big tilerange, bounds and location might be out of sync" + super() + const loadedTiles = new Set() + const neededTiles: Store = Stores.ListStabilized( + mapProperties.bounds + .mapD( + (bounds) => { + const tileRange = Tiles.TileRangeBetween( + zoomlevel, + bounds.getNorth(), + bounds.getEast(), + bounds.getSouth(), + bounds.getWest() ) - return undefined - } + if (tileRange.total > 10000) { + console.error( + "Got a really big tilerange, bounds and location might be out of sync" + ) + return undefined + } - const needed = Tiles.MapRange(tileRange, (x, y) => - Tiles.tile_index(zoomlevel, x, y) - ).filter((i) => !self._loadedTiles.has(i)) - if (needed.length === 0) { - return undefined - } - return needed - }, - [layer.isDisplayed, state.locationControl] - ) - .stabilized(250) + const needed = Tiles.MapRange(tileRange, (x, y) => + Tiles.tile_index(zoomlevel, x, y) + ).filter((i) => !loadedTiles.has(i)) + if (needed.length === 0) { + return undefined + } + return needed + }, + [options?.isActive, mapProperties.zoom] + ) + .stabilized(250) + ) neededTiles.addCallbackAndRunD((neededIndexes) => { - console.log("Tiled geojson source ", layer.layerDef.id, " needs", neededIndexes) - if (neededIndexes === undefined) { - return - } for (const neededIndex of neededIndexes) { - self._loadedTiles.add(neededIndex) - const src = constructTile(Tiles.tile_from_index(neededIndex)) - if (src !== undefined) { - self.loadedTiles.set(neededIndex, src) - } + loadedTiles.add(neededIndex) + super.addSource(constructSource(neededIndex)) } }) } diff --git a/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts b/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts index f312d0a35..4127a33d1 100644 --- a/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts +++ b/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts @@ -1,29 +1,25 @@ -import TileHierarchy from "./TileHierarchy" -import FeatureSource, { FeatureSourceForLayer, Tiled } from "../FeatureSource" -import { OsmNode, OsmObject, OsmWay } from "../../Osm/OsmObject" -import SimpleFeatureSource from "../Sources/SimpleFeatureSource" -import FilteredLayer from "../../../Models/FilteredLayer" -import { UIEventSource } from "../../UIEventSource" +import {OsmNode, OsmObject, OsmWay} from "../../Osm/OsmObject" +import {UIEventSource} from "../../UIEventSource" +import {BBox} from "../../BBox"; +import StaticFeatureSource from "../Sources/StaticFeatureSource"; +import {Tiles} from "../../../Models/TileRange"; -export default class FullNodeDatabaseSource implements TileHierarchy { - public readonly loadedTiles = new Map() - private readonly onTileLoaded: (tile: Tiled & FeatureSourceForLayer) => void - private readonly layer: FilteredLayer +export default class FullNodeDatabaseSource { + + private readonly loadedTiles = new Map>() private readonly nodeByIds = new Map() private readonly parentWays = new Map>() - constructor(layer: FilteredLayer, onTileLoaded: (tile: Tiled & FeatureSourceForLayer) => void) { - this.onTileLoaded = onTileLoaded - this.layer = layer - if (this.layer === undefined) { - throw "Layer is undefined" - } - } + private smallestZoom = 99 + private largestZoom = 0 - public handleOsmJson(osmJson: any, tileId: number) { + public handleOsmJson(osmJson: any, z: number, x: number, y: number) : void { const allObjects = OsmObject.ParseObjects(osmJson.elements) const nodesById = new Map() + this.smallestZoom = Math.min(this.smallestZoom, z) + this.largestZoom = Math.max(this.largestZoom, z) + for (const osmObj of allObjects) { if (osmObj.type !== "node") { continue @@ -53,16 +49,13 @@ export default class FullNodeDatabaseSource implements TileHierarchy ({ - feature: osmNode.asGeoJson(), - freshness: now, - })) + const asGeojsonFeatures = Array.from(nodesById.values()).map((osmNode) => + osmNode.asGeoJson() + ) - const featureSource = new SimpleFeatureSource(this.layer, tileId) - featureSource.features.setData(asGeojsonFeatures) - this.loadedTiles.set(tileId, featureSource) - this.onTileLoaded(featureSource) + const featureSource = new StaticFeatureSource(asGeojsonFeatures) + const tileId = Tiles.tile_index(z, x, y) + this.loadedTiles.set(tileId, nodesById) } /** @@ -76,11 +69,28 @@ export default class FullNodeDatabaseSource implements TileHierarchy { return this.parentWays.get(nodeId) } + + /** + * Gets (at least) all nodes which are part of this BBOX; might also return some nodes that fall outside of the bbox but are closeby + * @param bbox + */ + getNodesWithin(bbox: BBox) : Map{ + const allById = new Map() + for (let z = this.smallestZoom; z < this.largestZoom; z++) { + const range = Tiles.tileRangeFrom(bbox, z) + Tiles.MapRange(range, (x, y ) => { + const tileId = Tiles.tile_index(z, x, y) + const nodesById = this.loadedTiles.get(tileId) + nodesById?.forEach((v,k) => allById.set(k,v)) + }) + } + return allById + } } diff --git a/Logic/FeatureSource/TiledFeatureSource/LocalStorageFeatureSource.ts b/Logic/FeatureSource/TiledFeatureSource/LocalStorageFeatureSource.ts new file mode 100644 index 000000000..16cc2b94e --- /dev/null +++ b/Logic/FeatureSource/TiledFeatureSource/LocalStorageFeatureSource.ts @@ -0,0 +1,43 @@ +import DynamicTileSource from "./DynamicTileSource" +import {Store} from "../../UIEventSource" +import {BBox} from "../../BBox" +import TileLocalStorage from "../Actors/TileLocalStorage" +import {Feature} from "geojson" +import StaticFeatureSource from "../Sources/StaticFeatureSource" + +export default class LocalStorageFeatureSource extends DynamicTileSource { + constructor( + backend: string, + layername: string, + zoomlevel: number, + mapProperties: { + bounds: Store + zoom: Store + }, + options?: { + isActive?: Store, + maxAge?: number // In seconds + } + ) { + const storage = TileLocalStorage.construct(backend, layername, options?.maxAge ?? 24 * 60 * 60) + super( + zoomlevel, + (tileIndex) => + new StaticFeatureSource( + storage + .getTileSource(tileIndex) + .mapD((features) => { + if (features.length === undefined) { + console.trace("These are not features:", features) + storage.invalidate(zoomlevel, tileIndex) + return [] + } + return features.filter((f) => !f.properties.id.match(/(node|way)\/-[0-9]+/)); + } + ) + ), + mapProperties, + options + ) + } +} diff --git a/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts b/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts deleted file mode 100644 index 849ea4c7d..000000000 --- a/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts +++ /dev/null @@ -1,215 +0,0 @@ -import { Utils } from "../../../Utils" -import OsmToGeoJson from "osmtogeojson" -import StaticFeatureSource from "../Sources/StaticFeatureSource" -import PerLayerFeatureSourceSplitter from "../PerLayerFeatureSourceSplitter" -import { Store, UIEventSource } from "../../UIEventSource" -import FilteredLayer from "../../../Models/FilteredLayer" -import { FeatureSourceForLayer, Tiled } from "../FeatureSource" -import { Tiles } from "../../../Models/TileRange" -import { BBox } from "../../BBox" -import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig" -import { Or } from "../../Tags/Or" -import { TagsFilter } from "../../Tags/TagsFilter" -import { OsmObject } from "../../Osm/OsmObject" -import { FeatureCollection } from "@turf/turf" - -/** - * If a tile is needed (requested via the UIEventSource in the constructor), will download the appropriate tile and pass it via 'handleTile' - */ -export default class OsmFeatureSource { - public readonly isRunning: UIEventSource = new UIEventSource(false) - public readonly downloadedTiles = new Set() - public rawDataHandlers: ((osmJson: any, tileId: number) => void)[] = [] - private readonly _backend: string - private readonly filteredLayers: Store - private readonly handleTile: (fs: FeatureSourceForLayer & Tiled) => void - private isActive: Store - private options: { - handleTile: (tile: FeatureSourceForLayer & Tiled) => void - isActive: Store - neededTiles: Store - markTileVisited?: (tileId: number) => void - } - private readonly allowedTags: TagsFilter - - /** - * - * @param options: allowedFeatures is normally calculated from the layoutToUse - */ - constructor(options: { - handleTile: (tile: FeatureSourceForLayer & Tiled) => void - isActive: Store - neededTiles: Store - state: { - readonly filteredLayers: UIEventSource - readonly osmConnection: { - Backend(): string - } - readonly layoutToUse?: LayoutConfig - } - readonly allowedFeatures?: TagsFilter - markTileVisited?: (tileId: number) => void - }) { - this.options = options - this._backend = options.state.osmConnection.Backend() - this.filteredLayers = options.state.filteredLayers.map((layers) => - layers.filter((layer) => layer.layerDef.source.geojsonSource === undefined) - ) - this.handleTile = options.handleTile - this.isActive = options.isActive - const self = this - options.neededTiles.addCallbackAndRunD((neededTiles) => { - self.Update(neededTiles) - }) - - const neededLayers = (options.state.layoutToUse?.layers ?? []) - .filter((layer) => !layer.doNotDownload) - .filter( - (layer) => layer.source.geojsonSource === undefined || layer.source.isOsmCacheLayer - ) - this.allowedTags = - options.allowedFeatures ?? new Or(neededLayers.map((l) => l.source.osmTags)) - } - - private async Update(neededTiles: number[]) { - if (this.options.isActive?.data === false) { - return - } - - neededTiles = neededTiles.filter((tile) => !this.downloadedTiles.has(tile)) - - if (neededTiles.length == 0) { - return - } - - this.isRunning.setData(true) - try { - for (const neededTile of neededTiles) { - this.downloadedTiles.add(neededTile) - await this.LoadTile(...Tiles.tile_from_index(neededTile)) - } - } catch (e) { - console.error(e) - } finally { - this.isRunning.setData(false) - } - } - - /** - * The requested tile might only contain part of the relation. - * - * This method will download the full relation and return it as geojson if it was incomplete. - * If the feature is already complete (or is not a relation), the feature will be returned - */ - private async patchIncompleteRelations( - feature: { properties: { id: string } }, - originalJson: { elements: { type: "node" | "way" | "relation"; id: number }[] } - ): Promise { - if (!feature.properties.id.startsWith("relation")) { - return feature - } - const relationSpec = originalJson.elements.find( - (f) => "relation/" + f.id === feature.properties.id - ) - const members: { type: string; ref: number }[] = relationSpec["members"] - for (const member of members) { - const isFound = originalJson.elements.some( - (f) => f.id === member.ref && f.type === member.type - ) - if (isFound) { - continue - } - - // This member is missing. We redownload the entire relation instead - console.debug("Fetching incomplete relation " + feature.properties.id) - return (await OsmObject.DownloadObjectAsync(feature.properties.id)).asGeoJson() - } - return feature - } - - private async LoadTile(z, x, y): Promise { - if (z >= 22) { - throw "This is an absurd high zoom level" - } - - if (z < 14) { - throw `Zoom ${z} is too much for OSM to handle! Use a higher zoom level!` - } - - const bbox = BBox.fromTile(z, x, y) - const url = `${this._backend}/api/0.6/map?bbox=${bbox.minLon},${bbox.minLat},${bbox.maxLon},${bbox.maxLat}` - - let error = undefined - try { - const osmJson = await Utils.downloadJson(url) - try { - this.rawDataHandlers.forEach((handler) => - handler(osmJson, Tiles.tile_index(z, x, y)) - ) - const geojson = >OsmToGeoJson( - osmJson, - // @ts-ignore - { - flatProperties: true, - } - ) - - // The geojson contains _all_ features at the given location - // We only keep what is needed - - geojson.features = geojson.features.filter((feature) => - this.allowedTags.matchesProperties(feature.properties) - ) - - for (let i = 0; i < geojson.features.length; i++) { - geojson.features[i] = await this.patchIncompleteRelations( - geojson.features[i], - osmJson - ) - } - geojson.features.forEach((f) => { - f.properties["_backend"] = this._backend - }) - - const index = Tiles.tile_index(z, x, y) - new PerLayerFeatureSourceSplitter( - this.filteredLayers, - this.handleTile, - StaticFeatureSource.fromGeojson(geojson.features), - { - tileIndex: index, - } - ) - if (this.options.markTileVisited) { - this.options.markTileVisited(index) - } - } catch (e) { - console.error( - "PANIC: got the tile from the OSM-api, but something crashed handling this tile" - ) - error = e - } - } catch (e) { - console.error( - "Could not download tile", - z, - x, - y, - "due to", - e, - "; retrying with smaller bounds" - ) - if (e === "rate limited") { - return - } - await this.LoadTile(z + 1, x * 2, y * 2) - await this.LoadTile(z + 1, 1 + x * 2, y * 2) - await this.LoadTile(z + 1, x * 2, 1 + y * 2) - await this.LoadTile(z + 1, 1 + x * 2, 1 + y * 2) - } - - if (error !== undefined) { - throw error - } - } -} diff --git a/Logic/FeatureSource/TiledFeatureSource/README.md b/Logic/FeatureSource/TiledFeatureSource/README.md deleted file mode 100644 index 914c1caf7..000000000 --- a/Logic/FeatureSource/TiledFeatureSource/README.md +++ /dev/null @@ -1,24 +0,0 @@ -Data in MapComplete can come from multiple sources. - -Currently, they are: - -- The Overpass-API -- The OSM-API -- One or more GeoJSON files. This can be a single file or a set of tiled geojson files -- LocalStorage, containing features from a previous visit -- Changes made by the user introducing new features - -When the data enters from Overpass or from the OSM-API, they are first distributed per layer: - -OVERPASS | ---PerLayerFeatureSource---> FeatureSourceForLayer[] -OSM | - -The GeoJSon files (not tiled) are then added to this list - -A single FeatureSourcePerLayer is then further handled by splitting it into a tile hierarchy. - -In order to keep thins snappy, they are distributed over a tiled database per layer. - -## Notes - -`cached-featuresbookcases` is the old key used `cahced-features{themeid}` and should be cleaned up \ No newline at end of file diff --git a/Logic/FeatureSource/TiledFeatureSource/TileHierarchy.ts b/Logic/FeatureSource/TiledFeatureSource/TileHierarchy.ts deleted file mode 100644 index 93d883c7e..000000000 --- a/Logic/FeatureSource/TiledFeatureSource/TileHierarchy.ts +++ /dev/null @@ -1,24 +0,0 @@ -import FeatureSource, { Tiled } from "../FeatureSource" -import { BBox } from "../../BBox" - -export default interface TileHierarchy { - /** - * A mapping from 'tile_index' to the actual tile featrues - */ - loadedTiles: Map -} - -export class TileHierarchyTools { - public static getTiles( - hierarchy: TileHierarchy, - bbox: BBox - ): T[] { - const result: T[] = [] - hierarchy.loadedTiles.forEach((tile) => { - if (tile.bbox.overlapsWith(bbox)) { - result.push(tile) - } - }) - return result - } -} diff --git a/Logic/FeatureSource/TiledFeatureSource/TileHierarchyMerger.ts b/Logic/FeatureSource/TiledFeatureSource/TileHierarchyMerger.ts deleted file mode 100644 index b4de5333d..000000000 --- a/Logic/FeatureSource/TiledFeatureSource/TileHierarchyMerger.ts +++ /dev/null @@ -1,58 +0,0 @@ -import TileHierarchy from "./TileHierarchy" -import { UIEventSource } from "../../UIEventSource" -import FeatureSource, { FeatureSourceForLayer, IndexedFeatureSource, Tiled } from "../FeatureSource" -import FilteredLayer from "../../../Models/FilteredLayer" -import FeatureSourceMerger from "../Sources/FeatureSourceMerger" -import { Tiles } from "../../../Models/TileRange" -import { BBox } from "../../BBox" - -export class TileHierarchyMerger implements TileHierarchy { - public readonly loadedTiles: Map = new Map< - number, - FeatureSourceForLayer & Tiled - >() - public readonly layer: FilteredLayer - private readonly sources: Map> = new Map< - number, - UIEventSource - >() - private _handleTile: (src: FeatureSourceForLayer & IndexedFeatureSource, index: number) => void - - constructor( - layer: FilteredLayer, - handleTile: ( - src: FeatureSourceForLayer & IndexedFeatureSource & Tiled, - index: number - ) => void - ) { - this.layer = layer - this._handleTile = handleTile - } - - /** - * Add another feature source for the given tile. - * Entries for this tile will be merged - * @param src - */ - public registerTile(src: FeatureSource & Tiled) { - const index = src.tileIndex - if (this.sources.has(index)) { - const sources = this.sources.get(index) - sources.data.push(src) - sources.ping() - return - } - - // We have to setup - const sources = new UIEventSource([src]) - this.sources.set(index, sources) - const merger = new FeatureSourceMerger( - this.layer, - index, - BBox.fromTile(...Tiles.tile_from_index(index)), - sources - ) - this.loadedTiles.set(index, merger) - this._handleTile(merger, index) - } -} diff --git a/Logic/FeatureSource/TiledFeatureSource/TiledFeatureSource.ts b/Logic/FeatureSource/TiledFeatureSource/TiledFeatureSource.ts deleted file mode 100644 index 9327ec706..000000000 --- a/Logic/FeatureSource/TiledFeatureSource/TiledFeatureSource.ts +++ /dev/null @@ -1,248 +0,0 @@ -import FeatureSource, { FeatureSourceForLayer, IndexedFeatureSource, Tiled } from "../FeatureSource" -import { Store, UIEventSource } from "../../UIEventSource" -import FilteredLayer from "../../../Models/FilteredLayer" -import TileHierarchy from "./TileHierarchy" -import { Tiles } from "../../../Models/TileRange" -import { BBox } from "../../BBox" - -/** - * Contains all features in a tiled fashion. - * The data will be automatically broken down into subtiles when there are too much features in a single tile or if the zoomlevel is too high - */ -export default class TiledFeatureSource - implements - Tiled, - IndexedFeatureSource, - FeatureSourceForLayer, - TileHierarchy -{ - public readonly z: number - public readonly x: number - public readonly y: number - public readonly parent: TiledFeatureSource - public readonly root: TiledFeatureSource - public readonly layer: FilteredLayer - /* An index of all known tiles. allTiles[z][x][y].get('layerid') will yield the corresponding tile. - * Only defined on the root element! - */ - public readonly loadedTiles: Map = undefined - - public readonly maxFeatureCount: number - public readonly name - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> - public readonly containedIds: Store> - - public readonly bbox: BBox - public readonly tileIndex: number - private upper_left: TiledFeatureSource - private upper_right: TiledFeatureSource - private lower_left: TiledFeatureSource - private lower_right: TiledFeatureSource - private readonly maxzoom: number - private readonly options: TiledFeatureSourceOptions - - private constructor( - z: number, - x: number, - y: number, - parent: TiledFeatureSource, - options?: TiledFeatureSourceOptions - ) { - this.z = z - this.x = x - this.y = y - this.bbox = BBox.fromTile(z, x, y) - this.tileIndex = Tiles.tile_index(z, x, y) - this.name = `TiledFeatureSource(${z},${x},${y})` - this.parent = parent - this.layer = options.layer - options = options ?? {} - this.maxFeatureCount = options?.maxFeatureCount ?? 250 - this.maxzoom = options.maxZoomLevel ?? 18 - this.options = options - if (parent === undefined) { - throw "Parent is not allowed to be undefined. Use null instead" - } - if (parent === null && z !== 0 && x !== 0 && y !== 0) { - throw "Invalid root tile: z, x and y should all be null" - } - if (parent === null) { - this.root = this - this.loadedTiles = new Map() - } else { - this.root = this.parent.root - this.loadedTiles = this.root.loadedTiles - const i = Tiles.tile_index(z, x, y) - this.root.loadedTiles.set(i, this) - } - this.features = new UIEventSource([]) - this.containedIds = this.features.map((features) => { - if (features === undefined) { - return undefined - } - return new Set(features.map((f) => f.feature.properties.id)) - }) - - // We register this tile, but only when there is some data in it - if (this.options.registerTile !== undefined) { - this.features.addCallbackAndRunD((features) => { - if (features.length === 0) { - return - } - this.options.registerTile(this) - return true - }) - } - } - - public static createHierarchy( - features: FeatureSource, - options?: TiledFeatureSourceOptions - ): TiledFeatureSource { - options = { - ...options, - layer: features["layer"] ?? options.layer, - } - const root = new TiledFeatureSource(0, 0, 0, null, options) - features.features?.addCallbackAndRunD((feats) => root.addFeatures(feats)) - return root - } - - private isSplitNeeded(featureCount: number) { - if (this.upper_left !== undefined) { - // This tile has been split previously, so we keep on splitting - return true - } - if (this.z >= this.maxzoom) { - // We are not allowed to split any further - return false - } - if (this.options.minZoomLevel !== undefined && this.z < this.options.minZoomLevel) { - // We must have at least this zoom level before we are allowed to start splitting - return true - } - - // To much features - we split - return featureCount > this.maxFeatureCount - } - - /*** - * Adds the list of features to this hierarchy. - * If there are too much features, the list will be broken down and distributed over the subtiles (only retaining features that don't fit a subtile on this level) - * @param features - * @private - */ - private addFeatures(features: { feature: any; freshness: Date }[]) { - if (features === undefined || features.length === 0) { - return - } - - if (!this.isSplitNeeded(features.length)) { - this.features.setData(features) - return - } - - if (this.upper_left === undefined) { - this.upper_left = new TiledFeatureSource( - this.z + 1, - this.x * 2, - this.y * 2, - this, - this.options - ) - this.upper_right = new TiledFeatureSource( - this.z + 1, - this.x * 2 + 1, - this.y * 2, - this, - this.options - ) - this.lower_left = new TiledFeatureSource( - this.z + 1, - this.x * 2, - this.y * 2 + 1, - this, - this.options - ) - this.lower_right = new TiledFeatureSource( - this.z + 1, - this.x * 2 + 1, - this.y * 2 + 1, - this, - this.options - ) - } - - const ulf = [] - const urf = [] - const llf = [] - const lrf = [] - const overlapsboundary = [] - - for (const feature of features) { - const bbox = BBox.get(feature.feature) - - // There are a few strategies to deal with features that cross tile boundaries - - if (this.options.noDuplicates) { - // Strategy 1: We put the feature into a somewhat matching tile - if (bbox.overlapsWith(this.upper_left.bbox)) { - ulf.push(feature) - } else if (bbox.overlapsWith(this.upper_right.bbox)) { - urf.push(feature) - } else if (bbox.overlapsWith(this.lower_left.bbox)) { - llf.push(feature) - } else if (bbox.overlapsWith(this.lower_right.bbox)) { - lrf.push(feature) - } else { - overlapsboundary.push(feature) - } - } else if (this.options.minZoomLevel === undefined) { - // Strategy 2: put it into a strictly matching tile (or in this tile, which is slightly too big) - if (bbox.isContainedIn(this.upper_left.bbox)) { - ulf.push(feature) - } else if (bbox.isContainedIn(this.upper_right.bbox)) { - urf.push(feature) - } else if (bbox.isContainedIn(this.lower_left.bbox)) { - llf.push(feature) - } else if (bbox.isContainedIn(this.lower_right.bbox)) { - lrf.push(feature) - } else { - overlapsboundary.push(feature) - } - } else { - // Strategy 3: We duplicate a feature on a boundary into every tile as we need to get to the minZoomLevel - if (bbox.overlapsWith(this.upper_left.bbox)) { - ulf.push(feature) - } - if (bbox.overlapsWith(this.upper_right.bbox)) { - urf.push(feature) - } - if (bbox.overlapsWith(this.lower_left.bbox)) { - llf.push(feature) - } - if (bbox.overlapsWith(this.lower_right.bbox)) { - lrf.push(feature) - } - } - } - this.upper_left.addFeatures(ulf) - this.upper_right.addFeatures(urf) - this.lower_left.addFeatures(llf) - this.lower_right.addFeatures(lrf) - this.features.setData(overlapsboundary) - } -} - -export interface TiledFeatureSourceOptions { - readonly maxFeatureCount?: number - readonly maxZoomLevel?: number - readonly minZoomLevel?: number - /** - * IF minZoomLevel is set, and if a feature runs through a tile boundary, it would normally be duplicated. - * Setting 'dontEnforceMinZoomLevel' will assign to feature to some matching subtile. - */ - readonly noDuplicates?: boolean - readonly registerTile?: (tile: TiledFeatureSource & FeatureSourceForLayer & Tiled) => void - readonly layer?: FilteredLayer -} diff --git a/Logic/GeoOperations.ts b/Logic/GeoOperations.ts index 2ceb9b2d4..250e75182 100644 --- a/Logic/GeoOperations.ts +++ b/Logic/GeoOperations.ts @@ -1,27 +1,35 @@ import { BBox } from "./BBox" -import LayerConfig from "../Models/ThemeConfig/LayerConfig" import * as turf from "@turf/turf" +import { AllGeoJSON, booleanWithin, Coord } from "@turf/turf" import { - AllGeoJSON, - booleanWithin, - Coord, Feature, + FeatureCollection, + GeoJSON, Geometry, + LineString, + MultiLineString, MultiPolygon, + Point, Polygon, -} from "@turf/turf" -import { GeoJSON, LineString, Point, Position } from "geojson" -import togpx from "togpx" -import Constants from "../Models/Constants" + Position, +} from "geojson" +import { Tiles } from "../Models/TileRange" +import { Utils } from "../Utils" export class GeoOperations { + private static readonly _earthRadius = 6378137 + private static readonly _originShift = (2 * Math.PI * GeoOperations._earthRadius) / 2 + /** * Create a union between two features */ - static union = turf.union - static intersect = turf.intersect - private static readonly _earthRadius = 6378137 - private static readonly _originShift = (2 * Math.PI * GeoOperations._earthRadius) / 2 + public static union(f0: Feature, f1: Feature): Feature | null { + return turf.union(f0, f1) + } + + public static intersect(f0: Feature, f1: Feature): Feature | null { + return turf.intersect(f0, f1) + } static surfaceAreaInSqMeters(feature: any) { return turf.area(feature) @@ -234,7 +242,7 @@ export class GeoOperations { }) } - static bbox(feature: any): Feature { + static bbox(feature: Feature | FeatureCollection): Feature { const [lon, lat, lon0, lat0] = turf.bbox(feature) return { type: "Feature", @@ -263,15 +271,47 @@ export class GeoOperations { * @param way The road on which you want to find a point * @param point Point defined as [lon, lat] */ - public static nearestPoint(way: Feature, point: [number, number]) { + public static nearestPoint( + way: Feature, + point: [number, number] + ): Feature< + Point, + { + index: number + dist: number + location: number + } + > { + return ( + turf.nearestPointOnLine(>way, point, { units: "kilometers" }) + ) + } + + /** + * Helper method to reuse the coordinates of the way as LineString. + * Mostly used as helper for 'nearestPoint' + * @param way + */ + public static forceLineString(way: Feature): Feature + public static forceLineString( + way: Feature + ): Feature + public static forceLineString( + way: Feature + ): Feature { if (way.geometry.type === "Polygon") { way = { ...way } way.geometry = { ...way.geometry } way.geometry.type = "LineString" way.geometry.coordinates = (way.geometry).coordinates[0] + } else if (way.geometry.type === "MultiPolygon") { + way = { ...way } + way.geometry = { ...way.geometry } + way.geometry.type = "MultiLineString" + way.geometry.coordinates = (way.geometry).coordinates[0] } - return turf.nearestPointOnLine(>way, point, { units: "kilometers" }) + return way } public static toCSV(features: any[]): string { @@ -368,36 +408,87 @@ export class GeoOperations { /** * Calculates line intersection between two features. */ - public static LineIntersections(feature, otherFeature): [number, number][] { + public static LineIntersections(feature: Feature, otherFeature: Feature): [number, number][] { return turf .lineIntersect(feature, otherFeature) .features.map((p) => <[number, number]>p.geometry.coordinates) } - public static AsGpx( - feature: Feature, - options?: { layer?: LayerConfig; gpxMetadata?: any } - ): string { - const metadata = options?.gpxMetadata ?? {} - metadata["time"] = metadata["time"] ?? new Date().toISOString() - const tags = feature.properties + /** + * Given a list of features, will construct a map of slippy map tile-indices. + * Features of which the BBOX overlaps with the corresponding slippy map tile are added to the corresponding array + * @param features + * @param zoomlevel + */ + public static spreadIntoBboxes(features: Feature[], zoomlevel: number) : Map { - if (options?.layer !== undefined) { - metadata["name"] = options?.layer.title?.GetRenderValue(tags)?.Subs(tags)?.txt - metadata["desc"] = "Generated with MapComplete layer " + options?.layer.id - if (tags._backend?.contains("openstreetmap")) { - metadata["copyright"] = - "Data copyrighted by OpenStreetMap-contributors, freely available under ODbL. See https://www.openstreetmap.org/copyright" - metadata["author"] = tags["_last_edit:contributor"] - metadata["link"] = "https://www.openstreetmap.org/" + tags.id - metadata["time"] = tags["_last_edit:timestamp"] - } + const perBbox = new Map() + + for (const feature of features) { + const bbox = BBox.get(feature) + const tilerange = bbox.expandToTileBounds(zoomlevel).containingTileRange(zoomlevel) + Tiles.MapRange(tilerange, (x, y) => { + const tileNumber = Tiles.tile_index(zoomlevel, x, y) + let newFeatureList = perBbox.get(tileNumber) + if(newFeatureList === undefined){ + newFeatureList = [] + perBbox.set(tileNumber, newFeatureList) + } + newFeatureList.push(feature) + }) } - return togpx(feature, { - creator: "MapComplete " + Constants.vNumber, - metadata, - }) + return perBbox + } + public static toGpx( + locations: + | Feature + | Feature[], + title?: string + ) { + title = title?.trim() + if (title === undefined || title === "") { + title = "Uploaded with MapComplete" + } + title = Utils.EncodeXmlValue(title) + const trackPoints: string[] = [] + let locationsWithMeta: Feature[] + if (Array.isArray(locations)) { + locationsWithMeta = locations + } else { + locationsWithMeta = locations.geometry.coordinates.map( + (p) => + >{ + type: "Feature", + properties: {}, + geometry: { + type: "Point", + coordinates: p, + }, + } + ) + } + for (const l of locationsWithMeta) { + let trkpt = ` ` + if (l.properties.date) { + trkpt += ` ` + } + if (l.properties.altitude) { + trkpt += ` ${l.properties.altitude}` + } + trkpt += " " + trackPoints.push(trkpt) + } + const header = + '' + return ( + header + + "\n" + + title + + "\n\n" + + trackPoints.join("\n") + + "\n" + ) } public static IdentifieCommonSegments(coordinatess: [number, number][][]): { @@ -610,6 +701,20 @@ export class GeoOperations { return turf.bearing(a, b) } + public static along(a: Coord, b: Coord, distanceMeter: number): Coord { + return turf.along( + { + type:"Feature", + geometry:{ + type:"LineString", + coordinates: [a, b] + } + }, distanceMeter, {units: "meters"} + + ).geometry.coordinates + } + + /** * Returns 'true' if one feature contains the other feature * @@ -641,14 +746,14 @@ export class GeoOperations { */ static completelyWithin( feature: Feature, - possiblyEncloingFeature: Feature + possiblyEnclosingFeature: Feature ): boolean { - return booleanWithin(feature, possiblyEncloingFeature) + return booleanWithin(feature, possiblyEnclosingFeature) } /** * Create an intersection between two features. - * A new feature is returned based on 'toSplit', which'll have a geometry that is completely withing boundary + * One or multiple new feature is returned based on 'toSplit', which'll have a geometry that is completely withing boundary */ public static clipWith(toSplit: Feature, boundary: Feature): Feature[] { if (toSplit.geometry.type === "Point") { @@ -681,6 +786,115 @@ export class GeoOperations { throw "Invalid geometry type with GeoOperations.clipWith: " + toSplit.geometry.type } + /** + * + * + * const f = (type, feature: Feature) => GeoOperations.featureToCoordinateWithRenderingType(feature, type) + * const g = geometry => ( {type: "Feature", properties: {}, geometry}) + * f("point", g({type:"Point", coordinates:[1,2]})) // => [1,2] + * f("centroid", g({type:"Point", coordinates:[1,2]})) // => undefined + * f("start", g({type:"Point", coordinates:[1,2]})) // => undefined + * f("centroid", g({type:"LineString", coordinates:[[1,2], [3,4]]})) // => [2,3] + * f("centroid", g({type:"Polygon", coordinates:[[[1,2], [3,4], [1,2]]]})) // => [2,3] + * f("projected_centerpoint", g({type:"LineString", coordinates:[[1,2], [3,4]]})) // => [1.9993137596003214,2.999313759600321] + * f("start", g({type:"LineString", coordinates:[[1,2], [3,4]]})) // => [1,2] + * f("end", g({type:"LineString", coordinates:[[1,2], [3,4]]})) // => [3,4] + * + */ + public static featureToCoordinateWithRenderingType( + feature: Feature, + location: "point" | "centroid" | "start" | "end" | "projected_centerpoint" | string + ): [number, number] | undefined { + switch (location) { + case "point": + if (feature.geometry.type === "Point") { + return <[number, number]>feature.geometry.coordinates + } + return undefined + case "centroid": + if (feature.geometry.type === "Point") { + return undefined + } + return GeoOperations.centerpointCoordinates(feature) + case "projected_centerpoint": + if ( + feature.geometry.type === "LineString" || + feature.geometry.type === "MultiLineString" + ) { + const centerpoint = GeoOperations.centerpointCoordinates(feature) + const projected = GeoOperations.nearestPoint( + >feature, + centerpoint + ) + return <[number, number]>projected.geometry.coordinates + } + return undefined + case "start": + if (feature.geometry.type === "LineString") { + return <[number, number]>feature.geometry.coordinates[0] + } + return undefined + case "end": + if (feature.geometry.type === "LineString") { + return <[number, number]>feature.geometry.coordinates.at(-1) + } + return undefined + default: + throw "Unkown location type: " + location + } + } + + /** + * Constructs all tiles where features overlap with and puts those features in them. + * Long features (e.g. lines or polygons) which overlap with multiple tiles are referenced in each tile they overlap with + * @param zoomlevel + * @param features + */ + public static slice(zoomlevel: number, features: Feature[]): Map { + const tiles = new Map() + + for (const feature of features) { + const bbox = BBox.get(feature) + Tiles.MapRange(Tiles.tileRangeFrom(bbox, zoomlevel), (x, y) => { + const i = Tiles.tile_index(zoomlevel, x, y) + + let tiledata = tiles.get(i) + if (tiledata === undefined) { + tiledata = [] + tiles.set(i, tiledata) + } + tiledata.push(feature) + }) + } + + return tiles + } + + /** + * Creates a linestring object based on the outer ring of the given polygon + * + * Returns the argument if not a polygon + * @param p + */ + public static outerRing

(p: Feature): Feature { + if (p.geometry.type !== "Polygon") { + return >p + } + return { + type: "Feature", + properties: p.properties, + geometry: { + type: "LineString", + coordinates: p.geometry.coordinates[0], + }, + } + } + + static centerpointCoordinatesObj(geojson: Feature) { + const [lon, lat] = GeoOperations.centerpointCoordinates(geojson) + return { lon, lat } + } + /** * Helper function which does the heavy lifting for 'inside' */ diff --git a/Logic/ImageProviders/AllImageProviders.ts b/Logic/ImageProviders/AllImageProviders.ts index 770da2fbf..6daabfa60 100644 --- a/Logic/ImageProviders/AllImageProviders.ts +++ b/Logic/ImageProviders/AllImageProviders.ts @@ -1,10 +1,10 @@ -import { Mapillary } from "./Mapillary" -import { WikimediaImageProvider } from "./WikimediaImageProvider" -import { Imgur } from "./Imgur" -import GenericImageProvider from "./GenericImageProvider" -import { Store, UIEventSource } from "../UIEventSource" -import ImageProvider, { ProvidedImage } from "./ImageProvider" -import { WikidataImageProvider } from "./WikidataImageProvider" +import { Mapillary } from "./Mapillary"; +import { WikimediaImageProvider } from "./WikimediaImageProvider"; +import { Imgur } from "./Imgur"; +import GenericImageProvider from "./GenericImageProvider"; +import { Store, UIEventSource } from "../UIEventSource"; +import ImageProvider, { ProvidedImage } from "./ImageProvider"; +import { WikidataImageProvider } from "./WikidataImageProvider"; /** * A generic 'from the interwebz' image picker, without attribution @@ -44,7 +44,7 @@ export default class AllImageProviders { UIEventSource >() - public static LoadImagesFor(tags: Store, tagKey?: string[]): Store { + public static LoadImagesFor(tags: Store>, tagKey?: string[]): Store { if (tags.data.id === undefined) { return undefined } diff --git a/Logic/ImageProviders/WikidataImageProvider.ts b/Logic/ImageProviders/WikidataImageProvider.ts index 093153ab5..043fee4b7 100644 --- a/Logic/ImageProviders/WikidataImageProvider.ts +++ b/Logic/ImageProviders/WikidataImageProvider.ts @@ -12,8 +12,8 @@ export class WikidataImageProvider extends ImageProvider { super() } - public SourceIcon(backlinkSource?: string): BaseUIElement { - throw Svg.wikidata_svg() + public SourceIcon(_?: string): BaseUIElement { + return Svg.wikidata_svg() } public async ExtractUrls(key: string, value: string): Promise[]> { @@ -48,7 +48,7 @@ export class WikidataImageProvider extends ImageProvider { return allImages } - public DownloadAttribution(url: string): Promise { + public DownloadAttribution(_: string): Promise { throw new Error("Method not implemented; shouldn't be needed!") } } diff --git a/Logic/ImageProviders/WikimediaImageProvider.ts b/Logic/ImageProviders/WikimediaImageProvider.ts index 5d6dbbdbd..f9f40261d 100644 --- a/Logic/ImageProviders/WikimediaImageProvider.ts +++ b/Logic/ImageProviders/WikimediaImageProvider.ts @@ -73,14 +73,13 @@ export class WikimediaImageProvider extends ImageProvider { } return new Link( - Svg.wikimedia_commons_white_img, + Svg.wikimedia_commons_white_svg(), `https://commons.wikimedia.org/wiki/${backlink}`, true ) } public PrepUrl(value: string): ProvidedImage { - const hasCommonsPrefix = WikimediaImageProvider.startsWithCommonsPrefix(value) value = WikimediaImageProvider.removeCommonsPrefix(value) if (value.startsWith("File:")) { diff --git a/Logic/Maproulette.ts b/Logic/Maproulette.ts index 15e11ccba..161fc9b9d 100644 --- a/Logic/Maproulette.ts +++ b/Logic/Maproulette.ts @@ -29,8 +29,9 @@ export default class Maproulette { /** * The API key to use for all requests */ - private apiKey: string + private readonly apiKey: string + public static singleton = new Maproulette() /** * Creates a new Maproulette instance * @param endpoint The API endpoint to use @@ -71,4 +72,23 @@ export default class Maproulette { throw `Failed to close task: ${response.status}` } } + + /** + * Converts a status text into the corresponding number + * + * Maproulette.codeToIndex("Created") // => 0 + * Maproulette.codeToIndex("qdsf") // => undefined + * + */ + public static codeToIndex(code: string) : number | undefined{ + if(code === "Created"){ + return Maproulette.STATUS_OPEN + } + for (let i = 0; i < 9; i++) { + if(Maproulette.STATUS_MEANING[""+i] === code){ + return i + } + } + return undefined + } } diff --git a/Logic/MetaTagging.ts b/Logic/MetaTagging.ts index 47d698ac0..0e0129b9b 100644 --- a/Logic/MetaTagging.ts +++ b/Logic/MetaTagging.ts @@ -1,7 +1,14 @@ -import SimpleMetaTaggers, { SimpleMetaTagger } from "./SimpleMetaTagger" -import { ExtraFuncParams, ExtraFunctions } from "./ExtraFunctions" +import SimpleMetaTaggers, {MetataggingState, SimpleMetaTagger} from "./SimpleMetaTagger" +import {ExtraFuncParams, ExtraFunctions, ExtraFuncType} from "./ExtraFunctions" import LayerConfig from "../Models/ThemeConfig/LayerConfig" -import { ElementStorage } from "./ElementStorage" +import {Feature} from "geojson" +import FeaturePropertiesStore from "./FeatureSource/Actors/FeaturePropertiesStore" +import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import {GeoIndexedStoreForLayer} from "./FeatureSource/Actors/GeoIndexedStore" +import {IndexedFeatureSource} from "./FeatureSource/FeatureSource" +import OsmObjectDownloader from "./Osm/OsmObjectDownloader" +import {Utils} from "../Utils"; +import {UIEventSource} from "./UIEventSource"; /** * Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ... @@ -11,19 +18,58 @@ import { ElementStorage } from "./ElementStorage" export default class MetaTagging { private static errorPrintCount = 0 private static readonly stopErrorOutputAt = 10 - private static retaggingFuncCache = new Map void)[]>() + private static retaggingFuncCache = new Map) => void)[]>() + + constructor(state: { + layout: LayoutConfig + osmObjectDownloader: OsmObjectDownloader + perLayer: ReadonlyMap + indexedFeatures: IndexedFeatureSource + featureProperties: FeaturePropertiesStore + }) { + const params = MetaTagging.createExtraFuncParams(state) + for (const layer of state.layout.layers) { + if (layer.source === null) { + continue + } + const featureSource = state.perLayer.get(layer.id) + featureSource.features?.stabilized(1000)?.addCallbackAndRunD((features) => { + if (!(features?.length > 0)) { + // No features to handle + return + } + console.debug( + "Recalculating metatags for layer ", + layer.id, + "due to a change in the upstream features. Contains ", + features.length, + "items" + ) + MetaTagging.addMetatags( + features, + params, + layer, + state.layout, + state.osmObjectDownloader, + state.featureProperties + ) + }) + } + } /** - * This method (re)calculates all metatags and calculated tags on every given object. + * This method (re)calculates all metatags and calculated tags on every given feature. * The given features should be part of the given layer * * Returns true if at least one feature has changed properties */ public static addMetatags( - features: { feature: any; freshness: Date }[], + features: Feature[], params: ExtraFuncParams, layer: LayerConfig, - state?: { allElements?: ElementStorage }, + layout: LayoutConfig, + osmObjectDownloader: OsmObjectDownloader, + featurePropertiesStores?: FeaturePropertiesStore, options?: { includeDates?: true | boolean includeNonDates?: true | boolean @@ -34,7 +80,6 @@ export default class MetaTagging { return } - console.log("Recalculating metatags...") const metatagsToApply: SimpleMetaTagger[] = [] for (const metatag of SimpleMetaTaggers.metatags) { if (metatag.includesDates) { @@ -49,20 +94,23 @@ export default class MetaTagging { } // The calculated functions - per layer - which add the new keys - const layerFuncs = this.createRetaggingFunc(layer, state) + // Calculated functions are defined by the layer + const layerFuncs = this.createRetaggingFunc(layer, ExtraFunctions.constructHelpers(params)) + const state: MetataggingState = {layout, osmObjectDownloader} let atLeastOneFeatureChanged = false - + let strictlyEvaluated = 0 for (let i = 0; i < features.length; i++) { - const ff = features[i] - const feature = ff.feature - const freshness = ff.freshness + const feature = features[i] + const tags = featurePropertiesStores?.getStore(feature.properties.id) let somethingChanged = false let definedTags = new Set(Object.getOwnPropertyNames(feature.properties)) + for (const metatag of metatagsToApply) { try { - if (!metatag.keys.some((key) => feature.properties[key] === undefined)) { + if (!metatag.keys.some((key) => !(key in feature.properties))) { // All keys are already defined, we probably already ran this one + // Note that we use 'key in properties', not 'properties[key] === undefined'. The latter will cause evaluation of lazy properties continue } @@ -72,17 +120,20 @@ export default class MetaTagging { continue } somethingChanged = true - metatag.applyMetaTagsOnFeature(feature, freshness, layer, state) + metatag.applyMetaTagsOnFeature(feature, layer, tags, state) if (options?.evaluateStrict) { for (const key of metatag.keys) { - feature.properties[key] + const evaluated = feature.properties[key] + if (evaluated !== undefined) { + strictlyEvaluated++ + } } } } else { const newValueAdded = metatag.applyMetaTagsOnFeature( feature, - freshness, layer, + tags, state ) /* Note that the expression: @@ -104,135 +155,142 @@ export default class MetaTagging { ) } } - if (layerFuncs !== undefined) { - let retaggingChanged = false try { - retaggingChanged = layerFuncs(params, feature) + // We cannot do `somethingChanged || layerFuncs(feature)', due to the shortcutting behaviour it would not calculate the lazy functions + somethingChanged = layerFuncs(feature, tags) || somethingChanged } catch (e) { console.error(e) } - somethingChanged = somethingChanged || retaggingChanged } if (somethingChanged) { - state?.allElements?.getEventSourceById(feature.properties.id)?.ping() + try { + tags?.ping() + } catch (e) { + console.error("Could not ping a store for a changed property due to", e) + } atLeastOneFeatureChanged = true } } return atLeastOneFeatureChanged } - private static createFunctionsForFeature( - layerId: string, - calculatedTags: [string, string, boolean][] - ): ((feature: any) => void)[] { - const functions: ((feature: any) => any)[] = [] - for (const entry of calculatedTags) { - const key = entry[0] - const code = entry[1] - const isStrict = entry[2] - if (code === undefined) { - continue - } - - const calculateAndAssign: (feat: any) => any = (feat) => { - try { - let result = new Function("feat", "return " + code + ";")(feat) - if (result === "") { - result === undefined - } - if (result !== undefined && typeof result !== "string") { - // Make sure it is a string! - result = JSON.stringify(result) - } - delete feat.properties[key] - feat.properties[key] = result - return result - } catch (e) { - if (MetaTagging.errorPrintCount < MetaTagging.stopErrorOutputAt) { - console.warn( - "Could not calculate a " + - (isStrict ? "strict " : "") + - " calculated tag for key " + - key + - " defined by " + - code + - " (in layer" + - layerId + - ") due to \n" + - e + - "\n. Are you the theme creator? Doublecheck your code. Note that the metatags might not be stable on new features", - e, - e.stack - ) - MetaTagging.errorPrintCount++ - if (MetaTagging.errorPrintCount == MetaTagging.stopErrorOutputAt) { - console.error( - "Got ", - MetaTagging.stopErrorOutputAt, - " errors calculating this metatagging - stopping output now" - ) - } - } - return undefined + public static createExtraFuncParams(state: { + indexedFeatures: IndexedFeatureSource, + perLayer: ReadonlyMap + }) { + return { + getFeatureById: (id) => state.indexedFeatures.featuresById.data.get(id), + getFeaturesWithin: (layerId, bbox) => { + if (layerId === '*' || layerId === null || layerId === undefined) { + const feats: Feature[][] = [] + state.perLayer.forEach((layer) => { + feats.push(layer.GetFeaturesWithin(bbox)) + }) + return feats } - } + return [state.perLayer.get(layerId).GetFeaturesWithin(bbox)]; + }, + } + } - if (isStrict) { - functions.push(calculateAndAssign) - continue - } + /** + * Creates a function that implements that calculates a property and adds this property onto the feature properties + * @param specification + * @param helperFunctions + * @param layerId + * @private + */ + private static createFunctionForFeature([key, code, isStrict]: [string, string, boolean], + helperFunctions: Record Function>, + layerId: string = "unkown layer" + ): ((feature: Feature, propertiesStore?: UIEventSource) => void) | undefined { + if (code === undefined) { + return undefined + } - // Lazy function - const f = (feature: any) => { - delete feature.properties[key] - Object.defineProperty(feature.properties, key, { - configurable: true, - enumerable: false, // By setting this as not enumerable, the localTileSaver will _not_ calculate this - get: function () { - return calculateAndAssign(feature) - }, - }) + + const calculateAndAssign: ((feat: Feature, store?: UIEventSource) => string | any) = (feat, store) => { + try { + let result = new Function("feat", "{" + ExtraFunctions.types.join(", ") + "}", "return " + code + ";")(feat, helperFunctions) + if (result === "") { + result = undefined + } + const oldValue= feat.properties[key] + if(oldValue == result){ + return oldValue + } + delete feat.properties[key] + feat.properties[key] = result + store?.ping() + return result + } catch (e) { + if (MetaTagging.errorPrintCount < MetaTagging.stopErrorOutputAt) { + console.warn( + "Could not calculate a " + + (isStrict ? "strict " : "") + + " calculated tag for key " + + key + + " defined by " + + code + + " (in layer" + + layerId + + ") due to \n" + + e + + "\n. Are you the theme creator? Doublecheck your code. Note that the metatags might not be stable on new features", + e, + e.stack + ) + MetaTagging.errorPrintCount++ + if (MetaTagging.errorPrintCount == MetaTagging.stopErrorOutputAt) { + console.error( + "Got ", + MetaTagging.stopErrorOutputAt, + " errors calculating this metatagging - stopping output now" + ) + } + } return undefined } - - functions.push(f) } - return functions + + if (isStrict) { + return calculateAndAssign + } + return (feature: Feature, store?: UIEventSource) => { + delete feature.properties[key] + Utils.AddLazyProperty(feature.properties, key, () => calculateAndAssign(feature, store)) + } } /** * Creates the function which adds all the calculated tags to a feature. Called once per layer - * @param layer - * @param state - * @private */ private static createRetaggingFunc( layer: LayerConfig, - state - ): (params: ExtraFuncParams, feature: any) => boolean { + helpers: Record Function> + ): (feature: Feature, tags: UIEventSource>) => boolean { const calculatedTags: [string, string, boolean][] = layer.calculatedTags if (calculatedTags === undefined || calculatedTags.length === 0) { return undefined } - let functions: ((feature: any) => void)[] = MetaTagging.retaggingFuncCache.get(layer.id) + let functions: ((feature: Feature, propertiesStore?: UIEventSource) => void)[] = MetaTagging.retaggingFuncCache.get(layer.id) if (functions === undefined) { - functions = MetaTagging.createFunctionsForFeature(layer.id, calculatedTags) + functions = calculatedTags.map(spec => this.createFunctionForFeature(spec, helpers, layer.id)) MetaTagging.retaggingFuncCache.set(layer.id, functions) } - return (params: ExtraFuncParams, feature) => { + return (feature: Feature, store: UIEventSource>) => { const tags = feature.properties if (tags === undefined) { return } try { - ExtraFunctions.FullPatchFeature(params, feature) for (const f of functions) { - f(feature) + f(feature, store) } } catch (e) { console.error("Invalid syntax in calculated tags or some other error: ", e) diff --git a/Logic/Osm/Actions/ChangeLocationAction.ts b/Logic/Osm/Actions/ChangeLocationAction.ts index 0ec12bc7b..e5d2b8486 100644 --- a/Logic/Osm/Actions/ChangeLocationAction.ts +++ b/Logic/Osm/Actions/ChangeLocationAction.ts @@ -1,6 +1,5 @@ import { ChangeDescription } from "./ChangeDescription" import OsmChangeAction from "./OsmChangeAction" -import { Changes } from "../Changes" export default class ChangeLocationAction extends OsmChangeAction { private readonly _id: number @@ -24,7 +23,7 @@ export default class ChangeLocationAction extends OsmChangeAction { this._meta = meta } - protected async CreateChangeDescriptions(changes: Changes): Promise { + protected async CreateChangeDescriptions(): Promise { const d: ChangeDescription = { changes: { lat: this._newLonLat[1], diff --git a/Logic/Osm/Actions/ChangeTagAction.ts b/Logic/Osm/Actions/ChangeTagAction.ts index 63d8c2320..1abfb6798 100644 --- a/Logic/Osm/Actions/ChangeTagAction.ts +++ b/Logic/Osm/Actions/ChangeTagAction.ts @@ -1,5 +1,4 @@ import OsmChangeAction from "./OsmChangeAction" -import { Changes } from "../Changes" import { ChangeDescription } from "./ChangeDescription" import { TagsFilter } from "../../Tags/TagsFilter" import { OsmTags } from "../../../Models/OsmFeature" @@ -71,7 +70,7 @@ export default class ChangeTagAction extends OsmChangeAction { return { k: key.trim(), v: value.trim() } } - async CreateChangeDescriptions(changes: Changes): Promise { + async CreateChangeDescriptions(): Promise { const changedTags: { k: string; v: string }[] = this._tagsFilter .asChange(this._currentTags) .map(ChangeTagAction.checkChange) diff --git a/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts b/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts index e7e625fd2..1cf3dd369 100644 --- a/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts +++ b/Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction.ts @@ -1,18 +1,20 @@ -import { OsmCreateAction } from "./OsmChangeAction" -import { Tag } from "../../Tags/Tag" -import { Changes } from "../Changes" -import { ChangeDescription } from "./ChangeDescription" -import FeaturePipelineState from "../../State/FeaturePipelineState" -import FeatureSource from "../../FeatureSource/FeatureSource" +import {OsmCreateAction, PreviewableAction} from "./OsmChangeAction" +import {Tag} from "../../Tags/Tag" +import {Changes} from "../Changes" +import {ChangeDescription} from "./ChangeDescription" import CreateNewWayAction from "./CreateNewWayAction" -import CreateWayWithPointReuseAction, { MergePointConfig } from "./CreateWayWithPointReuseAction" -import { And } from "../../Tags/And" -import { TagUtils } from "../../Tags/TagUtils" +import CreateWayWithPointReuseAction, {MergePointConfig} from "./CreateWayWithPointReuseAction" +import {And} from "../../Tags/And" +import {TagUtils} from "../../Tags/TagUtils" +import {FeatureSource, IndexedFeatureSource} from "../../FeatureSource/FeatureSource" +import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig"; +import {Position} from "geojson"; +import FullNodeDatabaseSource from "../../FeatureSource/TiledFeatureSource/FullNodeDatabaseSource"; /** * More or less the same as 'CreateNewWay', except that it'll try to reuse already existing points */ -export default class CreateMultiPolygonWithPointReuseAction extends OsmCreateAction { +export default class CreateMultiPolygonWithPointReuseAction extends OsmCreateAction implements PreviewableAction { public newElementId: string = undefined public newElementIdNumber: number = undefined private readonly _tags: Tag[] @@ -24,19 +26,24 @@ export default class CreateMultiPolygonWithPointReuseAction extends OsmCreateAct constructor( tags: Tag[], - outerRingCoordinates: [number, number][], - innerRingsCoordinates: [number, number][][], - state: FeaturePipelineState, + outerRingCoordinates: Position[], + innerRingsCoordinates: Position[][], + state: { + layout: LayoutConfig; + changes: Changes; + indexedFeatures: IndexedFeatureSource, + fullNodeDatabase?: FullNodeDatabaseSource + }, config: MergePointConfig[], changeType: "import" | "create" | string ) { super(null, true) this._tags = [...tags, new Tag("type", "multipolygon")] this.changeType = changeType - this.theme = state?.layoutToUse?.id ?? "" + this.theme = state?.layout?.id ?? "" this.createOuterWay = new CreateWayWithPointReuseAction( [], - outerRingCoordinates, + <[number,number][]> outerRingCoordinates, state, config ) @@ -45,7 +52,7 @@ export default class CreateMultiPolygonWithPointReuseAction extends OsmCreateAct new CreateNewWayAction( [], ringCoordinates.map(([lon, lat]) => ({ lat, lon })), - { theme: state?.layoutToUse?.id } + { theme: state?.layout?.id } ) ) @@ -59,17 +66,7 @@ export default class CreateMultiPolygonWithPointReuseAction extends OsmCreateAct } } - public async getPreview(): Promise { - const outerPreview = await this.createOuterWay.getPreview() - outerPreview.features.data.push({ - freshness: new Date(), - feature: this.geojsonPreview, - }) - return outerPreview - } - protected async CreateChangeDescriptions(changes: Changes): Promise { - console.log("Running CMPWPRA") const descriptions: ChangeDescription[] = [] descriptions.push(...(await this.createOuterWay.CreateChangeDescriptions(changes))) for (const innerWay of this.createInnerWays) { @@ -105,4 +102,8 @@ export default class CreateMultiPolygonWithPointReuseAction extends OsmCreateAct return descriptions } + + getPreview(): Promise { + return undefined + } } diff --git a/Logic/Osm/Actions/CreateNewNodeAction.ts b/Logic/Osm/Actions/CreateNewNodeAction.ts index 7e69e8317..224f24aab 100644 --- a/Logic/Osm/Actions/CreateNewNodeAction.ts +++ b/Logic/Osm/Actions/CreateNewNodeAction.ts @@ -104,9 +104,13 @@ export default class CreateNewNodeAction extends OsmCreateAction { // Project the point onto the way console.log("Snapping a node onto an existing way...") const geojson = this._snapOnto.asGeoJson() - const projected = GeoOperations.nearestPoint(geojson, [this._lon, this._lat]) + const projected = GeoOperations.nearestPoint(GeoOperations.outerRing(geojson), [ + this._lon, + this._lat, + ]) const projectedCoor = <[number, number]>projected.geometry.coordinates const index = projected.properties.index + console.log("Attempting to snap:", { geojson, projected, projectedCoor, index }) // We check that it isn't close to an already existing point let reusedPointId = undefined let outerring: [number, number][] diff --git a/Logic/Osm/Actions/CreateNewWayAction.ts b/Logic/Osm/Actions/CreateNewWayAction.ts index 8b44a0c2c..50e2628a6 100644 --- a/Logic/Osm/Actions/CreateNewWayAction.ts +++ b/Logic/Osm/Actions/CreateNewWayAction.ts @@ -1,9 +1,9 @@ -import { ChangeDescription } from "./ChangeDescription" -import { OsmCreateAction } from "./OsmChangeAction" -import { Changes } from "../Changes" -import { Tag } from "../../Tags/Tag" +import {ChangeDescription} from "./ChangeDescription" +import {OsmCreateAction} from "./OsmChangeAction" +import {Changes} from "../Changes" +import {Tag} from "../../Tags/Tag" import CreateNewNodeAction from "./CreateNewNodeAction" -import { And } from "../../Tags/And" +import {And} from "../../Tags/And" export default class CreateNewWayAction extends OsmCreateAction { public newElementId: string = undefined diff --git a/Logic/Osm/Actions/CreateWayWithPointReuseAction.ts b/Logic/Osm/Actions/CreateWayWithPointReuseAction.ts index ed549d4af..a4a60039d 100644 --- a/Logic/Osm/Actions/CreateWayWithPointReuseAction.ts +++ b/Logic/Osm/Actions/CreateWayWithPointReuseAction.ts @@ -1,15 +1,17 @@ -import { OsmCreateAction } from "./OsmChangeAction" -import { Tag } from "../../Tags/Tag" -import { Changes } from "../Changes" -import { ChangeDescription } from "./ChangeDescription" -import FeaturePipelineState from "../../State/FeaturePipelineState" -import { BBox } from "../../BBox" -import { TagsFilter } from "../../Tags/TagsFilter" -import { GeoOperations } from "../../GeoOperations" -import FeatureSource from "../../FeatureSource/FeatureSource" +import {OsmCreateAction, PreviewableAction} from "./OsmChangeAction" +import {Tag} from "../../Tags/Tag" +import {Changes} from "../Changes" +import {ChangeDescription} from "./ChangeDescription" +import {BBox} from "../../BBox" +import {TagsFilter} from "../../Tags/TagsFilter" +import {GeoOperations} from "../../GeoOperations" +import {FeatureSource, IndexedFeatureSource} from "../../FeatureSource/FeatureSource" import StaticFeatureSource from "../../FeatureSource/Sources/StaticFeatureSource" import CreateNewNodeAction from "./CreateNewNodeAction" import CreateNewWayAction from "./CreateNewWayAction" +import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig"; +import FullNodeDatabaseSource from "../../FeatureSource/TiledFeatureSource/FullNodeDatabaseSource"; +import {Position} from "geojson"; export interface MergePointConfig { withinRangeOfM: number @@ -54,7 +56,7 @@ interface CoordinateInfo { /** * More or less the same as 'CreateNewWay', except that it'll try to reuse already existing points */ -export default class CreateWayWithPointReuseAction extends OsmCreateAction { +export default class CreateWayWithPointReuseAction extends OsmCreateAction implements PreviewableAction { public newElementId: string = undefined public newElementIdNumber: number = undefined private readonly _tags: Tag[] @@ -62,14 +64,24 @@ export default class CreateWayWithPointReuseAction extends OsmCreateAction { * lngLat-coordinates * @private */ - private _coordinateInfo: CoordinateInfo[] - private _state: FeaturePipelineState - private _config: MergePointConfig[] + private readonly _coordinateInfo: CoordinateInfo[] + private readonly _state: { + layout: LayoutConfig; + changes: Changes; + indexedFeatures: IndexedFeatureSource, + fullNodeDatabase?: FullNodeDatabaseSource + } + private readonly _config: MergePointConfig[] constructor( tags: Tag[], - coordinates: [number, number][], - state: FeaturePipelineState, + coordinates: Position[], + state: { + layout: LayoutConfig; + changes: Changes; + indexedFeatures: IndexedFeatureSource, + fullNodeDatabase?: FullNodeDatabaseSource + }, config: MergePointConfig[] ) { super(null, true) @@ -78,7 +90,7 @@ export default class CreateWayWithPointReuseAction extends OsmCreateAction { this._config = config // The main logic of this class: the coordinateInfo contains all the changes - this._coordinateInfo = this.CalculateClosebyNodes(coordinates) + this._coordinateInfo = this.CalculateClosebyNodes(<[number,number][]> coordinates) } public async getPreview(): Promise { @@ -188,7 +200,7 @@ export default class CreateWayWithPointReuseAction extends OsmCreateAction { } public async CreateChangeDescriptions(changes: Changes): Promise { - const theme = this._state?.layoutToUse?.id + const theme = this._state?.layout?.id const allChanges: ChangeDescription[] = [] const nodeIdsToUse: { lat: number; lon: number; nodeId?: number }[] = [] for (let i = 0; i < this._coordinateInfo.length; i++) { @@ -233,7 +245,7 @@ export default class CreateWayWithPointReuseAction extends OsmCreateAction { }, }) } - nodeIdsToUse.push({ lat, lon, nodeId: id }) + nodeIdsToUse.push({lat, lon, nodeId: id}) } const newWay = new CreateNewWayAction(this._tags, nodeIdsToUse, { @@ -252,9 +264,7 @@ export default class CreateWayWithPointReuseAction extends OsmCreateAction { private CalculateClosebyNodes(coordinates: [number, number][]): CoordinateInfo[] { const bbox = new BBox(coordinates) const state = this._state - const allNodes = [].concat( - ...(state?.featurePipeline?.GetFeaturesWithin("type_node", bbox.pad(1.2)) ?? []) - ) + const allNodes = state.fullNodeDatabase?.getNodesWithin(bbox.pad(1.2)) ?? [] const maxDistance = Math.max(...this._config.map((c) => c.withinRangeOfM)) // Init coordianteinfo with undefined but the same length as coordinates @@ -311,7 +321,7 @@ export default class CreateWayWithPointReuseAction extends OsmCreateAction { if (!config.ifMatches.matchesProperties(node.properties)) { continue } - closebyNodes.push({ node, d, config }) + closebyNodes.push({node, d, config}) } } diff --git a/Logic/Osm/Actions/DeleteAction.ts b/Logic/Osm/Actions/DeleteAction.ts index fb3712eb7..97a865056 100644 --- a/Logic/Osm/Actions/DeleteAction.ts +++ b/Logic/Osm/Actions/DeleteAction.ts @@ -8,6 +8,7 @@ import { And } from "../../Tags/And" import { Tag } from "../../Tags/Tag" import { OsmId } from "../../../Models/OsmFeature" import { Utils } from "../../../Utils" +import OsmObjectDownloader from "../OsmObjectDownloader"; export default class DeleteAction extends OsmChangeAction { private readonly _softDeletionTags: TagsFilter @@ -49,26 +50,34 @@ export default class DeleteAction extends OsmChangeAction { /** * * import {OsmNode} from "../OsmObject" + * import { ImmutableStore } from "../../UIEventSource"; + * import { OsmConnection } from "../OsmConnection"; * * const obj : OsmNode= new OsmNode(1) * obj.tags = {id:"node/1",name:"Monte Piselli - San Giacomo"} * const da = new DeleteAction("node/1", new Tag("man_made",""), {theme: "test", specialMotivation: "Testcase"}, true) - * const descr = await da.CreateChangeDescriptions(new Changes(), obj) + * const state = { dryRun: new ImmutableStore(true), osmConnection: new OsmConnection() } + * const descr = await da.CreateChangeDescriptions(new Changes(state), obj) * descr[0] // => {doDelete: true, meta: {theme: "test", specialMotivation: "Testcase",changeType: "deletion"}, type: "node",id: 1 } * * // Must not crash if softDeletionTags are undefined * const da = new DeleteAction("node/1", undefined, {theme: "test", specialMotivation: "Testcase"}, true) * const obj : OsmNode= new OsmNode(1) * obj.tags = {id:"node/1",name:"Monte Piselli - San Giacomo"} - * const descr = await da.CreateChangeDescriptions(new Changes(), obj) + * const state = { dryRun: new ImmutableStore(true), osmConnection: new OsmConnection() } + * const descr = await da.CreateChangeDescriptions(new Changes(state), obj) * descr[0] // => {doDelete: true, meta: {theme: "test", specialMotivation: "Testcase", changeType: "deletion"}, type: "node",id: 1 } */ public async CreateChangeDescriptions( changes: Changes, object?: OsmObject ): Promise { - const osmObject = object ?? (await OsmObject.DownloadObjectAsync(this._id)) + const osmObject = object ?? (await new OsmObjectDownloader(changes.backend, changes).DownloadObjectAsync(this._id)) + if(osmObject === "deleted"){ + // already deleted in the meantime - no more changes necessary + return [] + } if (this._hardDelete) { return [ { @@ -82,7 +91,7 @@ export default class DeleteAction extends OsmChangeAction { return await new ChangeTagAction(this._id, this._softDeletionTags, osmObject.tags, { ...this.meta, changeType: "soft-delete", - }).CreateChangeDescriptions(changes) + }).CreateChangeDescriptions() } } } diff --git a/Logic/Osm/Actions/OsmChangeAction.ts b/Logic/Osm/Actions/OsmChangeAction.ts index e07086c1c..b6043a886 100644 --- a/Logic/Osm/Actions/OsmChangeAction.ts +++ b/Logic/Osm/Actions/OsmChangeAction.ts @@ -4,6 +4,7 @@ */ import { Changes } from "../Changes" import { ChangeDescription } from "./ChangeDescription" +import {FeatureSource} from "../../FeatureSource/FeatureSource"; export default abstract class OsmChangeAction { public readonly trackStatistics: boolean @@ -20,12 +21,12 @@ export default abstract class OsmChangeAction { this.mainObjectId = mainObjectId } - public Perform(changes: Changes) { + public async Perform(changes: Changes) { if (this.isUsed) { throw "This ChangeAction is already used" } this.isUsed = true - return this.CreateChangeDescriptions(changes) + return await this.CreateChangeDescriptions(changes) } protected abstract CreateChangeDescriptions(changes: Changes): Promise @@ -35,3 +36,7 @@ export abstract class OsmCreateAction extends OsmChangeAction { public newElementId: string public newElementIdNumber: number } + +export interface PreviewableAction { + getPreview(): Promise +} diff --git a/Logic/Osm/Actions/RelationSplitHandler.ts b/Logic/Osm/Actions/RelationSplitHandler.ts index 1fd6749b8..3cdc6cc43 100644 --- a/Logic/Osm/Actions/RelationSplitHandler.ts +++ b/Logic/Osm/Actions/RelationSplitHandler.ts @@ -1,7 +1,8 @@ import OsmChangeAction from "./OsmChangeAction" import { Changes } from "../Changes" import { ChangeDescription } from "./ChangeDescription" -import { OsmObject, OsmRelation, OsmWay } from "../OsmObject" +import { OsmRelation, OsmWay } from "../OsmObject" +import OsmObjectDownloader from "../OsmObjectDownloader" export interface RelationSplitInput { relation: OsmRelation @@ -14,11 +15,13 @@ export interface RelationSplitInput { abstract class AbstractRelationSplitHandler extends OsmChangeAction { protected readonly _input: RelationSplitInput protected readonly _theme: string + protected readonly _objectDownloader: OsmObjectDownloader - constructor(input: RelationSplitInput, theme: string) { + constructor(input: RelationSplitInput, theme: string, objectDownloader: OsmObjectDownloader) { super("relation/" + input.relation.id, false) this._input = input this._theme = theme + this._objectDownloader = objectDownloader } /** @@ -33,7 +36,9 @@ abstract class AbstractRelationSplitHandler extends OsmChangeAction { return member.ref } if (member.type === "way") { - const osmWay = await OsmObject.DownloadObjectAsync("way/" + member.ref) + const osmWay = ( + await this._objectDownloader.DownloadObjectAsync("way/" + member.ref) + ) const nodes = osmWay.nodes if (first) { return nodes[0] @@ -52,26 +57,30 @@ abstract class AbstractRelationSplitHandler extends OsmChangeAction { * When a way is split and this way is part of a relation, the relation should be updated too to have the new segment if relevant. */ export default class RelationSplitHandler extends AbstractRelationSplitHandler { - constructor(input: RelationSplitInput, theme: string) { - super(input, theme) + constructor(input: RelationSplitInput, theme: string, objectDownloader: OsmObjectDownloader) { + super(input, theme, objectDownloader) } async CreateChangeDescriptions(changes: Changes): Promise { if (this._input.relation.tags["type"] === "restriction") { // This is a turn restriction - return new TurnRestrictionRSH(this._input, this._theme).CreateChangeDescriptions( - changes - ) + return new TurnRestrictionRSH( + this._input, + this._theme, + this._objectDownloader + ).CreateChangeDescriptions(changes) } - return new InPlaceReplacedmentRTSH(this._input, this._theme).CreateChangeDescriptions( - changes - ) + return new InPlaceReplacedmentRTSH( + this._input, + this._theme, + this._objectDownloader + ).CreateChangeDescriptions(changes) } } export class TurnRestrictionRSH extends AbstractRelationSplitHandler { - constructor(input: RelationSplitInput, theme: string) { - super(input, theme) + constructor(input: RelationSplitInput, theme: string, objectDownloader: OsmObjectDownloader) { + super(input, theme, objectDownloader) } public async CreateChangeDescriptions(changes: Changes): Promise { @@ -91,9 +100,11 @@ export class TurnRestrictionRSH extends AbstractRelationSplitHandler { if (selfMember.role === "via") { // A via way can be replaced in place - return new InPlaceReplacedmentRTSH(this._input, this._theme).CreateChangeDescriptions( - changes - ) + return new InPlaceReplacedmentRTSH( + this._input, + this._theme, + this._objectDownloader + ).CreateChangeDescriptions(changes) } // We have to keep only the way with a common point with the rest of the relation @@ -166,8 +177,8 @@ export class TurnRestrictionRSH extends AbstractRelationSplitHandler { * Note that the feature might appear multiple times. */ export class InPlaceReplacedmentRTSH extends AbstractRelationSplitHandler { - constructor(input: RelationSplitInput, theme: string) { - super(input, theme) + constructor(input: RelationSplitInput, theme: string, objectDownloader: OsmObjectDownloader) { + super(input, theme, objectDownloader) } async CreateChangeDescriptions(changes: Changes): Promise { diff --git a/Logic/Osm/Actions/ReplaceGeometryAction.ts b/Logic/Osm/Actions/ReplaceGeometryAction.ts index 94390f61f..70afff79e 100644 --- a/Logic/Osm/Actions/ReplaceGeometryAction.ts +++ b/Logic/Osm/Actions/ReplaceGeometryAction.ts @@ -1,28 +1,28 @@ -import OsmChangeAction from "./OsmChangeAction" -import { Changes } from "../Changes" -import { ChangeDescription } from "./ChangeDescription" -import { Tag } from "../../Tags/Tag" -import FeatureSource from "../../FeatureSource/FeatureSource" -import { OsmNode, OsmObject, OsmWay } from "../OsmObject" -import { GeoOperations } from "../../GeoOperations" +import OsmChangeAction, {PreviewableAction} from "./OsmChangeAction" +import {Changes} from "../Changes" +import {ChangeDescription} from "./ChangeDescription" +import {Tag} from "../../Tags/Tag" +import {FeatureSource} from "../../FeatureSource/FeatureSource" +import {OsmNode, OsmObject, OsmWay} from "../OsmObject" +import {GeoOperations} from "../../GeoOperations" import StaticFeatureSource from "../../FeatureSource/Sources/StaticFeatureSource" import CreateNewNodeAction from "./CreateNewNodeAction" import ChangeTagAction from "./ChangeTagAction" -import { And } from "../../Tags/And" -import { Utils } from "../../../Utils" -import { OsmConnection } from "../OsmConnection" -import { Feature } from "@turf/turf" -import FeaturePipeline from "../../FeatureSource/FeaturePipeline" -import { Geometry, LineString, Point, Polygon } from "geojson" +import {And} from "../../Tags/And" +import {Utils} from "../../../Utils" +import {OsmConnection} from "../OsmConnection" +import {Feature} from "@turf/turf" +import {Geometry, LineString, Point} from "geojson" +import FullNodeDatabaseSource from "../../FeatureSource/TiledFeatureSource/FullNodeDatabaseSource" -export default class ReplaceGeometryAction extends OsmChangeAction { +export default class ReplaceGeometryAction extends OsmChangeAction implements PreviewableAction{ /** * The target feature - mostly used for the metadata */ private readonly feature: any private readonly state: { osmConnection: OsmConnection - featurePipeline: FeaturePipeline + fullNodeDatabase?: FullNodeDatabaseSource } private readonly wayToReplaceId: string private readonly theme: string @@ -38,10 +38,15 @@ export default class ReplaceGeometryAction extends OsmChangeAction { private readonly identicalTo: number[] private readonly newTags: Tag[] | undefined + /** + * Not really the 'new' element, but the target that has been applied. + * Added for compatibility with other systems + */ + public readonly newElementId: string constructor( state: { - osmConnection: OsmConnection - featurePipeline: FeaturePipeline + osmConnection: OsmConnection, + fullNodeDatabase?: FullNodeDatabaseSource }, feature: any, wayToReplaceId: string, @@ -55,6 +60,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction { this.feature = feature this.wayToReplaceId = wayToReplaceId this.theme = options.theme + this.newElementId = wayToReplaceId const geom = this.feature.geometry let coordinates: [number, number][] @@ -81,7 +87,6 @@ export default class ReplaceGeometryAction extends OsmChangeAction { this.newTags = options.newTags } - // noinspection JSUnusedGlobalSymbols public async getPreview(): Promise { const { closestIds, allNodesById, detachedNodes, reprojectedNodes } = await this.GetClosestIds() @@ -195,7 +200,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction { }> { // TODO FIXME: if a new point has to be created, snap to already existing ways - const nodeDb = this.state.featurePipeline.fullNodeDatabase + const nodeDb = this.state.fullNodeDatabase if (nodeDb === undefined) { throw "PANIC: replaceGeometryAction needs the FullNodeDatabase, which is undefined. This should be initialized by having the 'type_node'-layer enabled in your theme. (NB: the replacebutton has type_node as dependency)" } @@ -415,7 +420,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction { } protected async CreateChangeDescriptions(changes: Changes): Promise { - const nodeDb = this.state.featurePipeline.fullNodeDatabase + const nodeDb = this.state.fullNodeDatabase if (nodeDb === undefined) { throw "PANIC: replaceGeometryAction needs the FullNodeDatabase, which is undefined. This should be initialized by having the 'type_node'-layer enabled in your theme. (NB: the replacebutton has type_node as dependency)" } @@ -455,6 +460,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction { } } + console.log("Adding tags", this.newTags,"to conflated way nr", this.wayToReplaceId) if (this.newTags !== undefined && this.newTags.length > 0) { const addExtraTags = new ChangeTagAction( this.wayToReplaceId, @@ -465,7 +471,7 @@ export default class ReplaceGeometryAction extends OsmChangeAction { changeType: "conflation", } ) - allChanges.push(...(await addExtraTags.CreateChangeDescriptions(changes))) + allChanges.push(...(await addExtraTags.CreateChangeDescriptions())) } const newCoordinates = [...this.targetCoordinates] diff --git a/Logic/Osm/Actions/SplitAction.ts b/Logic/Osm/Actions/SplitAction.ts index ba95dbe36..b4a8a93a3 100644 --- a/Logic/Osm/Actions/SplitAction.ts +++ b/Logic/Osm/Actions/SplitAction.ts @@ -1,9 +1,11 @@ -import { OsmObject, OsmWay } from "../OsmObject" -import { Changes } from "../Changes" -import { GeoOperations } from "../../GeoOperations" +import {OsmWay} from "../OsmObject" +import {Changes} from "../Changes" +import {GeoOperations} from "../../GeoOperations" import OsmChangeAction from "./OsmChangeAction" -import { ChangeDescription } from "./ChangeDescription" +import {ChangeDescription} from "./ChangeDescription" import RelationSplitHandler from "./RelationSplitHandler" +import {Feature, LineString} from "geojson" +import OsmObjectDownloader from "../OsmObjectDownloader" interface SplitInfo { originalIndex?: number // or negative for new elements @@ -14,9 +16,9 @@ interface SplitInfo { export default class SplitAction extends OsmChangeAction { private readonly wayId: string private readonly _splitPointsCoordinates: [number, number][] // lon, lat - private _meta: { theme: string; changeType: "split" } - private _toleranceInMeters: number - private _withNewCoordinates: (coordinates: [number, number][]) => void + private readonly _meta: { theme: string; changeType: "split" } + private readonly _toleranceInMeters: number + private readonly _withNewCoordinates: (coordinates: [number, number][]) => void /** * Create a changedescription for splitting a point. @@ -60,7 +62,9 @@ export default class SplitAction extends OsmChangeAction { } async CreateChangeDescriptions(changes: Changes): Promise { - const originalElement = await OsmObject.DownloadObjectAsync(this.wayId) + const originalElement = ( + await new OsmObjectDownloader(changes.backend, changes).DownloadObjectAsync(this.wayId) + ) const originalNodes = originalElement.nodes // First, calculate the splitpoints and remove points close to one another @@ -171,7 +175,8 @@ export default class SplitAction extends OsmChangeAction { // At last, we still have to check that we aren't part of a relation... // At least, the order of the ways is identical, so we can keep the same roles - const relations = await OsmObject.DownloadReferencingRelations(this.wayId) + const downloader = new OsmObjectDownloader(changes.backend, changes) + const relations = await downloader.DownloadReferencingRelations(this.wayId) for (const relation of relations) { const changDescrs = await new RelationSplitHandler( { @@ -181,7 +186,8 @@ export default class SplitAction extends OsmChangeAction { allWaysNodesInOrder: allWaysNodesInOrder, originalWayId: originalElement.id, }, - this._meta.theme + this._meta.theme, + downloader ).CreateChangeDescriptions(changes) changeDescription.push(...changDescrs) } @@ -197,7 +203,7 @@ export default class SplitAction extends OsmChangeAction { * If another point is closer then ~5m, we reuse that point */ private CalculateSplitCoordinates(osmWay: OsmWay, toleranceInM = 5): SplitInfo[] { - const wayGeoJson = osmWay.asGeoJson() + const wayGeoJson = >osmWay.asGeoJson() // Should be [lon, lat][] const originalPoints: [number, number][] = osmWay.coordinates.map((c) => [c[1], c[0]]) const allPoints: { diff --git a/Logic/Osm/Changes.ts b/Logic/Osm/Changes.ts index c2568def4..8ab80f151 100644 --- a/Logic/Osm/Changes.ts +++ b/Logic/Osm/Changes.ts @@ -1,45 +1,44 @@ -import { OsmNode, OsmObject, OsmRelation, OsmWay } from "./OsmObject" -import { UIEventSource } from "../UIEventSource" +import {OsmNode, OsmObject, OsmRelation, OsmWay} from "./OsmObject" +import {Store, UIEventSource} from "../UIEventSource" import Constants from "../../Models/Constants" import OsmChangeAction from "./Actions/OsmChangeAction" -import { ChangeDescription, ChangeDescriptionTools } from "./Actions/ChangeDescription" -import { Utils } from "../../Utils" -import { LocalStorageSource } from "../Web/LocalStorageSource" +import {ChangeDescription, ChangeDescriptionTools} from "./Actions/ChangeDescription" +import {Utils} from "../../Utils" +import {LocalStorageSource} from "../Web/LocalStorageSource" import SimpleMetaTagger from "../SimpleMetaTagger" -import FeatureSource from "../FeatureSource/FeatureSource" -import { ElementStorage } from "../ElementStorage" -import { GeoLocationPointProperties } from "../State/GeoLocationState" -import { GeoOperations } from "../GeoOperations" -import { ChangesetHandler, ChangesetTag } from "./ChangesetHandler" -import { OsmConnection } from "./OsmConnection" +import {FeatureSource, IndexedFeatureSource} from "../FeatureSource/FeatureSource" +import {GeoLocationPointProperties} from "../State/GeoLocationState" +import {GeoOperations} from "../GeoOperations" +import {ChangesetHandler, ChangesetTag} from "./ChangesetHandler" +import {OsmConnection} from "./OsmConnection" +import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore" +import OsmObjectDownloader from "./OsmObjectDownloader" /** * Handles all changes made to OSM. * Needs an authenticator via OsmConnection */ export class Changes { - public readonly name = "Newly added features" - /** - * All the newly created features as featureSource + all the modified features - */ - public features = new UIEventSource<{ feature: any; freshness: Date }[]>([]) public readonly pendingChanges: UIEventSource = LocalStorageSource.GetParsed("pending-changes", []) public readonly allChanges = new UIEventSource(undefined) - public readonly state: { allElements: ElementStorage; osmConnection: OsmConnection } + public readonly state: { allElements?: IndexedFeatureSource; osmConnection: OsmConnection } public readonly extraComment: UIEventSource = new UIEventSource(undefined) - - private historicalUserLocations: FeatureSource + public readonly backend: string + public readonly isUploading = new UIEventSource(false) + private readonly historicalUserLocations?: FeatureSource private _nextId: number = -1 // Newly assigned ID's are negative - private readonly isUploading = new UIEventSource(false) private readonly previouslyCreated: OsmObject[] = [] private readonly _leftRightSensitive: boolean - private _changesetHandler: ChangesetHandler + private readonly _changesetHandler: ChangesetHandler constructor( - state?: { - allElements: ElementStorage + state: { + dryRun: Store + allElements?: IndexedFeatureSource + featurePropertiesStore?: FeaturePropertiesStore osmConnection: OsmConnection + historicalUserLocations?: FeatureSource }, leftRightSensitive: boolean = false ) { @@ -49,10 +48,14 @@ export class Changes { // If a pending change contains a negative ID, we save that this._nextId = Math.min(-1, ...(this.pendingChanges.data?.map((pch) => pch.id) ?? [])) this.state = state - this._changesetHandler = state?.osmConnection?.CreateChangesetHandler( - state.allElements, + this.backend = state.osmConnection.Backend() + this._changesetHandler = new ChangesetHandler( + state.dryRun, + state.osmConnection, + state.featurePropertiesStore, this ) + this.historicalUserLocations = state.historicalUserLocations // Note: a changeset might be reused which was opened just before and might have already used some ids // This doesn't matter however, as the '-1' is per piecewise upload, not global per changeset @@ -148,273 +151,6 @@ export class Changes { this.allChanges.ping() } - private calculateDistanceToChanges( - change: OsmChangeAction, - changeDescriptions: ChangeDescription[] - ) { - const locations = this.historicalUserLocations?.features?.data - if (locations === undefined) { - // No state loaded or no locations -> we can't calculate... - return - } - if (!change.trackStatistics) { - // Probably irrelevant, such as a new helper node - return - } - - const now = new Date() - const recentLocationPoints = locations - .map((ff) => ff.feature) - .filter((feat) => feat.geometry.type === "Point") - .filter((feat) => { - const visitTime = new Date( - ((feat.properties)).date - ) - // In seconds - const diff = (now.getTime() - visitTime.getTime()) / 1000 - return diff < Constants.nearbyVisitTime - }) - if (recentLocationPoints.length === 0) { - // Probably no GPS enabled/no fix - return - } - - // The applicable points, contain information in their properties about location, time and GPS accuracy - // They are all GeoLocationPointProperties - // We walk every change and determine the closest distance possible - // Only if the change itself does _not_ contain any coordinates, we fall back and search the original feature in the state - - const changedObjectCoordinates: [number, number][] = [] - - const feature = this.state.allElements.ContainingFeatures.get(change.mainObjectId) - if (feature !== undefined) { - changedObjectCoordinates.push(GeoOperations.centerpointCoordinates(feature)) - } - - for (const changeDescription of changeDescriptions) { - const chng: - | { lat: number; lon: number } - | { coordinates: [number, number][] } - | { members } = changeDescription.changes - if (chng === undefined) { - continue - } - if (chng["lat"] !== undefined) { - changedObjectCoordinates.push([chng["lat"], chng["lon"]]) - } - if (chng["coordinates"] !== undefined) { - changedObjectCoordinates.push(...chng["coordinates"]) - } - } - - return Math.min( - ...changedObjectCoordinates.map((coor) => - Math.min( - ...recentLocationPoints.map((gpsPoint) => { - const otherCoor = GeoOperations.centerpointCoordinates(gpsPoint) - return GeoOperations.distanceBetween(coor, otherCoor) - }) - ) - ) - ) - } - - /** - * UPload the selected changes to OSM. - * Returns 'true' if successfull and if they can be removed - */ - private async flushSelectChanges( - pending: ChangeDescription[], - openChangeset: UIEventSource - ): Promise { - const self = this - const neededIds = Changes.GetNeededIds(pending) - - const osmObjects = Utils.NoNull( - await Promise.all( - neededIds.map(async (id) => - OsmObject.DownloadObjectAsync(id).catch((e) => { - console.error( - "Could not download OSM-object", - id, - " dropping it from the changes (" + e + ")" - ) - pending = pending.filter((ch) => ch.type + "/" + ch.id !== id) - return undefined - }) - ) - ) - ) - - if (this._leftRightSensitive) { - osmObjects.forEach((obj) => SimpleMetaTagger.removeBothTagging(obj.tags)) - } - - console.log("Got the fresh objects!", osmObjects, "pending: ", pending) - if (pending.length == 0) { - console.log("No pending changes...") - return true - } - - const perType = Array.from( - Utils.Hist( - pending - .filter( - (descr) => - descr.meta.changeType !== undefined && descr.meta.changeType !== null - ) - .map((descr) => descr.meta.changeType) - ), - ([key, count]) => ({ - key: key, - value: count, - aggregate: true, - }) - ) - const motivations = pending - .filter((descr) => descr.meta.specialMotivation !== undefined) - .map((descr) => ({ - key: descr.meta.changeType + ":" + descr.type + "/" + descr.id, - value: descr.meta.specialMotivation, - })) - - const distances = Utils.NoNull(pending.map((descr) => descr.meta.distanceToObject)) - distances.sort((a, b) => a - b) - const perBinCount = Constants.distanceToChangeObjectBins.map((_) => 0) - - let j = 0 - const maxDistances = Constants.distanceToChangeObjectBins - for (let i = 0; i < maxDistances.length; i++) { - const maxDistance = maxDistances[i] - // distances is sorted in ascending order, so as soon as one is to big, all the resting elements will be bigger too - while (j < distances.length && distances[j] < maxDistance) { - perBinCount[i]++ - j++ - } - } - - const perBinMessage = Utils.NoNull( - perBinCount.map((count, i) => { - if (count === 0) { - return undefined - } - const maxD = maxDistances[i] - let key = `change_within_${maxD}m` - if (maxD === Number.MAX_VALUE) { - key = `change_over_${maxDistances[i - 1]}m` - } - return { - key, - value: count, - aggregate: true, - } - }) - ) - - // This method is only called with changedescriptions for this theme - const theme = pending[0].meta.theme - let comment = "Adding data with #MapComplete for theme #" + theme - if (this.extraComment.data !== undefined) { - comment += "\n\n" + this.extraComment.data - } - - const metatags: ChangesetTag[] = [ - { - key: "comment", - value: comment, - }, - { - key: "theme", - value: theme, - }, - ...perType, - ...motivations, - ...perBinMessage, - ] - - await this._changesetHandler.UploadChangeset( - (csId, remappings) => { - if (remappings.size > 0) { - console.log("Rewriting pending changes from", pending, "with", remappings) - pending = pending.map((ch) => ChangeDescriptionTools.rewriteIds(ch, remappings)) - console.log("Result is", pending) - } - const changes: { - newObjects: OsmObject[] - modifiedObjects: OsmObject[] - deletedObjects: OsmObject[] - } = self.CreateChangesetObjects(pending, osmObjects) - return Changes.createChangesetFor("" + csId, changes) - }, - metatags, - openChangeset - ) - - console.log("Upload successfull!") - return true - } - - private async flushChangesAsync(): Promise { - const self = this - try { - // At last, we build the changeset and upload - const pending = self.pendingChanges.data - - const pendingPerTheme = new Map() - for (const changeDescription of pending) { - const theme = changeDescription.meta.theme - if (!pendingPerTheme.has(theme)) { - pendingPerTheme.set(theme, []) - } - pendingPerTheme.get(theme).push(changeDescription) - } - - const successes = await Promise.all( - Array.from(pendingPerTheme, async ([theme, pendingChanges]) => { - try { - const openChangeset = this.state.osmConnection - .GetPreference("current-open-changeset-" + theme) - .sync( - (str) => { - const n = Number(str) - if (isNaN(n)) { - return undefined - } - return n - }, - [], - (n) => "" + n - ) - console.log( - "Using current-open-changeset-" + - theme + - " from the preferences, got " + - openChangeset.data - ) - - return await self.flushSelectChanges(pendingChanges, openChangeset) - } catch (e) { - console.error("Could not upload some changes:", e) - return false - } - }) - ) - - if (!successes.some((s) => s == false)) { - // All changes successfull, we clear the data! - this.pendingChanges.setData([]) - } - } catch (e) { - console.error( - "Could not handle changes - probably an old, pending changeset in localstorage with an invalid format; erasing those", - e - ) - self.pendingChanges.setData([]) - } finally { - self.isUploading.setData(false) - } - } - public CreateChangesetObjects( changes: ChangeDescription[], downloadedOsmObjects: OsmObject[] @@ -510,11 +246,12 @@ export class Changes { switch (change.type) { case "node": // @ts-ignore - const nlat = change.changes.lat + const nlat = Utils.Round7(change.changes.lat) // @ts-ignore - const nlon = change.changes.lon + const nlon = Utils.Round7(change.changes.lon) const n = obj if (n.lat !== nlat || n.lon !== nlon) { + console.log("Node moved:", n.lat, nlat, n.lon, nlon) n.lat = nlat n.lon = nlon changed = true @@ -583,7 +320,284 @@ export class Changes { return result } - public setHistoricalUserLocations(locations: FeatureSource) { - this.historicalUserLocations = locations + private calculateDistanceToChanges( + change: OsmChangeAction, + changeDescriptions: ChangeDescription[] + ) { + const locations = this.historicalUserLocations?.features?.data + if (locations === undefined) { + // No state loaded or no locations -> we can't calculate... + return + } + if (!change.trackStatistics) { + // Probably irrelevant, such as a new helper node + return + } + + const now = new Date() + const recentLocationPoints = locations + .filter((feat) => feat.geometry.type === "Point") + .filter((feat) => { + const visitTime = new Date( + ((feat.properties)).date + ) + // In seconds + const diff = (now.getTime() - visitTime.getTime()) / 1000 + return diff < Constants.nearbyVisitTime + }) + if (recentLocationPoints.length === 0) { + // Probably no GPS enabled/no fix + return + } + + // The applicable points, contain information in their properties about location, time and GPS accuracy + // They are all GeoLocationPointProperties + // We walk every change and determine the closest distance possible + // Only if the change itself does _not_ contain any coordinates, we fall back and search the original feature in the state + + const changedObjectCoordinates: [number, number][] = [] + + { + const feature = this.state.allElements?.featuresById?.data.get(change.mainObjectId) + if (feature !== undefined) { + changedObjectCoordinates.push(GeoOperations.centerpointCoordinates(feature)) + } + } + + for (const changeDescription of changeDescriptions) { + const chng: + | { lat: number; lon: number } + | { coordinates: [number, number][] } + | { members } = changeDescription.changes + if (chng === undefined) { + continue + } + if (chng["lat"] !== undefined) { + changedObjectCoordinates.push([chng["lat"], chng["lon"]]) + } + if (chng["coordinates"] !== undefined) { + changedObjectCoordinates.push(...chng["coordinates"]) + } + } + + return Math.min( + ...changedObjectCoordinates.map((coor) => + Math.min( + ...recentLocationPoints.map((gpsPoint) => { + const otherCoor = GeoOperations.centerpointCoordinates(gpsPoint) + return GeoOperations.distanceBetween(coor, otherCoor) + }) + ) + ) + ) + } + + /** + * Upload the selected changes to OSM. + * Returns 'true' if successful and if they can be removed + */ + private async flushSelectChanges( + pending: ChangeDescription[], + openChangeset: UIEventSource + ): Promise { + const self = this + const neededIds = Changes.GetNeededIds(pending) + // We _do not_ pass in the Changes object itself - we want the data from OSM directly in order to apply the changes + const downloader = new OsmObjectDownloader(this.backend, undefined) + let osmObjects = await Promise.all<{ id: string; osmObj: OsmObject | "deleted" }>( + neededIds.map(async (id) => { + try { + const osmObj = await downloader.DownloadObjectAsync(id) + return {id, osmObj} + } catch (e) { + console.error( + "Could not download OSM-object", + id, + " dropping it from the changes (" + e + ")" + ) + return undefined + } + }) + ) + + osmObjects = Utils.NoNull(osmObjects) + + for (const {osmObj, id} of osmObjects) { + if (osmObj === "deleted") { + pending = pending.filter((ch) => ch.type + "/" + ch.id !== id) + } + } + + const objects = osmObjects + .filter((obj) => obj.osmObj !== "deleted") + .map((obj) => obj.osmObj) + + if (this._leftRightSensitive) { + objects.forEach((obj) => SimpleMetaTagger.removeBothTagging(obj.tags)) + } + + console.log("Got the fresh objects!", objects, "pending: ", pending) + if (pending.length == 0) { + console.log("No pending changes...") + return true + } + + const perType = Array.from( + Utils.Hist( + pending + .filter( + (descr) => + descr.meta.changeType !== undefined && descr.meta.changeType !== null + ) + .map((descr) => descr.meta.changeType) + ), + ([key, count]) => ({ + key: key, + value: count, + aggregate: true, + }) + ) + const motivations = pending + .filter((descr) => descr.meta.specialMotivation !== undefined) + .map((descr) => ({ + key: descr.meta.changeType + ":" + descr.type + "/" + descr.id, + value: descr.meta.specialMotivation, + })) + + const distances = Utils.NoNull(pending.map((descr) => descr.meta.distanceToObject)) + distances.sort((a, b) => a - b) + const perBinCount = Constants.distanceToChangeObjectBins.map((_) => 0) + + let j = 0 + const maxDistances = Constants.distanceToChangeObjectBins + for (let i = 0; i < maxDistances.length; i++) { + const maxDistance = maxDistances[i] + // distances is sorted in ascending order, so as soon as one is to big, all the resting elements will be bigger too + while (j < distances.length && distances[j] < maxDistance) { + perBinCount[i]++ + j++ + } + } + + const perBinMessage = Utils.NoNull( + perBinCount.map((count, i) => { + if (count === 0) { + return undefined + } + const maxD = maxDistances[i] + let key = `change_within_${maxD}m` + if (maxD === Number.MAX_VALUE) { + key = `change_over_${maxDistances[i - 1]}m` + } + return { + key, + value: count, + aggregate: true, + } + }) + ) + + // This method is only called with changedescriptions for this theme + const theme = pending[0].meta.theme + let comment = "Adding data with #MapComplete for theme #" + theme + if (this.extraComment.data !== undefined) { + comment += "\n\n" + this.extraComment.data + } + + const metatags: ChangesetTag[] = [ + { + key: "comment", + value: comment, + }, + { + key: "theme", + value: theme, + }, + ...perType, + ...motivations, + ...perBinMessage, + ] + + await this._changesetHandler.UploadChangeset( + (csId, remappings) => { + if (remappings.size > 0) { + console.log("Rewriting pending changes from", pending, "with", remappings) + pending = pending.map((ch) => ChangeDescriptionTools.rewriteIds(ch, remappings)) + console.log("Result is", pending) + } + const changes: { + newObjects: OsmObject[] + modifiedObjects: OsmObject[] + deletedObjects: OsmObject[] + } = self.CreateChangesetObjects(pending, objects) + return Changes.createChangesetFor("" + csId, changes) + }, + metatags, + openChangeset + ) + + console.log("Upload successfull!") + return true + } + + private async flushChangesAsync(): Promise { + const self = this + try { + // At last, we build the changeset and upload + const pending = self.pendingChanges.data + + const pendingPerTheme = new Map() + for (const changeDescription of pending) { + const theme = changeDescription.meta.theme + if (!pendingPerTheme.has(theme)) { + pendingPerTheme.set(theme, []) + } + pendingPerTheme.get(theme).push(changeDescription) + } + + const successes = await Promise.all( + Array.from(pendingPerTheme, async ([theme, pendingChanges]) => { + try { + const openChangeset = this.state.osmConnection + .GetPreference("current-open-changeset-" + theme) + .sync( + (str) => { + const n = Number(str) + if (isNaN(n)) { + return undefined + } + return n + }, + [], + (n) => "" + n + ) + console.log( + "Using current-open-changeset-" + + theme + + " from the preferences, got " + + openChangeset.data + ) + + return await self.flushSelectChanges(pendingChanges, openChangeset) + } catch (e) { + console.error("Could not upload some changes:", e) + return false + } + }) + ) + + if (!successes.some((s) => s == false)) { + // All changes successfull, we clear the data! + this.pendingChanges.setData([]) + } + } catch (e) { + console.error( + "Could not handle changes - probably an old, pending changeset in localstorage with an invalid format; erasing those", + e + ) + self.pendingChanges.setData([]) + } finally { + self.isUploading.setData(false) + } } } diff --git a/Logic/Osm/ChangesetHandler.ts b/Logic/Osm/ChangesetHandler.ts index 2661f9402..01c2da21c 100644 --- a/Logic/Osm/ChangesetHandler.ts +++ b/Logic/Osm/ChangesetHandler.ts @@ -1,7 +1,6 @@ import escapeHtml from "escape-html" import UserDetails, { OsmConnection } from "./OsmConnection" -import { UIEventSource } from "../UIEventSource" -import { ElementStorage } from "../ElementStorage" +import { Store, UIEventSource } from "../UIEventSource" import Locale from "../../UI/i18n/Locale" import Constants from "../../Models/Constants" import { Changes } from "./Changes" @@ -14,12 +13,11 @@ export interface ChangesetTag { } export class ChangesetHandler { - private readonly allElements: ElementStorage + private readonly allElements: { addAlias: (id0: String, id1: string) => void } private osmConnection: OsmConnection private readonly changes: Changes - private readonly _dryRun: UIEventSource + private readonly _dryRun: Store private readonly userDetails: UIEventSource - private readonly auth: any private readonly backend: string /** @@ -28,20 +26,11 @@ export class ChangesetHandler { */ private readonly _remappings = new Map() - /** - * Use 'osmConnection.CreateChangesetHandler' instead - * @param dryRun - * @param osmConnection - * @param allElements - * @param changes - * @param auth - */ constructor( - dryRun: UIEventSource, + dryRun: Store, osmConnection: OsmConnection, - allElements: ElementStorage, - changes: Changes, - auth + allElements: { addAlias: (id0: string, id1: string) => void } | undefined, + changes: Changes ) { this.osmConnection = osmConnection this.allElements = allElements @@ -49,7 +38,6 @@ export class ChangesetHandler { this._dryRun = dryRun this.userDetails = osmConnection.userDetails this.backend = osmConnection._oauth_config.url - this.auth = auth if (dryRun) { console.log("DRYRUN ENABLED") @@ -61,7 +49,7 @@ export class ChangesetHandler { * * ChangesetHandler.removeDuplicateMetaTags([{key: "k", value: "v"}, {key: "k0", value: "v0"}, {key: "k", value:"v"}] // => [{key: "k", value: "v"}, {key: "k0", value: "v0"}] */ - public static removeDuplicateMetaTags(extraMetaTags: ChangesetTag[]): ChangesetTag[] { + private static removeDuplicateMetaTags(extraMetaTags: ChangesetTag[]): ChangesetTag[] { const r: ChangesetTag[] = [] const seen = new Set() for (const extraMetaTag of extraMetaTags) { @@ -80,9 +68,9 @@ export class ChangesetHandler { * The key is changed _in place_; true will be returned if a change has been applied * @param extraMetaTags * @param rewriteIds - * @private + * @public for testing purposes */ - static rewriteMetaTags(extraMetaTags: ChangesetTag[], rewriteIds: Map) { + public static rewriteMetaTags(extraMetaTags: ChangesetTag[], rewriteIds: Map) { let hasChange = false for (const tag of extraMetaTags) { const match = tag.key.match(/^([a-zA-Z0-9_]+):(node\/-[0-9])$/) @@ -141,9 +129,9 @@ export class ChangesetHandler { const csId = await this.OpenChangeset(extraMetaTags) openChangeset.setData(csId) const changeset = generateChangeXML(csId, this._remappings) - console.trace( + console.log( "Opened a new changeset (openChangeset.data is undefined):", - changeset + changeset, extraMetaTags ) const changes = await this.UploadChange(csId, changeset) const hasSpecialMotivationChanges = ChangesetHandler.rewriteMetaTags( @@ -197,6 +185,8 @@ export class ChangesetHandler { * @param extraMetaTags: new changeset tags to add/fuse with this changeset * @param rewriteIds: the mapping of ids * @param oldChangesetMeta: the metadata-object of the already existing changeset + * + * @public for testing purposes */ public RewriteTagsOf( extraMetaTags: ChangesetTag[], @@ -309,7 +299,7 @@ export class ChangesetHandler { } for (const mapping of mappings) { const [oldId, newId] = mapping - this.allElements.addAlias(oldId, newId) + this.allElements?.addAlias(oldId, newId) if (newId !== undefined) { this._remappings.set(mapping[0], mapping[1]) } @@ -317,29 +307,16 @@ export class ChangesetHandler { return new Map(mappings) } + // noinspection JSUnusedLocalSymbols private async CloseChangeset(changesetId: number = undefined): Promise { - const self = this - return new Promise(function (resolve, reject) { - if (changesetId === undefined) { - return - } - self.auth.xhr( - { - method: "PUT", - path: "/api/0.6/changeset/" + changesetId + "/close", - }, - function (err, response) { - if (response == null) { - console.log("err", err) - } - console.log("Closed changeset ", changesetId) - resolve() - } - ) - }) + if (changesetId === undefined) { + return + } + await this.osmConnection.put("changeset/" + changesetId + "/close") + console.log("Closed changeset ", changesetId) } - async GetChangesetMeta(csId: number): Promise<{ + private async GetChangesetMeta(csId: number): Promise<{ id: number open: boolean uid: number @@ -358,34 +335,16 @@ export class ChangesetHandler { private async UpdateTags(csId: number, tags: ChangesetTag[]) { tags = ChangesetHandler.removeDuplicateMetaTags(tags) - const self = this - return new Promise(function (resolve, reject) { - tags = Utils.NoNull(tags).filter( - (tag) => - tag.key !== undefined && - tag.value !== undefined && - tag.key !== "" && - tag.value !== "" - ) - const metadata = tags.map((kv) => ``) - - self.auth.xhr( - { - method: "PUT", - path: "/api/0.6/changeset/" + csId, - options: { header: { "Content-Type": "text/xml" } }, - content: [``, metadata, ``].join(""), - }, - function (err, response) { - if (response === undefined) { - console.error("Updating the tags of changeset " + csId + " failed:", err) - reject(err) - } else { - resolve(response) - } - } - ) - }) + tags = Utils.NoNull(tags).filter( + (tag) => + tag.key !== undefined && + tag.value !== undefined && + tag.key !== "" && + tag.value !== "" + ) + const metadata = tags.map((kv) => ``) + const content = [``, metadata, ``].join("") + return this.osmConnection.put("changeset/" + csId, content, { "Content-Type": "text/xml" }) } private defaultChangesetTags(): ChangesetTag[] { @@ -413,57 +372,35 @@ export class ChangesetHandler { * @constructor * @private */ - private OpenChangeset(changesetTags: ChangesetTag[]): Promise { - const self = this - return new Promise(function (resolve, reject) { - const metadata = changesetTags - .map((cstag) => [cstag.key, cstag.value]) - .filter((kv) => (kv[1] ?? "") !== "") - .map((kv) => ``) - .join("\n") + private async OpenChangeset(changesetTags: ChangesetTag[]): Promise { + const metadata = changesetTags + .map((cstag) => [cstag.key, cstag.value]) + .filter((kv) => (kv[1] ?? "") !== "") + .map((kv) => ``) + .join("\n") - self.auth.xhr( - { - method: "PUT", - path: "/api/0.6/changeset/create", - options: { header: { "Content-Type": "text/xml" } }, - content: [``, metadata, ``].join(""), - }, - function (err, response) { - if (response === undefined) { - console.error("Opening a changeset failed:", err) - reject(err) - } else { - resolve(Number(response)) - } - } - ) - }) + const csId = await this.osmConnection.put( + "changeset/create", + [``, metadata, ``].join(""), + { "Content-Type": "text/xml" } + ) + return Number(csId) } /** * Upload a changesetXML */ - private UploadChange(changesetId: number, changesetXML: string): Promise> { - const self = this - return new Promise(function (resolve, reject) { - self.auth.xhr( - { - method: "POST", - options: { header: { "Content-Type": "text/xml" } }, - path: "/api/0.6/changeset/" + changesetId + "/upload", - content: changesetXML, - }, - function (err, response) { - if (response == null) { - console.error("Uploading an actual change failed", err) - reject(err) - } - const changes = self.parseUploadChangesetResponse(response) - console.log("Uploaded changeset ", changesetId) - resolve(changes) - } - ) - }) + private async UploadChange( + changesetId: number, + changesetXML: string + ): Promise> { + const response = await this.osmConnection.post( + "changeset/" + changesetId + "/upload", + changesetXML, + { "Content-Type": "text/xml" } + ) + const changes = this.parseUploadChangesetResponse(response) + console.log("Uploaded changeset ", changesetId) + return changes } } diff --git a/Logic/Osm/Geocoding.ts b/Logic/Osm/Geocoding.ts index 4e349d8ba..09da7af6d 100644 --- a/Logic/Osm/Geocoding.ts +++ b/Logic/Osm/Geocoding.ts @@ -1,4 +1,3 @@ -import State from "../../State" import { Utils } from "../../Utils" import { BBox } from "../BBox" @@ -6,6 +5,10 @@ export interface GeoCodeResult { display_name: string lat: number lon: number + /** + * Format: + * [lat, lat, lon, lon] + */ boundingbox: number[] osm_type: "node" | "way" | "relation" osm_id: string @@ -14,8 +17,8 @@ export interface GeoCodeResult { export class Geocoding { private static readonly host = "https://nominatim.openstreetmap.org/search?" - static async Search(query: string): Promise { - const b = State?.state?.currentBounds?.data ?? BBox.global + static async Search(query: string, bbox: BBox): Promise { + const b = bbox ?? BBox.global const url = Geocoding.host + "format=json&limit=1&viewbox=" + diff --git a/Logic/Osm/OsmConnection.ts b/Logic/Osm/OsmConnection.ts index f4b5c323c..a14d30849 100644 --- a/Logic/Osm/OsmConnection.ts +++ b/Logic/Osm/OsmConnection.ts @@ -1,13 +1,7 @@ import osmAuth from "osm-auth" import { Store, Stores, UIEventSource } from "../UIEventSource" import { OsmPreferences } from "./OsmPreferences" -import { ChangesetHandler } from "./ChangesetHandler" -import { ElementStorage } from "../ElementStorage" -import Svg from "../../Svg" -import Img from "../../UI/Base/Img" import { Utils } from "../../Utils" -import { OsmObject } from "./OsmObject" -import { Changes } from "./Changes" export default class UserDetails { public loggedIn = false @@ -64,7 +58,7 @@ export class OsmConnection { oauth_secret: string url: string } - private readonly _dryRun: UIEventSource + private readonly _dryRun: Store private fakeUser: boolean private _onLoggedIn: ((userDetails: UserDetails) => void)[] = [] private readonly _iframeMode: Boolean | boolean @@ -72,7 +66,7 @@ export class OsmConnection { private isChecking = false constructor(options?: { - dryRun?: UIEventSource + dryRun?: Store fakeUser?: false | boolean oauth_token?: UIEventSource // Used to keep multiple changesets open and to write to the correct changeset @@ -87,7 +81,6 @@ export class OsmConnection { OsmConnection.oauth_configs[options.osmConfiguration ?? "osm"] ?? OsmConnection.oauth_configs.osm console.debug("Using backend", this._oauth_config.url) - OsmObject.SetBackendUrl(this._oauth_config.url + "/") this._iframeMode = Utils.runningFromConsole ? false : window !== window.top this.userDetails = new UIEventSource( @@ -148,16 +141,6 @@ export class OsmConnection { } } - public CreateChangesetHandler(allElements: ElementStorage, changes: Changes) { - return new ChangesetHandler( - this._dryRun, - /*casting is needed to make the tests work*/ this, - allElements, - changes, - this.auth - ) - } - public GetPreference( key: string, defaultValue: string = undefined, @@ -252,7 +235,7 @@ export class OsmConnection { userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? 0 ) data.tracesCount = Number.parseInt( - userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? 0 + userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? 0 ) data.img = undefined @@ -288,6 +271,57 @@ export class OsmConnection { ) } + /** + * Interact with the API. + * + * @param path: the path to query, without host and without '/api/0.6'. Example 'notes/1234/close' + */ + public async interact( + path: string, + method: "GET" | "POST" | "PUT" | "DELETE", + header?: Record, + content?: string + ): Promise { + return new Promise((ok, error) => { + this.auth.xhr( + { + method, + options: { + header, + }, + content, + path: `/api/0.6/${path}`, + }, + function (err, response) { + if (err !== null) { + error(err) + } else { + ok(response) + } + } + ) + }) + } + + public async post( + path: string, + content?: string, + header?: Record + ): Promise { + return await this.interact(path, "POST", header, content) + } + public async put( + path: string, + content?: string, + header?: Record + ): Promise { + return await this.interact(path, "PUT", header, content) + } + + public async get(path: string, header?: Record): Promise { + return await this.interact(path, "GET", header) + } + public closeNote(id: number | string, text?: string): Promise { let textSuffix = "" if ((text ?? "") !== "") { @@ -299,21 +333,7 @@ export class OsmConnection { ok() }) } - return new Promise((ok, error) => { - this.auth.xhr( - { - method: "POST", - path: `/api/0.6/notes/${id}/close${textSuffix}`, - }, - function (err, _) { - if (err !== null) { - error(err) - } else { - ok() - } - } - ) - }) + return this.post(`notes/${id}/close${textSuffix}`) } public reopenNote(id: number | string, text?: string): Promise { @@ -327,24 +347,10 @@ export class OsmConnection { if ((text ?? "") !== "") { textSuffix = "?text=" + encodeURIComponent(text) } - return new Promise((ok, error) => { - this.auth.xhr( - { - method: "POST", - path: `/api/0.6/notes/${id}/reopen${textSuffix}`, - }, - function (err, _) { - if (err !== null) { - error(err) - } else { - ok() - } - } - ) - }) + return this.post(`notes/${id}/reopen${textSuffix}`) } - public openNote(lat: number, lon: number, text: string): Promise<{ id: number }> { + public async openNote(lat: number, lon: number, text: string): Promise<{ id: number }> { if (this._dryRun.data) { console.warn("Dryrun enabled - not actually opening note with text ", text) return new Promise<{ id: number }>((ok) => { @@ -356,29 +362,13 @@ export class OsmConnection { } const auth = this.auth const content = { lat, lon, text } - return new Promise((ok, error) => { - auth.xhr( - { - method: "POST", - path: `/api/0.6/notes.json`, - options: { - header: { "Content-Type": "application/json" }, - }, - content: JSON.stringify(content), - }, - function (err, response: string) { - console.log("RESPONSE IS", response) - if (err !== null) { - error(err) - } else { - const parsed = JSON.parse(response) - const id = parsed.properties.id - console.log("OPENED NOTE", id) - ok({ id }) - } - } - ) + const response = await this.post("notes.json", JSON.stringify(content), { + "Content-Type": "application/json", }) + const parsed = JSON.parse(response) + const id = parsed.properties + console.log("OPENED NOTE", id) + return id } public async uploadGpxTrack( @@ -434,31 +424,13 @@ export class OsmConnection { } body += "--" + boundary + "--\r\n" - return new Promise((ok, error) => { - auth.xhr( - { - method: "POST", - path: `/api/0.6/gpx/create`, - options: { - header: { - "Content-Type": "multipart/form-data; boundary=" + boundary, - "Content-Length": body.length, - }, - }, - content: body, - }, - function (err, response: string) { - console.log("RESPONSE IS", response) - if (err !== null) { - error(err) - } else { - const parsed = JSON.parse(response) - console.log("Uploaded GPX track", parsed) - ok({ id: parsed }) - } - } - ) + const response = await this.post("gpx/create", body, { + "Content-Type": "multipart/form-data; boundary=" + boundary, + "Content-Length": body.length, }) + const parsed = JSON.parse(response) + console.log("Uploaded GPX track", parsed) + return { id: parsed } } public addCommentToNote(id: number | string, text: string): Promise { diff --git a/Logic/Osm/OsmObject.ts b/Logic/Osm/OsmObject.ts index 0589e647c..71bddf53a 100644 --- a/Logic/Osm/OsmObject.ts +++ b/Logic/Osm/OsmObject.ts @@ -1,17 +1,13 @@ import {Utils} from "../../Utils" import polygon_features from "../../assets/polygon-features.json" -import {Store, UIEventSource} from "../UIEventSource" -import {BBox} from "../BBox" import OsmToGeoJson from "osmtogeojson" -import {NodeId, OsmFeature, OsmId, OsmTags, RelationId, WayId} from "../../Models/OsmFeature" +import {OsmFeature, OsmId, OsmTags, WayId} from "../../Models/OsmFeature" import {Feature, LineString, Polygon} from "geojson" export abstract class OsmObject { private static defaultBackend = "https://www.openstreetmap.org/" protected static backendURL = OsmObject.defaultBackend private static polygonFeatures = OsmObject.constructPolygonFeatures() - private static objectCache = new Map>() - private static historyCache = new Map>() type: "node" | "way" | "relation" id: number /** @@ -31,189 +27,6 @@ export abstract class OsmObject { } } - public static SetBackendUrl(url: string) { - if (!url.endsWith("/")) { - throw "Backend URL must end with a '/'" - } - if (!url.startsWith("http")) { - throw "Backend URL must begin with http" - } - this.backendURL = url - } - - public static DownloadObject(id: NodeId, forceRefresh?: boolean): Store - public static DownloadObject(id: RelationId, forceRefresh?: boolean): Store - public static DownloadObject(id: WayId, forceRefresh?: boolean): Store - public static DownloadObject(id: string, forceRefresh: boolean = false): Store { - let src: UIEventSource - if (OsmObject.objectCache.has(id)) { - src = OsmObject.objectCache.get(id) - if (forceRefresh) { - src.setData(undefined) - } else { - return src - } - } else { - src = UIEventSource.FromPromise(OsmObject.DownloadObjectAsync(id)) - } - - OsmObject.objectCache.set(id, src) - return src - } - - static async DownloadPropertiesOf(id: string): Promise { - const splitted = id.split("/") - const idN = Number(splitted[1]) - if (idN < 0) { - return undefined - } - - const url = `${OsmObject.backendURL}api/0.6/${id}` - const rawData = await Utils.downloadJsonCachedAdvanced(url, 1000) - if (rawData["error"] !== undefined && rawData["statuscode"] === 410) { - return "deleted" - } - return rawData["content"].elements[0].tags - } - - static async DownloadObjectAsync( - id: NodeId, - maxCacheAgeInSecs?: number - ): Promise - static async DownloadObjectAsync( - id: WayId, - maxCacheAgeInSecs?: number - ): Promise - static async DownloadObjectAsync( - id: RelationId, - maxCacheAgeInSecs?: number - ): Promise - static async DownloadObjectAsync( - id: OsmId, - maxCacheAgeInSecs?: number - ): Promise - static async DownloadObjectAsync( - id: string, - maxCacheAgeInSecs?: number - ): Promise - static async DownloadObjectAsync( - id: string, - maxCacheAgeInSecs?: number - ): Promise { - const splitted = id.split("/") - const type = splitted[0] - const idN = Number(splitted[1]) - if (idN < 0) { - return undefined - } - - const full = !id.startsWith("node") ? "/full" : "" - const url = `${OsmObject.backendURL}api/0.6/${id}${full}` - const rawData = await Utils.downloadJsonCached(url, (maxCacheAgeInSecs ?? 10) * 1000) - if (rawData === undefined) { - return undefined - } - // A full query might contain more then just the requested object (e.g. nodes that are part of a way, where we only want the way) - const parsed = OsmObject.ParseObjects(rawData.elements) - // Lets fetch the object we need - for (const osmObject of parsed) { - if (osmObject.type !== type) { - continue - } - if (osmObject.id !== idN) { - continue - } - // Found the one! - return osmObject - } - throw "PANIC: requested object is not part of the response" - } - - /** - * Downloads the ways that are using this node. - * Beware: their geometry will be incomplete! - */ - public static DownloadReferencingWays(id: string): Promise { - return Utils.downloadJsonCached( - `${OsmObject.backendURL}api/0.6/${id}/ways`, - 60 * 1000 - ).then((data) => { - return data.elements.map((wayInfo) => { - const way = new OsmWay(wayInfo.id) - way.LoadData(wayInfo) - return way - }) - }) - } - - /** - * Downloads the relations that are using this feature. - * Beware: their geometry will be incomplete! - */ - public static async DownloadReferencingRelations(id: string): Promise { - const data = await Utils.downloadJsonCached( - `${OsmObject.backendURL}api/0.6/${id}/relations`, - 60 * 1000 - ) - return data.elements.map((wayInfo) => { - const rel = new OsmRelation(wayInfo.id) - rel.LoadData(wayInfo) - rel.SaveExtraData(wayInfo, undefined) - return rel - }) - } - - public static DownloadHistory(id: NodeId): UIEventSource - public static DownloadHistory(id: WayId): UIEventSource - public static DownloadHistory(id: RelationId): UIEventSource - - public static DownloadHistory(id: OsmId): UIEventSource - public static DownloadHistory(id: string): UIEventSource { - if (OsmObject.historyCache.has(id)) { - return OsmObject.historyCache.get(id) - } - const splitted = id.split("/") - const type = splitted[0] - const idN = Number(splitted[1]) - const src = new UIEventSource([]) - OsmObject.historyCache.set(id, src) - Utils.downloadJsonCached( - `${OsmObject.backendURL}api/0.6/${type}/${idN}/history`, - 10 * 60 * 1000 - ).then((data) => { - const elements: any[] = data.elements - const osmObjects: OsmObject[] = [] - for (const element of elements) { - let osmObject: OsmObject = null - element.nodes = [] - switch (type) { - case "node": - osmObject = new OsmNode(idN) - break - case "way": - osmObject = new OsmWay(idN) - break - case "relation": - osmObject = new OsmRelation(idN) - break - } - osmObject?.LoadData(element) - osmObject?.SaveExtraData(element, []) - osmObjects.push(osmObject) - } - src.setData(osmObjects) - }) - return src - } - - // bounds should be: [[maxlat, minlon], [minlat, maxlon]] (same as Utils.tile_bounds) - public static async LoadArea(bbox: BBox): Promise { - const url = `${OsmObject.backendURL}api/0.6/map.json?bbox=${bbox.minLon},${bbox.minLat},${bbox.maxLon},${bbox.maxLat}` - const data = await Utils.downloadJson(url) - const elements: any[] = data.elements - return OsmObject.ParseObjects(elements) - } - public static ParseObjects(elements: any[]): OsmObject[] { const objects: OsmObject[] = [] const allNodes: Map = new Map() @@ -355,12 +168,16 @@ export abstract class OsmObject { return 'version="' + this.version + '"' } - private LoadData(element: any): void { - this.tags = element.tags ?? this.tags - this.version = element.version - this.timestamp = element.timestamp + protected LoadData(element: any): void { + if (element === undefined) { + return + } + this.tags = element?.tags ?? this.tags const tgs = this.tags - if (element.tags === undefined) { + tgs["id"] = (this.type + "/" + this.id) + this.version = element?.version + this.timestamp = element?.timestamp + if (element?.tags === undefined) { // Simple node which is part of a way - not important return } @@ -369,7 +186,6 @@ export abstract class OsmObject { tgs["_last_edit:changeset"] = element.changeset tgs["_last_edit:timestamp"] = element.timestamp tgs["_version_number"] = element.version - tgs["id"] = (this.type + "/" + this.id) } } @@ -377,8 +193,9 @@ export class OsmNode extends OsmObject { lat: number lon: number - constructor(id: number) { + constructor(id: number, extraData?) { super("node", id) + this.LoadData(extraData) } ChangesetXML(changesetId: string, header?: string): string { @@ -429,8 +246,9 @@ export class OsmWay extends OsmObject { lat: number lon: number - constructor(id: number) { + constructor(id: number, wayInfo?) { super("way", id) + this.LoadData(wayInfo) } centerpoint(): [number, number] { @@ -533,8 +351,9 @@ export class OsmRelation extends OsmObject { private geojson = undefined - constructor(id: number) { + constructor(id: number, extraInfo?: any) { super("relation", id) + this.LoadData(extraInfo) } centerpoint(): [number, number] { diff --git a/Logic/Osm/OsmObjectDownloader.ts b/Logic/Osm/OsmObjectDownloader.ts new file mode 100644 index 000000000..c6c238eb8 --- /dev/null +++ b/Logic/Osm/OsmObjectDownloader.ts @@ -0,0 +1,243 @@ +import { Utils } from "../../Utils" +import { OsmNode, OsmObject, OsmRelation, OsmWay } from "./OsmObject" +import { NodeId, OsmId, RelationId, WayId } from "../../Models/OsmFeature" +import { Store, UIEventSource } from "../UIEventSource" +import { ChangeDescription } from "./Actions/ChangeDescription" + +/** + * The OSM-Object downloader downloads the latest version of the object, but applies 'pendingchanges' to them, + * so that we always have a consistent view + */ +export default class OsmObjectDownloader { + private readonly _changes?: { + readonly pendingChanges: UIEventSource + readonly isUploading: Store + } + private readonly backend: string + private historyCache = new Map>() + + constructor( + backend: string = "https://www.openstreetmap.org", + changes?: { + readonly pendingChanges: UIEventSource + readonly isUploading: Store + } + ) { + this._changes = changes + if (!backend.endsWith("/")) { + backend += "/" + } + if (!backend.startsWith("http")) { + throw "Backend URL must begin with http" + } + this.backend = backend + } + + async DownloadObjectAsync(id: NodeId, maxCacheAgeInSecs?: number): Promise + + async DownloadObjectAsync(id: WayId, maxCacheAgeInSecs?: number): Promise + + async DownloadObjectAsync( + id: RelationId, + maxCacheAgeInSecs?: number + ): Promise + + async DownloadObjectAsync(id: OsmId, maxCacheAgeInSecs?: number): Promise + + async DownloadObjectAsync( + id: string, + maxCacheAgeInSecs?: number + ): Promise + + async DownloadObjectAsync(id: string, maxCacheAgeInSecs?: number) { + // Wait until uploading is done + if (this._changes) { + await this._changes.isUploading.AsPromise((o) => o === false) + } + + const splitted = id.split("/") + const type = splitted[0] + const idN = Number(splitted[1]) + let obj: OsmObject | "deleted" + if (idN < 0) { + obj = this.constructObject(<"node" | "way" | "relation">type, idN) + } else { + obj = await this.RawDownloadObjectAsync(type, idN, maxCacheAgeInSecs) + } + if (obj === "deleted") { + return obj + } + return await this.applyPendingChanges(obj) + } + + public DownloadHistory(id: NodeId): UIEventSource + + public DownloadHistory(id: WayId): UIEventSource + + public DownloadHistory(id: RelationId): UIEventSource + + public DownloadHistory(id: OsmId): UIEventSource + + public DownloadHistory(id: string): UIEventSource { + if (this.historyCache.has(id)) { + return this.historyCache.get(id) + } + const splitted = id.split("/") + const type = splitted[0] + const idN = Number(splitted[1]) + const src = new UIEventSource([]) + this.historyCache.set(id, src) + Utils.downloadJsonCached( + `${this.backend}api/0.6/${type}/${idN}/history`, + 10 * 60 * 1000 + ).then((data) => { + const elements: any[] = data.elements + const osmObjects: OsmObject[] = [] + for (const element of elements) { + let osmObject: OsmObject = null + element.nodes = [] + switch (type) { + case "node": + osmObject = new OsmNode(idN, element) + break + case "way": + osmObject = new OsmWay(idN, element) + break + case "relation": + osmObject = new OsmRelation(idN, element) + break + } + osmObject?.SaveExtraData(element, []) + osmObjects.push(osmObject) + } + src.setData(osmObjects) + }) + return src + } + + /** + * Downloads the ways that are using this node. + * Beware: their geometry will be incomplete! + */ + public async DownloadReferencingWays(id: string): Promise { + const data = await Utils.downloadJsonCached(`${this.backend}api/0.6/${id}/ways`, 60 * 1000) + return data.elements.map((wayInfo) => new OsmWay(wayInfo.id, wayInfo)) + } + + /** + * Downloads the relations that are using this feature. + * Beware: their geometry will be incomplete! + */ + public async DownloadReferencingRelations(id: string): Promise { + const data = await Utils.downloadJsonCached( + `${this.backend}api/0.6/${id}/relations`, + 60 * 1000 + ) + return data.elements.map((wayInfo) => { + const rel = new OsmRelation(wayInfo.id, wayInfo) + rel.SaveExtraData(wayInfo, undefined) + return rel + }) + } + + private applyNodeChange(object: OsmNode, change: { lat: number; lon: number }) { + object.lat = change.lat + object.lon = change.lon + } + + private applyWayChange(object: OsmWay, change: { nodes: number[]; coordinates }) { + object.nodes = change.nodes + object.coordinates = change.coordinates.map(([lat, lon]) => [lon, lat]) + } + + private applyRelationChange( + object: OsmRelation, + change: { members: { type: "node" | "way" | "relation"; ref: number; role: string }[] } + ) { + object.members = change.members + } + + private async applyPendingChanges(object: OsmObject): Promise { + if (!this._changes) { + return object + } + const pendingChanges = this._changes.pendingChanges.data + for (const pendingChange of pendingChanges) { + if (object.id !== pendingChange.id || object.type !== pendingChange.type) { + continue + } + if (pendingChange.doDelete) { + return "deleted" + } + if (pendingChange.tags) { + for (const { k, v } of pendingChange.tags) { + if (v === undefined) { + delete object.tags[k] + } else { + object.tags[k] = v + } + } + } + + if (pendingChange.changes) { + switch (pendingChange.type) { + case "node": + this.applyNodeChange(object, pendingChange.changes) + break + case "way": + this.applyWayChange(object, pendingChange.changes) + break + case "relation": + this.applyRelationChange(object, pendingChange.changes) + break + } + } + } + return object + } + + /** + * Creates an empty object of the specified type with the specified id. + * We assume that the pending changes will be applied on them, filling in details such as coordinates, tags, ... + */ + private constructObject(type: "node" | "way" | "relation", id: number): OsmObject { + switch (type) { + case "node": + return new OsmNode(id) + case "way": + return new OsmWay(id) + case "relation": + return new OsmRelation(id) + } + } + + private async RawDownloadObjectAsync( + type: string, + idN: number, + maxCacheAgeInSecs?: number + ): Promise { + const full = type !== "node" ? "/full" : "" + const url = `${this.backend}api/0.6/${type}/${idN}${full}` + const rawData = await Utils.downloadJsonCachedAdvanced( + url, + (maxCacheAgeInSecs ?? 10) * 1000 + ) + if (rawData["error"] !== undefined && rawData["statuscode"] === 410) { + return "deleted" + } + // A full query might contain more then just the requested object (e.g. nodes that are part of a way, where we only want the way) + const parsed = OsmObject.ParseObjects(rawData["content"].elements) + // Lets fetch the object we need + for (const osmObject of parsed) { + if (osmObject.type !== type) { + continue + } + if (osmObject.id !== idN) { + continue + } + // Found the one! + return osmObject + } + throw "PANIC: requested object is not part of the response" + } +} diff --git a/Logic/Osm/Overpass.ts b/Logic/Osm/Overpass.ts index 1293857fc..9a4b53edb 100644 --- a/Logic/Osm/Overpass.ts +++ b/Logic/Osm/Overpass.ts @@ -1,5 +1,4 @@ import { TagsFilter } from "../Tags/TagsFilter" -import RelationsTracker from "./RelationsTracker" import { Utils } from "../../Utils" import { ImmutableStore, Store } from "../UIEventSource" import { BBox } from "../BBox" @@ -15,14 +14,12 @@ export class Overpass { private readonly _timeout: Store private readonly _extraScripts: string[] private readonly _includeMeta: boolean - private _relationTracker: RelationsTracker constructor( filter: TagsFilter, extraScripts: string[], interpreterUrl: string, timeout?: Store, - relationTracker?: RelationsTracker, includeMeta = true ) { this._timeout = timeout ?? new ImmutableStore(90) @@ -34,7 +31,6 @@ export class Overpass { this._filter = optimized this._extraScripts = extraScripts this._includeMeta = includeMeta - this._relationTracker = relationTracker } public async queryGeoJson(bounds: BBox): Promise<[FeatureCollection, Date]> { @@ -57,7 +53,6 @@ export class Overpass { } public async ExecuteQuery(query: string): Promise<[FeatureCollection, Date]> { - const self = this const json = await Utils.downloadJson(this.buildUrl(query)) if (json.elements.length === 0 && json.remark !== undefined) { @@ -68,7 +63,6 @@ export class Overpass { console.warn("No features for", json) } - self._relationTracker?.RegisterRelations(json) const geojson = osmtogeojson(json) const osmTime = new Date(json.osm3s.timestamp_osm_base) return [geojson, osmTime] @@ -104,7 +98,6 @@ export class Overpass { /** * Constructs the actual script to execute on Overpass with geocoding * 'PostCall' can be used to set an extra range, see 'AsOverpassTurboLink' - * */ public buildScriptInArea( area: { osm_type: "way" | "relation"; osm_id: number }, @@ -142,7 +135,7 @@ export class Overpass { * Little helper method to quickly open overpass-turbo in the browser */ public static AsOverpassTurboLink(tags: TagsFilter) { - const overpass = new Overpass(tags, [], "", undefined, undefined, false) + const overpass = new Overpass(tags, [], "", undefined, false) const script = overpass.buildScript("", "({{bbox}})", true) const url = "http://overpass-turbo.eu/?Q=" return url + encodeURIComponent(script) diff --git a/Logic/Osm/RelationsTracker.ts b/Logic/Osm/RelationsTracker.ts deleted file mode 100644 index e4c65ba87..000000000 --- a/Logic/Osm/RelationsTracker.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { UIEventSource } from "../UIEventSource" - -export interface Relation { - id: number - type: "relation" - members: { - type: "way" | "node" | "relation" - ref: number - role: string - }[] - tags: any - // Alias for tags; tags == properties - properties: any -} - -export default class RelationsTracker { - public knownRelations = new UIEventSource>( - new Map(), - "Relation memberships" - ) - - constructor() {} - - /** - * Gets an overview of the relations - except for multipolygons. We don't care about those - * @param overpassJson - * @constructor - */ - private static GetRelationElements(overpassJson: any): Relation[] { - const relations = overpassJson.elements.filter( - (element) => element.type === "relation" && element.tags.type !== "multipolygon" - ) - for (const relation of relations) { - relation.properties = relation.tags - } - return relations - } - - public RegisterRelations(overpassJson: any): void { - this.UpdateMembershipTable(RelationsTracker.GetRelationElements(overpassJson)) - } - - /** - * Build a mapping of {memberId --> {role in relation, id of relation} } - * @param relations - * @constructor - */ - private UpdateMembershipTable(relations: Relation[]): void { - const memberships = this.knownRelations.data - let changed = false - for (const relation of relations) { - for (const member of relation.members) { - const role = { - role: member.role, - relation: relation, - } - const key = member.type + "/" + member.ref - if (!memberships.has(key)) { - memberships.set(key, []) - } - const knownRelations = memberships.get(key) - - const alreadyExists = knownRelations.some((knownRole) => { - return knownRole.role === role.role && knownRole.relation === role.relation - }) - if (!alreadyExists) { - knownRelations.push(role) - changed = true - } - } - } - if (changed) { - this.knownRelations.ping() - } - } -} diff --git a/Logic/SimpleMetaTagger.ts b/Logic/SimpleMetaTagger.ts index faddf2906..cc3565a49 100644 --- a/Logic/SimpleMetaTagger.ts +++ b/Logic/SimpleMetaTagger.ts @@ -10,25 +10,155 @@ import { CountryCoder } from "latlon2country" import Constants from "../Models/Constants" import { TagUtils } from "./Tags/TagUtils" import { Feature, LineString } from "geojson" -import { OsmObject } from "./Osm/OsmObject" +import { OsmTags } from "../Models/OsmFeature" +import { UIEventSource } from "./UIEventSource" +import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" +import OsmObjectDownloader from "./Osm/OsmObjectDownloader" -export class SimpleMetaTagger { +/** + * All elements that are needed to perform metatagging + */ +export interface MetataggingState { + layout: LayoutConfig + osmObjectDownloader: OsmObjectDownloader +} + +export abstract class SimpleMetaTagger { public readonly keys: string[] public readonly doc: string public readonly isLazy: boolean public readonly includesDates: boolean - public readonly applyMetaTagsOnFeature: ( - feature: any, - freshness: Date, - layer: LayerConfig, - state - ) => boolean /*** * A function that adds some extra data to a feature * @param docs: what does this extra data do? - * @param f: apply the changes. Returns true if something changed */ + protected constructor(docs: { + keys: string[] + doc: string + /** + * Set this flag if the data is volatile or date-based. + * It'll _won't_ be cached in this case + */ + includesDates?: boolean + isLazy?: boolean + cleanupRetagger?: boolean + }) { + this.keys = docs.keys + this.doc = docs.doc + this.isLazy = docs.isLazy + this.includesDates = docs.includesDates ?? false + if (!docs.cleanupRetagger) { + for (const key of docs.keys) { + if (!key.startsWith("_") && key.toLowerCase().indexOf("theme") < 0) { + throw `Incorrect key for a calculated meta value '${key}': it should start with underscore (_)` + } + } + } + } + + /** + * Applies the metatag-calculation, returns 'true' if the upstream source needs to be pinged + * @param feature + * @param layer + * @param tagsStore + * @param state + */ + public abstract applyMetaTagsOnFeature( + feature: any, + layer: LayerConfig, + tagsStore: UIEventSource>, + state: MetataggingState + ): boolean +} + +export class ReferencingWaysMetaTagger extends SimpleMetaTagger { + /** + * Disable this metatagger, e.g. for caching or tests + * This is a bit a work-around + */ + public static enabled = true + + constructor() { + super({ + keys: ["_referencing_ways"], + isLazy: true, + doc: "_referencing_ways contains - for a node - which ways use this this node as point in their geometry. ", + }) + } + + public applyMetaTagsOnFeature(feature, layer, tags, state) { + if (!ReferencingWaysMetaTagger.enabled) { + return false + } + //this function has some extra code to make it work in SimpleAddUI.ts to also work for newly added points + const id = feature.properties.id + if (!id.startsWith("node/")) { + return false + } + + Utils.AddLazyPropertyAsync(feature.properties, "_referencing_ways", async () => { + const referencingWays = await state.osmObjectDownloader.DownloadReferencingWays(id) + const wayIds = referencingWays.map((w) => "way/" + w.id) + wayIds.sort() + return wayIds.join(";") + }) + + return true + } +} + +class CountryTagger extends SimpleMetaTagger { + private static readonly coder = new CountryCoder( + Constants.countryCoderEndpoint, + Utils.downloadJson + ) + public runningTasks: Set = new Set() + + constructor() { + super({ + keys: ["_country"], + doc: "The country code of the property (with latlon2country)", + includesDates: false, + }) + } + + applyMetaTagsOnFeature(feature, _, tagsSource) { + let centerPoint: any = GeoOperations.centerpoint(feature) + const runningTasks = this.runningTasks + const lat = centerPoint.geometry.coordinates[1] + const lon = centerPoint.geometry.coordinates[0] + runningTasks.add(feature) + CountryTagger.coder + .GetCountryCodeAsync(lon, lat) + .then((countries) => { + if(!countries){ + console.warn("Country coder returned ", countries) + return + } + const oldCountry = feature.properties["_country"] + const newCountry = countries[0].trim().toLowerCase() + if (oldCountry !== newCountry) { + tagsSource.data["_country"] = newCountry + tagsSource?.ping() + } + }) + .catch((e) => { + console.warn(e) + }) + .finally(() => runningTasks.delete(feature)) + return false + } +} + +class InlineMetaTagger extends SimpleMetaTagger { + public readonly applyMetaTagsOnFeature: ( + feature: any, + layer: LayerConfig, + tagsStore: UIEventSource, + state: MetataggingState + ) => boolean + constructor( docs: { keys: string[] @@ -41,121 +171,21 @@ export class SimpleMetaTagger { isLazy?: boolean cleanupRetagger?: boolean }, - f: (feature: any, freshness: Date, layer: LayerConfig, state) => boolean + f: ( + feature: any, + layer: LayerConfig, + tagsStore: UIEventSource, + state: MetataggingState + ) => boolean ) { - this.keys = docs.keys - this.doc = docs.doc - this.isLazy = docs.isLazy + super(docs) this.applyMetaTagsOnFeature = f - this.includesDates = docs.includesDates ?? false - if (!docs.cleanupRetagger) { - for (const key of docs.keys) { - if (!key.startsWith("_") && key.toLowerCase().indexOf("theme") < 0) { - throw `Incorrect key for a calculated meta value '${key}': it should start with underscore (_)` - } - } - } } } -export class ReferencingWaysMetaTagger extends SimpleMetaTagger { - /** - * Disable this metatagger, e.g. for caching or tests - * This is a bit a work-around - */ - public static enabled = true +class RewriteMetaInfoTags extends SimpleMetaTagger { constructor() { - super( - { - keys: ["_referencing_ways"], - isLazy: true, - doc: "_referencing_ways contains - for a node - which ways use this this node as point in their geometry. If the preset has 'snapToLayer' defined, the icon will be calculated based on the preset tags with `_referencing_ways=[\"way/-1\"]` added.", - }, - (feature, _, __, state) => { - if (!ReferencingWaysMetaTagger.enabled) { - return false - } - //this function has some extra code to make it work in SimpleAddUI.ts to also work for newly added points - const id = feature.properties.id - if (!id.startsWith("node/")) { - return false - } - - const currentTagsSource = state.allElements?.getEventSourceById(id) - if (currentTagsSource === undefined) { - return - } - Utils.AddLazyPropertyAsync( - currentTagsSource.data, - "_referencing_ways", - async () => { - const referencingWays = await OsmObject.DownloadReferencingWays(id) - const wayIds = referencingWays.map((w) => "way/" + w.id) - wayIds.sort() - const wayIdsStr = wayIds.join(";") - if (wayIdsStr !== "" && currentTagsSource.data[""] !== wayIdsStr) { - currentTagsSource.data["_referencing_ways"] = wayIdsStr - currentTagsSource.ping() - } - } - ) - - return true - } - ) - } -} - -export class CountryTagger extends SimpleMetaTagger { - private static readonly coder = new CountryCoder( - Constants.countryCoderEndpoint, - Utils.downloadJson - ) - public runningTasks: Set - - constructor() { - const runningTasks = new Set() - super( - { - keys: ["_country"], - doc: "The country code of the property (with latlon2country)", - includesDates: false, - }, - (feature, _, __, state) => { - let centerPoint: any = GeoOperations.centerpoint(feature) - const lat = centerPoint.geometry.coordinates[1] - const lon = centerPoint.geometry.coordinates[0] - runningTasks.add(feature) - CountryTagger.coder - .GetCountryCodeAsync(lon, lat) - .then((countries) => { - runningTasks.delete(feature) - try { - const oldCountry = feature.properties["_country"] - feature.properties["_country"] = countries[0].trim().toLowerCase() - if (oldCountry !== feature.properties["_country"]) { - const tagsSource = state?.allElements?.getEventSourceById( - feature.properties.id - ) - tagsSource?.ping() - } - } catch (e) { - console.warn(e) - } - }) - .catch((_) => { - runningTasks.delete(feature) - }) - return false - } - ) - this.runningTasks = runningTasks - } -} - -export default class SimpleMetaTaggers { - public static readonly objectMetaInfo = new SimpleMetaTagger( - { + super({ keys: [ "_last_edit:contributor", "_last_edit:contributor:uid", @@ -164,33 +194,42 @@ export default class SimpleMetaTaggers { "_version_number", "_backend", ], - doc: "Information about the last edit of this object.", - }, - (feature) => { - /*Note: also called by 'UpdateTagsFromOsmAPI'*/ + doc: "Information about the last edit of this object. This object will actually _rewrite_ some tags for features coming from overpass", + }) + } - const tgs = feature.properties - let movedSomething = false + applyMetaTagsOnFeature(feature: Feature): boolean { + /*Note: also called by 'UpdateTagsFromOsmAPI'*/ - function move(src: string, target: string) { - if (tgs[src] === undefined) { - return - } - tgs[target] = tgs[src] - delete tgs[src] - movedSomething = true + const tgs = feature.properties + let movedSomething = false + + function move(src: string, target: string) { + if (tgs[src] === undefined) { + return } - - move("user", "_last_edit:contributor") - move("uid", "_last_edit:contributor:uid") - move("changeset", "_last_edit:changeset") - move("timestamp", "_last_edit:timestamp") - move("version", "_version_number") - return movedSomething + tgs[target] = tgs[src] + delete tgs[src] + movedSomething = true } - ) + + move("user", "_last_edit:contributor") + move("uid", "_last_edit:contributor:uid") + move("changeset", "_last_edit:changeset") + move("timestamp", "_last_edit:timestamp") + move("version", "_version_number") + feature.properties._backend = feature.properties._backend ?? "https://openstreetmap.org" + return movedSomething + } +} + +export default class SimpleMetaTaggers { + /** + * A simple metatagger which rewrites various metatags as needed + */ + public static readonly objectMetaInfo = new RewriteMetaInfoTags() public static country = new CountryTagger() - public static geometryType = new SimpleMetaTagger( + public static geometryType = new InlineMetaTagger( { keys: ["_geometry:type"], doc: "Adds the geometry type as property. This is identical to the GoeJson geometry type and is one of `Point`,`LineString`, `Polygon` and exceptionally `MultiPolygon` or `MultiLineString`", @@ -201,6 +240,7 @@ export default class SimpleMetaTaggers { return changed } ) + public static referencingWays = new ReferencingWaysMetaTagger() private static readonly cardinalDirections = { N: 0, NNE: 22.5, @@ -219,7 +259,7 @@ export default class SimpleMetaTaggers { NW: 315, NNW: 337.5, } - private static latlon = new SimpleMetaTagger( + private static latlon = new InlineMetaTagger( { keys: ["_lat", "_lon"], doc: "The latitude and longitude of the point (or centerpoint in the case of a way/area)", @@ -230,18 +270,16 @@ export default class SimpleMetaTaggers { const lon = centerPoint.geometry.coordinates[0] feature.properties["_lat"] = "" + lat feature.properties["_lon"] = "" + lon - feature._lon = lon // This is dirty, I know - feature._lat = lat return true } ) - private static layerInfo = new SimpleMetaTagger( + private static layerInfo = new InlineMetaTagger( { doc: "The layer-id to which this feature belongs. Note that this might be return any applicable if `passAllFeatures` is defined.", keys: ["_layer"], includesDates: false, }, - (feature, freshness, layer) => { + (feature, layer) => { if (feature.properties._layer === layer.id) { return false } @@ -249,7 +287,7 @@ export default class SimpleMetaTaggers { return true } ) - private static noBothButLeftRight = new SimpleMetaTagger( + private static noBothButLeftRight = new InlineMetaTagger( { keys: [ "sidewalk:left", @@ -261,7 +299,7 @@ export default class SimpleMetaTaggers { includesDates: false, cleanupRetagger: true, }, - (feature, state, layer) => { + (feature, layer) => { if (!layer.lineRendering.some((lr) => lr.leftRightSensitive)) { return } @@ -269,24 +307,28 @@ export default class SimpleMetaTaggers { return SimpleMetaTaggers.removeBothTagging(feature.properties) } ) - private static surfaceArea = new SimpleMetaTagger( + private static surfaceArea = new InlineMetaTagger( { - keys: ["_surface", "_surface:ha"], - doc: "The surface area of the feature, in square meters and in hectare. Not set on points and ways", + keys: ["_surface"], + doc: "The surface area of the feature in square meters. Not set on points and ways", isLazy: true, }, (feature) => { - Object.defineProperty(feature.properties, "_surface", { - enumerable: false, - configurable: true, - get: () => { - const sqMeters = "" + GeoOperations.surfaceAreaInSqMeters(feature) - delete feature.properties["_surface"] - feature.properties["_surface"] = sqMeters - return sqMeters - }, + Utils.AddLazyProperty(feature.properties, "_surface", () => { + return "" + GeoOperations.surfaceAreaInSqMeters(feature) + }) + return true + } + ) + private static surfaceAreaHa = new InlineMetaTagger( + { + keys: ["_surface:ha"], + doc: "The surface area of the feature in hectare. Not set on points and ways", + isLazy: true, + }, + (feature) => { Utils.AddLazyProperty(feature.properties, "_surface:ha", () => { const sqMeters = GeoOperations.surfaceAreaInSqMeters(feature) return "" + Math.floor(sqMeters / 1000) / 10 @@ -295,7 +337,7 @@ export default class SimpleMetaTaggers { return true } ) - private static levels = new SimpleMetaTagger( + private static levels = new InlineMetaTagger( { doc: "Extract the 'level'-tag into a normalized, ';'-separated value", keys: ["_level"], @@ -314,15 +356,14 @@ export default class SimpleMetaTaggers { return true } ) - - private static canonicalize = new SimpleMetaTagger( + private static canonicalize = new InlineMetaTagger( { doc: "If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical form (e.g. `1meter` will be rewritten to `1m`; `1` will be rewritten to `1m` as well)", keys: ["Theme-defined keys"], }, (feature, _, __, state) => { const units = Utils.NoNull( - [].concat(...(state?.layoutToUse?.layers?.map((layer) => layer.units) ?? [])) + [].concat(...(state?.layout?.layers?.map((layer) => layer.units) ?? [])) ) if (units.length == 0) { return @@ -372,7 +413,7 @@ export default class SimpleMetaTaggers { return rewritten } ) - private static lngth = new SimpleMetaTagger( + private static lngth = new InlineMetaTagger( { keys: ["_length", "_length:km"], doc: "The total length of a feature in meters (and in kilometers, rounded to one decimal for '_length:km'). For a surface, the length of the perimeter", @@ -386,14 +427,14 @@ export default class SimpleMetaTaggers { return true } ) - private static isOpen = new SimpleMetaTagger( + private static isOpen = new InlineMetaTagger( { keys: ["_isOpen"], doc: "If 'opening_hours' is present, it will add the current state of the feature (being 'yes' or 'no')", includesDates: true, isLazy: true, }, - (feature, _, __, state) => { + (feature) => { if (Utils.runningFromConsole) { // We are running from console, thus probably creating a cache // isOpen is irrelevant @@ -443,7 +484,7 @@ export default class SimpleMetaTaggers { }) } ) - private static directionSimplified = new SimpleMetaTagger( + private static directionSimplified = new InlineMetaTagger( { keys: ["_direction:numerical", "_direction:leftright"], doc: "_direction:numerical is a normalized, numerical direction based on 'camera:direction' or on 'direction'; it is only present if a valid direction is found (e.g. 38.5 or NE). _direction:leftright is either 'left' or 'right', which is left-looking on the map or 'right-looking' on the map", @@ -467,8 +508,7 @@ export default class SimpleMetaTaggers { return true } ) - - private static directionCenterpoint = new SimpleMetaTagger( + private static directionCenterpoint = new InlineMetaTagger( { keys: ["_direction:centerpoint"], isLazy: true, @@ -501,20 +541,15 @@ export default class SimpleMetaTaggers { return true } ) - - private static currentTime = new SimpleMetaTagger( + private static currentTime = new InlineMetaTagger( { - keys: ["_now:date", "_now:datetime", "_loaded:date", "_loaded:_datetime"], + keys: ["_now:date", "_now:datetime"], doc: "Adds the time that the data got loaded - pretty much the time of downloading from overpass. The format is YYYY-MM-DD hh:mm, aka 'sortable' aka ISO-8601-but-not-entirely", includesDates: true, }, - (feature, freshness) => { + (feature) => { const now = new Date() - if (typeof freshness === "string") { - freshness = new Date(freshness) - } - function date(d: Date) { return d.toISOString().slice(0, 10) } @@ -525,18 +560,35 @@ export default class SimpleMetaTaggers { feature.properties["_now:date"] = date(now) feature.properties["_now:datetime"] = datetime(now) - feature.properties["_loaded:date"] = date(freshness) - feature.properties["_loaded:datetime"] = datetime(freshness) return true } ) - public static referencingWays = new ReferencingWaysMetaTagger() + private static timeSinceLastEdit = new InlineMetaTagger( + { + keys: ["_last_edit:passed_time"], + doc: "Gives the number of seconds since the last edit. Note that this will _not_ update, but rather be the number of seconds elapsed at the moment this tag is read first", + isLazy: true, + includesDates: true, + }, + (feature, layer, tagsStore) => { + Utils.AddLazyProperty(feature.properties, "_last_edit:passed_time", () => { + const lastEditTimestamp = new Date( + feature.properties["_last_edit:timestamp"] + ).getTime() + const now: number = Date.now() + const millisElapsed = now - lastEditTimestamp + return "" + millisElapsed / 1000 + }) + return true + } + ) public static metatags: SimpleMetaTagger[] = [ SimpleMetaTaggers.latlon, SimpleMetaTaggers.layerInfo, SimpleMetaTaggers.surfaceArea, + SimpleMetaTaggers.surfaceAreaHa, SimpleMetaTaggers.lngth, SimpleMetaTaggers.canonicalize, SimpleMetaTaggers.country, @@ -549,10 +601,8 @@ export default class SimpleMetaTaggers { SimpleMetaTaggers.geometryType, SimpleMetaTaggers.levels, SimpleMetaTaggers.referencingWays, + SimpleMetaTaggers.timeSinceLastEdit, ] - public static readonly lazyTags: string[] = [].concat( - ...SimpleMetaTaggers.metatags.filter((tagger) => tagger.isLazy).map((tagger) => tagger.keys) - ) /** * Edits the given object to rewrite 'both'-tagging into a 'left-right' tagging scheme. diff --git a/Logic/State/ElementsState.ts b/Logic/State/ElementsState.ts deleted file mode 100644 index cecb04009..000000000 --- a/Logic/State/ElementsState.ts +++ /dev/null @@ -1,91 +0,0 @@ -import FeatureSwitchState from "./FeatureSwitchState" -import { ElementStorage } from "../ElementStorage" -import { Changes } from "../Osm/Changes" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import { UIEventSource } from "../UIEventSource" -import Loc from "../../Models/Loc" -import { BBox } from "../BBox" -import { QueryParameters } from "../Web/QueryParameters" -import { LocalStorageSource } from "../Web/LocalStorageSource" -import { Utils } from "../../Utils" -import ChangeToElementsActor from "../Actors/ChangeToElementsActor" -import PendingChangesUploader from "../Actors/PendingChangesUploader" - -/** - * The part of the state keeping track of where the elements, loading them, configuring the feature pipeline etc - */ -export default class ElementsState extends FeatureSwitchState { - /** - The mapping from id -> UIEventSource - */ - public allElements: ElementStorage = new ElementStorage() - - /** - The latest element that was selected - */ - public readonly selectedElement = new UIEventSource(undefined, "Selected element") - - /** - * The map location: currently centered lat, lon and zoom - */ - public readonly locationControl = new UIEventSource(undefined, "locationControl") - - /** - * The current visible extent of the screen - */ - public readonly currentBounds = new UIEventSource(undefined) - - constructor(layoutToUse: LayoutConfig) { - super(layoutToUse) - - function localStorageSynced( - key: string, - deflt: number, - docs: string - ): UIEventSource { - const localStorage = LocalStorageSource.Get(key) - const previousValue = localStorage.data - const src = UIEventSource.asFloat( - QueryParameters.GetQueryParameter(key, "" + deflt, docs).syncWith(localStorage) - ) - - if (src.data === deflt) { - const prev = Number(previousValue) - if (!isNaN(prev)) { - src.setData(prev) - } - } - - return src - } - - // -- Location control initialization - const zoom = localStorageSynced( - "z", - layoutToUse?.startZoom ?? 1, - "The initial/current zoom level" - ) - const lat = localStorageSynced( - "lat", - layoutToUse?.startLat ?? 0, - "The initial/current latitude" - ) - const lon = localStorageSynced( - "lon", - layoutToUse?.startLon ?? 0, - "The initial/current longitude of the app" - ) - - this.locationControl.setData({ - zoom: Utils.asFloat(zoom.data), - lat: Utils.asFloat(lat.data), - lon: Utils.asFloat(lon.data), - }) - this.locationControl.addCallback((latlonz) => { - // Sync the location controls - zoom.setData(latlonz.zoom) - lat.setData(latlonz.lat) - lon.setData(latlonz.lon) - }) - } -} diff --git a/Logic/State/FeaturePipelineState.ts b/Logic/State/FeaturePipelineState.ts deleted file mode 100644 index 8c56a0aac..000000000 --- a/Logic/State/FeaturePipelineState.ts +++ /dev/null @@ -1,174 +0,0 @@ -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import FeaturePipeline from "../FeatureSource/FeaturePipeline" -import { Tiles } from "../../Models/TileRange" -import ShowDataLayer from "../../UI/ShowDataLayer/ShowDataLayer" -import { TileHierarchyAggregator } from "../../UI/ShowDataLayer/TileHierarchyAggregator" -import ShowTileInfo from "../../UI/ShowDataLayer/ShowTileInfo" -import { UIEventSource } from "../UIEventSource" -import MapState from "./MapState" -import SelectedFeatureHandler from "../Actors/SelectedFeatureHandler" -import Hash from "../Web/Hash" -import { BBox } from "../BBox" -import FeatureInfoBox from "../../UI/Popup/FeatureInfoBox" -import { FeatureSourceForLayer, Tiled } from "../FeatureSource/FeatureSource" -import MetaTagRecalculator from "../FeatureSource/Actors/MetaTagRecalculator" -import ScrollableFullScreen from "../../UI/Base/ScrollableFullScreen" -import LayerConfig from "../../Models/ThemeConfig/LayerConfig" - -export default class FeaturePipelineState extends MapState { - /** - * The piece of code which fetches data from various sources and shows it on the background map - */ - public readonly featurePipeline: FeaturePipeline - private readonly featureAggregator: TileHierarchyAggregator - private readonly metatagRecalculator: MetaTagRecalculator - private readonly popups: Map = new Map< - string, - ScrollableFullScreen - >() - - constructor(layoutToUse: LayoutConfig) { - super(layoutToUse) - - const clustering = layoutToUse?.clustering - this.featureAggregator = TileHierarchyAggregator.createHierarchy(this) - const clusterCounter = this.featureAggregator - const self = this - - /** - * We are a bit in a bind: - * There is the featurePipeline, which creates some sources during construction - * THere is the metatagger, which needs to have these sources registered AND which takes a FeaturePipeline as argument - * - * This is a bit of a catch-22 (except that it isn't) - * The sources that are registered in the constructor are saved into 'registeredSources' temporary - * - */ - const sourcesToRegister = [] - - function registerRaw(source: FeatureSourceForLayer & Tiled) { - if (self.metatagRecalculator === undefined) { - sourcesToRegister.push(source) - } else { - self.metatagRecalculator.registerSource(source) - } - } - - function registerSource(source: FeatureSourceForLayer & Tiled) { - clusterCounter.addTile(source) - const sourceBBox = source.features.map((allFeatures) => - BBox.bboxAroundAll(allFeatures.map((f) => BBox.get(f.feature))) - ) - - // Do show features indicates if the respective 'showDataLayer' should be shown. It can be hidden by e.g. clustering - const doShowFeatures = source.features.map( - (f) => { - const z = self.locationControl.data.zoom - - if (!source.layer.isDisplayed.data) { - return false - } - - const bounds = self.currentBounds.data - if (bounds === undefined) { - // Map is not yet displayed - return false - } - - if (!sourceBBox.data.overlapsWith(bounds)) { - // Not within range -> features are hidden - return false - } - - if (z < source.layer.layerDef.minzoom) { - // Layer is always hidden for this zoom level - return false - } - - if (z > clustering.maxZoom) { - return true - } - - if (f.length > clustering.minNeededElements) { - // This tile alone already has too much features - return false - } - - let [tileZ, tileX, tileY] = Tiles.tile_from_index(source.tileIndex) - if (tileZ >= z) { - while (tileZ > z) { - tileZ-- - tileX = Math.floor(tileX / 2) - tileY = Math.floor(tileY / 2) - } - - if ( - clusterCounter.getTile(Tiles.tile_index(tileZ, tileX, tileY)) - ?.totalValue > clustering.minNeededElements - ) { - // To much elements - return false - } - } - - return true - }, - [self.currentBounds, source.layer.isDisplayed, sourceBBox] - ) - - new ShowDataLayer({ - features: source, - leafletMap: self.leafletMap, - layerToShow: source.layer.layerDef, - doShowLayer: doShowFeatures, - selectedElement: self.selectedElement, - state: self, - popup: (tags, layer) => self.CreatePopup(tags, layer), - }) - } - - this.featurePipeline = new FeaturePipeline(registerSource, this, { - handleRawFeatureSource: registerRaw, - }) - this.metatagRecalculator = new MetaTagRecalculator(this, this.featurePipeline) - this.metatagRecalculator.registerSource(this.currentView, true) - - sourcesToRegister.forEach((source) => self.metatagRecalculator.registerSource(source)) - - new SelectedFeatureHandler(Hash.hash, this) - - this.AddClusteringToMap(this.leafletMap) - } - - public CreatePopup(tags: UIEventSource, layer: LayerConfig): ScrollableFullScreen { - if (this.popups.has(tags.data.id)) { - return this.popups.get(tags.data.id) - } - const popup = new FeatureInfoBox(tags, layer, this) - this.popups.set(tags.data.id, popup) - return popup - } - - /** - * Adds the cluster-tiles to the given map - * @param leafletMap: a UIEventSource possible having a leaflet map - * @constructor - */ - public AddClusteringToMap(leafletMap: UIEventSource) { - const clustering = this.layoutToUse.clustering - const self = this - new ShowDataLayer({ - features: this.featureAggregator.getCountsForZoom( - clustering, - this.locationControl, - clustering.minNeededElements - ), - leafletMap: leafletMap, - layerToShow: ShowTileInfo.styling, - popup: this.featureSwitchIsDebugging.data - ? (tags, layer) => new FeatureInfoBox(tags, layer, self) - : undefined, - state: this, - }) - } -} diff --git a/Logic/State/FeatureSwitchState.ts b/Logic/State/FeatureSwitchState.ts index d012ef3de..94d367e20 100644 --- a/Logic/State/FeatureSwitchState.ts +++ b/Logic/State/FeatureSwitchState.ts @@ -2,12 +2,58 @@ * The part of the global state which initializes the feature switches, based on default values and on the layoutToUse */ import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import { UIEventSource } from "../UIEventSource" -import { QueryParameters } from "../Web/QueryParameters" +import {UIEventSource} from "../UIEventSource" +import {QueryParameters} from "../Web/QueryParameters" import Constants from "../../Models/Constants" -import { Utils } from "../../Utils" +import {Utils} from "../../Utils" -export default class FeatureSwitchState { +class FeatureSwitchUtils { + static initSwitch( + key: string, + deflt:boolean, + documentation: string + ): UIEventSource { + const defaultValue = deflt + const queryParam = QueryParameters.GetQueryParameter( + key, + "" + defaultValue, + documentation + ) + + // It takes the current layout, extracts the default value for this query parameter. A query parameter event source is then retrieved and flattened + return queryParam.sync( + (str) => (str === undefined ? defaultValue : str !== "false"), + [], + (b) => (b == defaultValue ? undefined : "" + b) + ) + + + } + +} + +export class OsmConnectionFeatureSwitches { + + public readonly featureSwitchFakeUser: UIEventSource + public readonly featureSwitchApiURL: UIEventSource + + constructor() { + this.featureSwitchApiURL = QueryParameters.GetQueryParameter( + "backend", + "osm", + "The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test'" + ) + + this.featureSwitchFakeUser = QueryParameters.GetBooleanQueryParameter( + "fake-user", + false, + "If true, 'dryrun' mode is activated and a fake user account is loaded" + ) + } +} + + +export default class FeatureSwitchState extends OsmConnectionFeatureSwitches{ /** * The layout that is being used in this run */ @@ -26,119 +72,88 @@ export default class FeatureSwitchState { public readonly featureSwitchIsTesting: UIEventSource public readonly featureSwitchIsDebugging: UIEventSource public readonly featureSwitchShowAllQuestions: UIEventSource - public readonly featureSwitchApiURL: UIEventSource public readonly featureSwitchFilter: UIEventSource public readonly featureSwitchEnableExport: UIEventSource - public readonly featureSwitchFakeUser: UIEventSource - public readonly featureSwitchExportAsPdf: UIEventSource public readonly overpassUrl: UIEventSource public readonly overpassTimeout: UIEventSource public readonly overpassMaxZoom: UIEventSource public readonly osmApiTileSize: UIEventSource public readonly backgroundLayerId: UIEventSource - public constructor(layoutToUse: LayoutConfig) { + public constructor(layoutToUse?: LayoutConfig) { + super() this.layoutToUse = layoutToUse // Helper function to initialize feature switches - function featSw( - key: string, - deflt: (layout: LayoutConfig) => boolean, - documentation: string - ): UIEventSource { - const defaultValue = deflt(layoutToUse) - const queryParam = QueryParameters.GetQueryParameter( - key, - "" + defaultValue, - documentation - ) - // It takes the current layout, extracts the default value for this query parameter. A query parameter event source is then retrieved and flattened - return queryParam.sync( - (str) => (str === undefined ? defaultValue : str !== "false"), - [], - (b) => (b == defaultValue ? undefined : "" + b) - ) - } - - this.featureSwitchUserbadge = featSw( + this.featureSwitchUserbadge = FeatureSwitchUtils.initSwitch( "fs-userbadge", - (layoutToUse) => layoutToUse?.enableUserBadge ?? true, + layoutToUse?.enableUserBadge ?? true, "Disables/Enables the user information pill (userbadge) at the top left. Disabling this disables logging in and thus disables editing all together, effectively putting MapComplete into read-only mode." ) - this.featureSwitchSearch = featSw( + this.featureSwitchSearch = FeatureSwitchUtils.initSwitch( "fs-search", - (layoutToUse) => layoutToUse?.enableSearch ?? true, + layoutToUse?.enableSearch ?? true, "Disables/Enables the search bar" ) - this.featureSwitchBackgroundSelection = featSw( + this.featureSwitchBackgroundSelection = FeatureSwitchUtils.initSwitch( "fs-background", - (layoutToUse) => layoutToUse?.enableBackgroundLayerSelection ?? true, + layoutToUse?.enableBackgroundLayerSelection ?? true, "Disables/Enables the background layer control" ) - this.featureSwitchFilter = featSw( + this.featureSwitchFilter = FeatureSwitchUtils.initSwitch( "fs-filter", - (layoutToUse) => layoutToUse?.enableLayers ?? true, + layoutToUse?.enableLayers ?? true, "Disables/Enables the filter view" ) - this.featureSwitchAddNew = featSw( + this.featureSwitchAddNew = FeatureSwitchUtils.initSwitch( "fs-add-new", - (layoutToUse) => layoutToUse?.enableAddNewPoints ?? true, + layoutToUse?.enableAddNewPoints ?? true, "Disables/Enables the 'add new feature'-popup. (A theme without presets might not have it in the first place)" ) - this.featureSwitchWelcomeMessage = featSw( + this.featureSwitchWelcomeMessage = FeatureSwitchUtils.initSwitch( "fs-welcome-message", - () => true, + true, "Disables/enables the help menu or welcome message" ) - this.featureSwitchCommunityIndex = featSw( + this.featureSwitchCommunityIndex = FeatureSwitchUtils.initSwitch( "fs-community-index", - () => true, + true, "Disables/enables the button to get in touch with the community" ) - this.featureSwitchExtraLinkEnabled = featSw( + this.featureSwitchExtraLinkEnabled = FeatureSwitchUtils.initSwitch( "fs-iframe-popout", - (_) => true, + true, "Disables/Enables the extraLink button. By default, if in iframe mode and the welcome message is hidden, a popout button to the full mapcomplete instance is shown instead (unless disabled with this switch or another extraLink button is enabled)" ) - this.featureSwitchMoreQuests = featSw( + this.featureSwitchMoreQuests = FeatureSwitchUtils.initSwitch( "fs-more-quests", - (layoutToUse) => layoutToUse?.enableMoreQuests ?? true, + layoutToUse?.enableMoreQuests ?? true, "Disables/Enables the 'More Quests'-tab in the welcome message" ) - this.featureSwitchShareScreen = featSw( + this.featureSwitchShareScreen = FeatureSwitchUtils.initSwitch( "fs-share-screen", - (layoutToUse) => layoutToUse?.enableShareScreen ?? true, + layoutToUse?.enableShareScreen ?? true, "Disables/Enables the 'Share-screen'-tab in the welcome message" ) - this.featureSwitchGeolocation = featSw( + this.featureSwitchGeolocation = FeatureSwitchUtils.initSwitch( "fs-geolocation", - (layoutToUse) => layoutToUse?.enableGeolocation ?? true, + layoutToUse?.enableGeolocation ?? true, "Disables/Enables the geolocation button" ) - this.featureSwitchShowAllQuestions = featSw( + this.featureSwitchShowAllQuestions = FeatureSwitchUtils.initSwitch( "fs-all-questions", - (layoutToUse) => layoutToUse?.enableShowAllQuestions ?? false, + layoutToUse?.enableShowAllQuestions ?? false, "Always show all questions" ) - this.featureSwitchEnableExport = featSw( + this.featureSwitchEnableExport = FeatureSwitchUtils.initSwitch( "fs-export", - (layoutToUse) => layoutToUse?.enableExportButton ?? false, + layoutToUse?.enableExportButton ?? true, "Enable the export as GeoJSON and CSV button" ) - this.featureSwitchExportAsPdf = featSw( - "fs-pdf", - (layoutToUse) => layoutToUse?.enablePdfDownload ?? false, - "Enable the PDF download button" - ) - this.featureSwitchApiURL = QueryParameters.GetQueryParameter( - "backend", - "osm", - "The OSM backend to use - can be used to redirect mapcomplete to the testing backend when using 'osm-test'" - ) let testingDefaultValue = false if ( @@ -161,12 +176,6 @@ export default class FeatureSwitchState { "If true, shows some extra debugging help such as all the available tags on every object" ) - this.featureSwitchFakeUser = QueryParameters.GetBooleanQueryParameter( - "fake-user", - false, - "If true, 'dryrun' mode is activated and a fake user account is loaded" - ) - this.overpassUrl = QueryParameters.GetQueryParameter( "overpassUrl", (layoutToUse?.overpassUrl ?? Constants.defaultOverpassUrls).join(","), diff --git a/Logic/State/GeoLocationState.ts b/Logic/State/GeoLocationState.ts index b6bd13e24..cca92aff3 100644 --- a/Logic/State/GeoLocationState.ts +++ b/Logic/State/GeoLocationState.ts @@ -2,7 +2,7 @@ import { UIEventSource } from "../UIEventSource" import { LocalStorageSource } from "../Web/LocalStorageSource" import { QueryParameters } from "../Web/QueryParameters" -type GeolocationState = "prompt" | "requested" | "granted" | "denied" +export type GeolocationPermissionState = "prompt" | "requested" | "granted" | "denied" export interface GeoLocationPointProperties extends GeolocationCoordinates { id: "gps" @@ -21,7 +21,7 @@ export class GeoLocationState { * 'granted' means that it is granted * 'denied' means that we don't have access */ - public readonly permission: UIEventSource = new UIEventSource("prompt") + public readonly permission: UIEventSource = new UIEventSource("prompt") /** * Important to determine e.g. if we move automatically on fix or not @@ -30,8 +30,11 @@ export class GeoLocationState { /** * If true: the map will center (and re-center) to this location */ - public readonly isLocked: UIEventSource = new UIEventSource(false) + public readonly allowMoving: UIEventSource = new UIEventSource(true) + /** + * The latest GeoLocationCoordinates, as given by the WebAPI + */ public readonly currentGPSLocation: UIEventSource = new UIEventSource(undefined) @@ -72,7 +75,6 @@ export class GeoLocationState { self._previousLocationGrant.setData("false") } }) - console.log("Previous location grant:", this._previousLocationGrant.data) if (this._previousLocationGrant.data === "true") { // A previous visit successfully granted permission. Chance is high that we are allowed to use it again! @@ -87,7 +89,6 @@ export class GeoLocationState { } this.requestPermission() } - window["geolocation_state"] = this } /** diff --git a/Logic/State/LayerState.ts b/Logic/State/LayerState.ts new file mode 100644 index 000000000..4a13e3c93 --- /dev/null +++ b/Logic/State/LayerState.ts @@ -0,0 +1,119 @@ +import { UIEventSource } from "../UIEventSource" +import { GlobalFilter } from "../../Models/GlobalFilter" +import FilteredLayer from "../../Models/FilteredLayer" +import LayerConfig from "../../Models/ThemeConfig/LayerConfig" +import { OsmConnection } from "../Osm/OsmConnection" +import { Tag } from "../Tags/Tag" +import Translations from "../../UI/i18n/Translations" +import { RegexTag } from "../Tags/RegexTag" +import { Or } from "../Tags/Or" + +/** + * The layer state keeps track of: + * - Which layers are enabled + * - Which filters are used, including 'global' filters + */ +export default class LayerState { + /** + * Filters which apply onto all layers + */ + public readonly globalFilters: UIEventSource = new UIEventSource( + [], + "globalFilters" + ) + + /** + * Which layers are enabled in the current theme and what filters are applied onto them + */ + public readonly filteredLayers: ReadonlyMap + private readonly osmConnection: OsmConnection + + /** + * + * @param osmConnection + * @param layers + * @param context: the context, probably the name of the theme. Used to disambiguate the upstream user preference + */ + constructor(osmConnection: OsmConnection, layers: LayerConfig[], context: string) { + this.osmConnection = osmConnection + const filteredLayers = new Map() + for (const layer of layers) { + filteredLayers.set( + layer.id, + FilteredLayer.initLinkedState(layer, context, this.osmConnection) + ) + } + this.filteredLayers = filteredLayers + layers.forEach((l) => LayerState.linkFilterStates(l, filteredLayers)) + } + + /** + * Sets the global filter which looks to the 'level'-tag. + * Only features with the given 'level' will be shown. + * + * If undefined is passed, _all_ levels will be shown + * @param level + */ + public setLevelFilter(level?: string) { + // Remove all previous + const l = this.globalFilters.data.length + this.globalFilters.data = this.globalFilters.data.filter((f) => f.id !== "level") + if (!level) { + if (l !== this.globalFilters.data.length) { + this.globalFilters.ping() + } + return + } + const t = Translations.t.general.levelSelection + const conditionsOrred = [ + new Tag("level", "" + level), + new RegexTag("level", new RegExp("(.*;)?" + level + "(;.*)?")), + ] + if(level === "0") { + conditionsOrred.push(new Tag("level", "")) // No level tag is the same as level '0' + } + console.log("Setting levels filter to", conditionsOrred) + this.globalFilters.data.push({ + id: "level", + state: level, + osmTags: new Or(conditionsOrred), + onNewPoint: { + tags: [new Tag("level", level)], + icon: "./assets/svg/elevator.svg", + confirmAddNew: t.confirmLevel.PartialSubs({ level }), + safetyCheck: t.addNewOnLevel.Subs({ level }), + }, + }) + this.globalFilters.ping() + } + + /** + * Some layers copy the filter state of another layer - this is quite often the case for 'sibling'-layers, + * (where two variations of the same layer are used, e.g. a specific type of shop on all zoom levels and all shops on high zoom). + * + * This methods links those states for the given layer + */ + private static linkFilterStates( + layer: LayerConfig, + filteredLayers: Map + ) { + if (layer.filterIsSameAs === undefined) { + return + } + const toReuse = filteredLayers.get(layer.filterIsSameAs) + if (toReuse === undefined) { + throw ( + "Error in layer " + + layer.id + + ": it defines that it should be use the filters of " + + layer.filterIsSameAs + + ", but this layer was not loaded" + ) + } + console.warn( + "Linking filter and isDisplayed-states of " + layer.id + " and " + layer.filterIsSameAs + ) + const copy = new FilteredLayer(layer, toReuse.appliedFilters, toReuse.isDisplayed) + filteredLayers.set(layer.id, copy) + } +} diff --git a/Logic/State/MapState.ts b/Logic/State/MapState.ts deleted file mode 100644 index 121e82ff9..000000000 --- a/Logic/State/MapState.ts +++ /dev/null @@ -1,542 +0,0 @@ -import UserRelatedState from "./UserRelatedState" -import { Store, Stores, UIEventSource } from "../UIEventSource" -import BaseLayer from "../../Models/BaseLayer" -import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import AvailableBaseLayers from "../Actors/AvailableBaseLayers" -import Attribution from "../../UI/BigComponents/Attribution" -import Minimap, { MinimapObj } from "../../UI/Base/Minimap" -import { Tiles } from "../../Models/TileRange" -import BaseUIElement from "../../UI/BaseUIElement" -import FilteredLayer, { FilterState } from "../../Models/FilteredLayer" -import TilesourceConfig from "../../Models/ThemeConfig/TilesourceConfig" -import { QueryParameters } from "../Web/QueryParameters" -import ShowOverlayLayer from "../../UI/ShowDataLayer/ShowOverlayLayer" -import { FeatureSourceForLayer, Tiled } from "../FeatureSource/FeatureSource" -import SimpleFeatureSource from "../FeatureSource/Sources/SimpleFeatureSource" -import { LocalStorageSource } from "../Web/LocalStorageSource" -import { GeoOperations } from "../GeoOperations" -import TitleHandler from "../Actors/TitleHandler" -import { BBox } from "../BBox" -import LayerConfig from "../../Models/ThemeConfig/LayerConfig" -import { TiledStaticFeatureSource } from "../FeatureSource/Sources/StaticFeatureSource" -import { Translation, TypedTranslation } from "../../UI/i18n/Translation" -import { Tag } from "../Tags/Tag" -import { OsmConnection } from "../Osm/OsmConnection" -import { Feature, LineString } from "geojson" -import { OsmTags } from "../../Models/OsmFeature" - -export interface GlobalFilter { - filter: FilterState - id: string - onNewPoint: { - safetyCheck: Translation - confirmAddNew: TypedTranslation<{ preset: Translation }> - tags: Tag[] - } -} - -/** - * Contains all the leaflet-map related state - */ -export default class MapState extends UserRelatedState { - /** - The leaflet instance of the big basemap - */ - public leafletMap = new UIEventSource(undefined, "leafletmap") - /** - * A list of currently available background layers - */ - public availableBackgroundLayers: Store - - /** - * The current background layer - */ - public backgroundLayer: UIEventSource - /** - * Last location where a click was registered - */ - public readonly LastClickLocation: UIEventSource<{ - lat: number - lon: number - }> = new UIEventSource<{ lat: number; lon: number }>(undefined) - - /** - * The bounds of the current map view - */ - public currentView: FeatureSourceForLayer & Tiled - /** - * The location as delivered by the GPS - */ - public currentUserLocation: SimpleFeatureSource - - /** - * All previously visited points, with their metadata - */ - public historicalUserLocations: SimpleFeatureSource - /** - * The number of seconds that the GPS-locations are stored in memory. - * Time in seconds - */ - public gpsLocationHistoryRetentionTime = new UIEventSource( - 7 * 24 * 60 * 60, - "gps_location_retention" - ) - /** - * A featureSource containing a single linestring which has the GPS-history of the user. - * However, metadata (such as when every single point was visited) is lost here (but is kept in `historicalUserLocations`. - * Note that this featureSource is _derived_ from 'historicalUserLocations' - */ - public historicalUserLocationsTrack: FeatureSourceForLayer & Tiled - - /** - * A feature source containing the current home location of the user - */ - public homeLocation: FeatureSourceForLayer & Tiled - - /** - * A builtin layer which contains the selected element. - * Loads 'selected_element.json' - * This _might_ contain multiple points, e.g. every center of a multipolygon - */ - public selectedElementsLayer: FeatureSourceForLayer & Tiled - - public readonly mainMapObject: BaseUIElement & MinimapObj - - /** - * Which layers are enabled in the current theme and what filters are applied onto them - */ - public filteredLayers: UIEventSource = new UIEventSource( - [], - "filteredLayers" - ) - - /** - * Filters which apply onto all layers - */ - public globalFilters: UIEventSource = new UIEventSource([], "globalFilters") - - /** - * Which overlays are shown - */ - public overlayToggles: { config: TilesourceConfig; isDisplayed: UIEventSource }[] - - constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) { - super(layoutToUse, options) - - this.availableBackgroundLayers = AvailableBaseLayers.AvailableLayersAt(this.locationControl) - - let defaultLayer = AvailableBaseLayers.osmCarto - const available = this.availableBackgroundLayers.data - for (const layer of available) { - if (this.backgroundLayerId.data === layer.id) { - defaultLayer = layer - } - } - const self = this - this.backgroundLayer = new UIEventSource(defaultLayer) - this.backgroundLayer.addCallbackAndRunD((layer) => self.backgroundLayerId.setData(layer.id)) - - const attr = new Attribution( - this.locationControl, - this.osmConnection.userDetails, - this.layoutToUse, - this.currentBounds - ) - - // Will write into this.leafletMap - this.mainMapObject = Minimap.createMiniMap({ - background: this.backgroundLayer, - location: this.locationControl, - leafletMap: this.leafletMap, - bounds: this.currentBounds, - attribution: attr, - lastClickLocation: this.LastClickLocation, - }) - - this.overlayToggles = - this.layoutToUse?.tileLayerSources - ?.filter((c) => c.name !== undefined) - ?.map((c) => ({ - config: c, - isDisplayed: QueryParameters.GetBooleanQueryParameter( - "overlay-" + c.id, - c.defaultState, - "Wether or not the overlay " + c.id + " is shown" - ), - })) ?? [] - this.filteredLayers = new UIEventSource( - MapState.InitializeFilteredLayers(this.layoutToUse, this.osmConnection) - ) - - this.lockBounds() - this.AddAllOverlaysToMap(this.leafletMap) - - this.initHomeLocation() - this.initGpsLocation() - this.initUserLocationTrail() - this.initCurrentView() - this.initSelectedElement() - - new TitleHandler(this) - } - - public AddAllOverlaysToMap(leafletMap: UIEventSource) { - const initialized = new Set() - for (const overlayToggle of this.overlayToggles) { - new ShowOverlayLayer(overlayToggle.config, leafletMap, overlayToggle.isDisplayed) - initialized.add(overlayToggle.config) - } - - for (const tileLayerSource of this.layoutToUse?.tileLayerSources ?? []) { - if (initialized.has(tileLayerSource)) { - continue - } - new ShowOverlayLayer(tileLayerSource, leafletMap) - } - } - - private lockBounds() { - const layout = this.layoutToUse - if (!layout?.lockLocation) { - return - } - console.warn("Locking the bounds to ", layout.lockLocation) - this.mainMapObject.installBounds( - new BBox(layout.lockLocation), - this.featureSwitchIsTesting.data - ) - } - - private initCurrentView() { - let currentViewLayer: FilteredLayer = this.filteredLayers.data.filter( - (l) => l.layerDef.id === "current_view" - )[0] - - if (currentViewLayer === undefined) { - // This layer is not needed by the theme and thus unloaded - return - } - - let i = 0 - const self = this - const features: Store<{ feature: any; freshness: Date }[]> = this.currentBounds.map( - (bounds) => { - if (bounds === undefined) { - return [] - } - i++ - const feature = { - freshness: new Date(), - feature: { - type: "Feature", - properties: { - id: "current_view-" + i, - current_view: "yes", - zoom: "" + self.locationControl.data.zoom, - }, - geometry: { - type: "Polygon", - coordinates: [ - [ - [bounds.maxLon, bounds.maxLat], - [bounds.minLon, bounds.maxLat], - [bounds.minLon, bounds.minLat], - [bounds.maxLon, bounds.minLat], - [bounds.maxLon, bounds.maxLat], - ], - ], - }, - }, - } - return [feature] - } - ) - - this.currentView = new TiledStaticFeatureSource(features, currentViewLayer) - } - - private initGpsLocation() { - // Initialize the gps layer data. This is emtpy for now, the actual writing happens in the Geolocationhandler - const gpsLayerDef: FilteredLayer = this.filteredLayers.data.filter( - (l) => l.layerDef.id === "gps_location" - )[0] - if (gpsLayerDef === undefined) { - return - } - this.currentUserLocation = new SimpleFeatureSource(gpsLayerDef, Tiles.tile_index(0, 0, 0)) - } - - private initSelectedElement() { - const layerDef: FilteredLayer = this.filteredLayers.data.filter( - (l) => l.layerDef.id === "selected_element" - )[0] - const empty = [] - const store = this.selectedElement.map((feature) => { - if (feature === undefined || feature === null) { - return empty - } - return [ - { - feature: { - type: "Feature", - properties: { - selected: "yes", - id: "selected" + feature.properties.id, - }, - geometry: feature.geometry, - }, - freshness: new Date(), - }, - ] - }) - this.selectedElementsLayer = new TiledStaticFeatureSource(store, layerDef) - } - - private initUserLocationTrail() { - const features = LocalStorageSource.GetParsed<{ feature: any; freshness: Date }[]>( - "gps_location_history", - [] - ) - const now = new Date().getTime() - features.data = features.data - .map((ff) => ({ feature: ff.feature, freshness: new Date(ff.freshness) })) - .filter( - (ff) => - now - ff.freshness.getTime() < 1000 * this.gpsLocationHistoryRetentionTime.data - ) - features.ping() - const self = this - let i = 0 - this.currentUserLocation?.features?.addCallbackAndRunD(([location]) => { - if (location === undefined) { - return - } - - const previousLocation = features.data[features.data.length - 1] - if (previousLocation !== undefined) { - const d = GeoOperations.distanceBetween( - previousLocation.feature.geometry.coordinates, - location.feature.geometry.coordinates - ) - let timeDiff = Number.MAX_VALUE // in seconds - const olderLocation = features.data[features.data.length - 2] - if (olderLocation !== undefined) { - timeDiff = - (new Date(previousLocation.freshness).getTime() - - new Date(olderLocation.freshness).getTime()) / - 1000 - } - if (d < 20 && timeDiff < 60) { - // Do not append changes less then 20m - it's probably noise anyway - return - } - } - - const feature = JSON.parse(JSON.stringify(location.feature)) - feature.properties.id = "gps/" + features.data.length - i++ - features.data.push({ feature, freshness: new Date() }) - features.ping() - }) - - let gpsLayerDef: FilteredLayer = this.filteredLayers.data.filter( - (l) => l.layerDef.id === "gps_location_history" - )[0] - if (gpsLayerDef !== undefined) { - this.historicalUserLocations = new SimpleFeatureSource( - gpsLayerDef, - Tiles.tile_index(0, 0, 0), - features - ) - this.changes.setHistoricalUserLocations(this.historicalUserLocations) - } - - const asLine = features.map((allPoints) => { - if (allPoints === undefined || allPoints.length < 2) { - return [] - } - - const feature: Feature = { - type: "Feature", - properties: { - id: "location_track", - "_date:now": new Date().toISOString(), - }, - geometry: { - type: "LineString", - coordinates: allPoints.map((ff) => ff.feature.geometry.coordinates), - }, - } - - self.allElements.ContainingFeatures.set(feature.properties.id, feature) - - return [ - { - feature, - freshness: new Date(), - }, - ] - }) - let gpsLineLayerDef: FilteredLayer = this.filteredLayers.data.filter( - (l) => l.layerDef.id === "gps_track" - )[0] - if (gpsLineLayerDef !== undefined) { - this.historicalUserLocationsTrack = new TiledStaticFeatureSource( - asLine, - gpsLineLayerDef - ) - } - } - - private initHomeLocation() { - const empty = [] - const feature = Stores.ListStabilized( - this.osmConnection.userDetails.map((userDetails) => { - if (userDetails === undefined) { - return undefined - } - const home = userDetails.home - if (home === undefined) { - return undefined - } - return [home.lon, home.lat] - }) - ).map((homeLonLat) => { - if (homeLonLat === undefined) { - return empty - } - return [ - { - feature: { - type: "Feature", - properties: { - id: "home", - "user:home": "yes", - _lon: homeLonLat[0], - _lat: homeLonLat[1], - }, - geometry: { - type: "Point", - coordinates: homeLonLat, - }, - }, - freshness: new Date(), - }, - ] - }) - - const flayer = this.filteredLayers.data.filter((l) => l.layerDef.id === "home_location")[0] - if (flayer !== undefined) { - this.homeLocation = new TiledStaticFeatureSource(feature, flayer) - } - } - - private static getPref( - osmConnection: OsmConnection, - key: string, - layer: LayerConfig - ): UIEventSource { - return osmConnection.GetPreference(key, layer.shownByDefault + "").sync( - (v) => { - if (v === undefined) { - return undefined - } - return v === "true" - }, - [], - (b) => { - if (b === undefined) { - return undefined - } - return "" + b - } - ) - } - - public static InitializeFilteredLayers( - layoutToUse: { layers: LayerConfig[]; id: string }, - osmConnection: OsmConnection - ): FilteredLayer[] { - if (layoutToUse === undefined) { - return [] - } - const flayers: FilteredLayer[] = [] - for (const layer of layoutToUse.layers) { - let isDisplayed: UIEventSource - if (layer.syncSelection === "local") { - isDisplayed = LocalStorageSource.GetParsed( - layoutToUse.id + "-layer-" + layer.id + "-enabled", - layer.shownByDefault - ) - } else if (layer.syncSelection === "theme-only") { - isDisplayed = MapState.getPref( - osmConnection, - layoutToUse.id + "-layer-" + layer.id + "-enabled", - layer - ) - } else if (layer.syncSelection === "global") { - isDisplayed = MapState.getPref( - osmConnection, - "layer-" + layer.id + "-enabled", - layer - ) - } else { - isDisplayed = QueryParameters.GetBooleanQueryParameter( - "layer-" + layer.id, - layer.shownByDefault, - "Wether or not layer " + layer.id + " is shown" - ) - } - - const flayer: FilteredLayer = { - isDisplayed, - layerDef: layer, - appliedFilters: new UIEventSource>( - new Map() - ), - } - layer.filters.forEach((filterConfig) => { - const stateSrc = filterConfig.initState() - - stateSrc.addCallbackAndRun((state) => - flayer.appliedFilters.data.set(filterConfig.id, state) - ) - flayer.appliedFilters - .map((dict) => dict.get(filterConfig.id)) - .addCallback((state) => stateSrc.setData(state)) - }) - - flayers.push(flayer) - } - - for (const layer of layoutToUse.layers) { - if (layer.filterIsSameAs === undefined) { - continue - } - const toReuse = flayers.find((l) => l.layerDef.id === layer.filterIsSameAs) - if (toReuse === undefined) { - throw ( - "Error in layer " + - layer.id + - ": it defines that it should be use the filters of " + - layer.filterIsSameAs + - ", but this layer was not loaded" - ) - } - console.warn( - "Linking filter and isDisplayed-states of " + - layer.id + - " and " + - layer.filterIsSameAs - ) - const selfLayer = flayers.findIndex((l) => l.layerDef.id === layer.id) - flayers[selfLayer] = { - isDisplayed: toReuse.isDisplayed, - layerDef: layer, - appliedFilters: toReuse.appliedFilters, - } - } - - return flayers - } -} diff --git a/Logic/State/UserRelatedState.ts b/Logic/State/UserRelatedState.ts index cbd0d889a..703242c59 100644 --- a/Logic/State/UserRelatedState.ts +++ b/Logic/State/UserRelatedState.ts @@ -1,60 +1,67 @@ import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" -import { OsmConnection } from "../Osm/OsmConnection" -import { MangroveIdentity } from "../Web/MangroveReviews" -import { Store, UIEventSource } from "../UIEventSource" -import { QueryParameters } from "../Web/QueryParameters" +import {OsmConnection} from "../Osm/OsmConnection" +import {MangroveIdentity} from "../Web/MangroveReviews" +import {Store, Stores, UIEventSource} from "../UIEventSource" +import StaticFeatureSource from "../FeatureSource/Sources/StaticFeatureSource" +import {FeatureSource} from "../FeatureSource/FeatureSource" +import {Feature} from "geojson" +import {Utils} from "../../Utils" +import translators from "../../assets/translators.json" +import codeContributors from "../../assets/contributors.json" +import LayerConfig from "../../Models/ThemeConfig/LayerConfig" +import {LayerConfigJson} from "../../Models/ThemeConfig/Json/LayerConfigJson" +import usersettings from "../../assets/generated/layers/usersettings.json" import Locale from "../../UI/i18n/Locale" -import ElementsState from "./ElementsState" -import SelectedElementTagsUpdater from "../Actors/SelectedElementTagsUpdater" -import { Changes } from "../Osm/Changes" -import ChangeToElementsActor from "../Actors/ChangeToElementsActor" -import PendingChangesUploader from "../Actors/PendingChangesUploader" -import Maproulette from "../Maproulette" +import LinkToWeblate from "../../UI/Base/LinkToWeblate" +import FeatureSwitchState from "./FeatureSwitchState" +import Constants from "../../Models/Constants"; /** * The part of the state which keeps track of user-related stuff, e.g. the OSM-connection, * which layers they enabled, ... */ -export default class UserRelatedState extends ElementsState { +export default class UserRelatedState { + public static readonly usersettingsConfig = UserRelatedState.initUserRelatedState() + public static readonly availableUserSettingsIds: string[] = + UserRelatedState.usersettingsConfig?.tagRenderings?.map((tr) => tr.id) ?? [] /** The user credentials */ public osmConnection: OsmConnection - /** - THe change handler - */ - public changes: Changes /** * The key for mangrove */ - public mangroveIdentity: MangroveIdentity - - /** - * Maproulette connection - */ - public maprouletteConnection: Maproulette - + public readonly mangroveIdentity: MangroveIdentity public readonly installedUserThemes: Store - public readonly showAllQuestionsAtOnce: UIEventSource + public static readonly SHOW_TAGS_VALUES = ["always","yes","full"] as const + public readonly showTags: UIEventSource<"no" | undefined | "always" | "yes" | "full">; + public readonly homeLocation: FeatureSource + public readonly language: UIEventSource + /** + * The number of seconds that the GPS-locations are stored in memory. + * Time in seconds + */ + public readonly gpsLocationHistoryRetentionTime = new UIEventSource( + 7 * 24 * 60 * 60, + "gps_location_retention" + ) + /** + * Preferences as tags exposes many preferences and state properties as record. + * This is used to bridge the internal state with the usersettings.json layerconfig file + */ + public readonly preferencesAsTags: UIEventSource> - constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) { - super(layoutToUse) - - this.osmConnection = new OsmConnection({ - dryRun: this.featureSwitchIsTesting, - fakeUser: this.featureSwitchFakeUser.data, - oauth_token: QueryParameters.GetQueryParameter( - "oauth_token", - undefined, - "Used to complete the login" - ), - osmConfiguration: <"osm" | "osm-test">this.featureSwitchApiURL.data, - attemptLogin: options?.attemptLogin, - }) + constructor( + osmConnection: OsmConnection, + availableLanguages?: string[], + layout?: LayoutConfig, + featureSwitches?: FeatureSwitchState + ) { + this.osmConnection = osmConnection { const translationMode: UIEventSource = - this.osmConnection.GetPreference("translation-mode") + this.osmConnection.GetPreference("translation-mode", "false") translationMode.addCallbackAndRunD((mode) => { mode = mode.toLowerCase() if (mode === "true" || mode === "yes") { @@ -72,60 +79,49 @@ export default class UserRelatedState extends ElementsState { }) } - this.changes = new Changes(this, layoutToUse?.isLeftRightSensitive() ?? false) this.showAllQuestionsAtOnce = UIEventSource.asBoolean( this.osmConnection.GetPreference("show-all-questions", "false", { documentation: "Either 'true' or 'false'. If set, all questions will be shown all at once", }) ) - new ChangeToElementsActor(this.changes, this.allElements) - new PendingChangesUploader(this.changes, this.selectedElement) + this.language = this.osmConnection.GetPreference("language") + this.showTags = >this.osmConnection.GetPreference("show_tags") this.mangroveIdentity = new MangroveIdentity( this.osmConnection.GetLongPreference("identity", "mangrove") ) - this.maprouletteConnection = new Maproulette() + this.InitializeLanguage(availableLanguages) - if (layoutToUse?.hideFromOverview) { - this.osmConnection.isLoggedIn.addCallbackAndRunD((loggedIn) => { - if (loggedIn) { - this.osmConnection - .GetPreference("hidden-theme-" + layoutToUse?.id + "-enabled") - .setData("true") - return true - } - }) - } - - if (this.layoutToUse !== undefined && !this.layoutToUse.official) { - console.log("Marking unofficial theme as visited") - this.osmConnection.GetLongPreference("unofficial-theme-" + this.layoutToUse.id).setData( - JSON.stringify({ - id: this.layoutToUse.id, - icon: this.layoutToUse.icon, - title: this.layoutToUse.title.translations, - shortDescription: this.layoutToUse.shortDescription.translations, - definition: this.layoutToUse["definition"], - }) - ) - } - - this.InitializeLanguage() - new SelectedElementTagsUpdater(this) this.installedUserThemes = this.InitInstalledUserThemes() + + this.homeLocation = this.initHomeLocation() + + this.preferencesAsTags = this.initAmendedPrefs(layout, featureSwitches) + } + + private static initUserRelatedState(): LayerConfig { + try{ + + return new LayerConfig( + usersettings, + "userinformationpanel" + ) + }catch(e){ + return undefined + } } public GetUnofficialTheme(id: string): | { - id: string - icon: string - title: any - shortDescription: any - definition?: any - isOfficial: boolean - } + id: string + icon: string + title: any + shortDescription: any + definition?: any + isOfficial: boolean + } | undefined { console.log("GETTING UNOFFICIAL THEME") const pref = this.osmConnection.GetLongPreference("unofficial-theme-" + id) @@ -150,8 +146,8 @@ export default class UserRelatedState extends ElementsState { } catch (e) { console.warn( "Removing theme " + - id + - " as it could not be parsed from the preferences; the content is:", + id + + " as it could not be parsed from the preferences; the content is:", str ) pref.setData(null) @@ -159,26 +155,50 @@ export default class UserRelatedState extends ElementsState { } } - private InitializeLanguage() { - const layoutToUse = this.layoutToUse - Locale.language.syncWith(this.osmConnection.GetPreference("language")) + public markLayoutAsVisited(layout: LayoutConfig) { + if (!layout) { + console.error("Trying to mark a layout as visited, but ", layout, " got passed") + return + } + if (layout.hideFromOverview) { + this.osmConnection.isLoggedIn.addCallbackAndRunD((loggedIn) => { + if (loggedIn) { + this.osmConnection + .GetPreference("hidden-theme-" + layout?.id + "-enabled") + .setData("true") + return true + } + }) + } + if (!layout.official) { + this.osmConnection.GetLongPreference("unofficial-theme-" + layout.id).setData( + JSON.stringify({ + id: layout.id, + icon: layout.icon, + title: layout.title.translations, + shortDescription: layout.shortDescription.translations, + definition: layout["definition"], + }) + ) + } + } + + private InitializeLanguage(availableLanguages?: string[]) { + this.language.addCallbackAndRunD(language => Locale.language.setData(language)) Locale.language.addCallback((currentLanguage) => { - if (layoutToUse === undefined) { - return - } if (Locale.showLinkToWeblate.data) { return true // Disable auto switching as we are in translators mode } - if (this.layoutToUse.language.indexOf(currentLanguage) < 0) { + if (availableLanguages?.indexOf(currentLanguage) < 0) { console.log( "Resetting language to", - layoutToUse.language[0], + availableLanguages[0], "as", currentLanguage, " is unsupported" ) // The current language is not supported -> switch to a supported one - Locale.language.setData(layoutToUse.language[0]) + Locale.language.setData(availableLanguages[0]) } }) Locale.language.ping() @@ -193,4 +213,185 @@ export default class UserRelatedState extends ElementsState { .map((k) => k.substring(prefix.length, k.length - postfix.length)) ) } + + private initHomeLocation(): FeatureSource { + const empty = [] + const feature: Store = Stores.ListStabilized( + this.osmConnection.userDetails.map((userDetails) => { + if (userDetails === undefined) { + return undefined + } + const home = userDetails.home + if (home === undefined) { + return undefined + } + return [home.lon, home.lat] + }) + ).map((homeLonLat) => { + if (homeLonLat === undefined) { + return empty + } + return [ + { + type: "Feature", + properties: { + id: "home", + "user:home": "yes", + _lon: homeLonLat[0], + _lat: homeLonLat[1], + }, + geometry: { + type: "Point", + coordinates: homeLonLat, + }, + }, + ] + }) + return new StaticFeatureSource(feature) + } + + /** + * Initialize the 'amended preferences'. + * This is inherently a dirty and chaotic method, as it shoves many properties into this EventSourcd + * */ + private initAmendedPrefs( + layout?: LayoutConfig, + featureSwitches?: FeatureSwitchState + ): UIEventSource> { + const amendedPrefs = new UIEventSource>({ + _theme: layout?.id, + _backend: this.osmConnection.Backend(), + _applicationOpened: new Date().toISOString(), + _supports_sharing: (typeof window === "undefined") ? "no" : (window.navigator.share ? "yes" : "no") + }) + + for (const key in Constants.userJourney) { + amendedPrefs.data["__userjourney_" + key] = Constants.userJourney[key] + } + + const osmConnection = this.osmConnection + osmConnection.preferencesHandler.preferences.addCallback((newPrefs) => { + for (const k in newPrefs) { + amendedPrefs.data[k] = newPrefs[k] + } + amendedPrefs.ping() + }) + const usersettingsConfig = UserRelatedState.usersettingsConfig + const translationMode = osmConnection.GetPreference("translation-mode") + Locale.language.mapD( + (language) => { + amendedPrefs.data["_language"] = language + const trmode = translationMode.data + if ((trmode === "true" || trmode === "mobile") && layout !== undefined) { + const missing = layout.missingTranslations() + const total = missing.total + + const untranslated = missing.untranslated.get(language) ?? [] + const hasMissingTheme = untranslated.some((k) => k.startsWith("themes:")) + const missingLayers = Utils.Dedup( + untranslated + .filter((k) => k.startsWith("layers:")) + .map((k) => k.slice("layers:".length).split(".")[0]) + ) + + const zenLinks: { link: string; id: string }[] = Utils.NoNull([ + hasMissingTheme + ? { + id: "theme:" + layout.id, + link: LinkToWeblate.hrefToWeblateZen( + language, + "themes", + layout.id + ), + } + : undefined, + ...missingLayers.map((id) => ({ + id: "layer:" + id, + link: LinkToWeblate.hrefToWeblateZen(language, "layers", id), + })), + ]) + const untranslated_count = untranslated.length + amendedPrefs.data["_translation_total"] = "" + total + amendedPrefs.data["_translation_translated_count"] = + "" + (total - untranslated_count) + amendedPrefs.data["_translation_percentage"] = + "" + Math.floor((100 * (total - untranslated_count)) / total) + amendedPrefs.data["_translation_links"] = JSON.stringify(zenLinks) + } + amendedPrefs.ping() + }, + [translationMode] + ) + osmConnection.userDetails.addCallback((userDetails) => { + for (const k in userDetails) { + amendedPrefs.data["_" + k] = "" + userDetails[k] + } + + for (const [name, code, _] of usersettingsConfig.calculatedTags) { + try { + let result = new Function("feat", "return " + code + ";")({ + properties: amendedPrefs.data, + }) + if (result !== undefined && result !== "" && result !== null) { + if (typeof result !== "string") { + result = JSON.stringify(result) + } + amendedPrefs.data[name] = result + } + } catch (e) { + console.error( + "Calculating a tag for userprofile-settings failed for variable", + name, + e + ) + } + } + + const simplifiedName = userDetails.name.toLowerCase().replace(/\s+/g, "") + const isTranslator = translators.contributors.find( + (c: { contributor: string; commits: number }) => { + const replaced = c.contributor.toLowerCase().replace(/\s+/g, "") + return replaced === simplifiedName + } + ) + if (isTranslator) { + amendedPrefs.data["_translation_contributions"] = "" + isTranslator.commits + } + const isCodeContributor = codeContributors.contributors.find( + (c: { contributor: string; commits: number }) => { + const replaced = c.contributor.toLowerCase().replace(/\s+/g, "") + return replaced === simplifiedName + } + ) + if (isCodeContributor) { + amendedPrefs.data["_code_contributions"] = "" + isCodeContributor.commits + } + amendedPrefs.ping() + }) + + amendedPrefs.addCallbackD((tags) => { + for (const key in tags) { + if (key.startsWith("_") || key === "mapcomplete-language") { + // Language is managed seperately + continue + } + this.osmConnection.GetPreference(key, undefined, {prefix: ""}).setData(tags[key]) + } + }) + + for (const key in featureSwitches) { + if (featureSwitches[key].addCallbackAndRun) { + featureSwitches[key].addCallbackAndRun((v) => { + const oldV = amendedPrefs.data["__" + key] + if (oldV === v) { + return + } + amendedPrefs.data["__" + key] = "" + v + amendedPrefs.ping() + }) + } + } + + return amendedPrefs + } } diff --git a/Logic/Tags/And.ts b/Logic/Tags/And.ts index 507fe877b..72d04414a 100644 --- a/Logic/Tags/And.ts +++ b/Logic/Tags/And.ts @@ -39,7 +39,7 @@ export class And extends TagsFilter { return new And(ands) } - matchesProperties(tags: any): boolean { + matchesProperties(tags: Record): boolean { for (const tagsFilter of this.and) { if (!tagsFilter.matchesProperties(tags)) { return false @@ -147,7 +147,7 @@ export class And extends TagsFilter { return [].concat(...this.and.map((subkeys) => subkeys.usedTags())) } - asChange(properties: any): { k: string; v: string }[] { + asChange(properties: Record): { k: string; v: string }[] { const result = [] for (const tagsFilter of this.and) { result.push(...tagsFilter.asChange(properties)) @@ -394,7 +394,7 @@ export class And extends TagsFilter { return !this.and.some((t) => !t.isNegative()) } - visit(f: (TagsFilter: any) => void) { + visit(f: (tagsFilter: TagsFilter) => void) { f(this) this.and.forEach((sub) => sub.visit(f)) } diff --git a/Logic/Tags/ComparingTag.ts b/Logic/Tags/ComparingTag.ts index db66a1fdc..685cd2550 100644 --- a/Logic/Tags/ComparingTag.ts +++ b/Logic/Tags/ComparingTag.ts @@ -15,11 +15,11 @@ export default class ComparingTag implements TagsFilter { this._representation = representation } - asChange(properties: any): { k: string; v: string }[] { + asChange(properties: Record): { k: string; v: string }[] { throw "A comparable tag can not be used to be uploaded to OSM" } - asHumanString(linkToWiki: boolean, shorten: boolean, properties: any) { + asHumanString(linkToWiki: boolean, shorten: boolean, properties: Record) { return this._key + this._representation } @@ -44,7 +44,7 @@ export default class ComparingTag implements TagsFilter { * t.matchesProperties({key: 0}) // => true * t.matchesProperties({differentKey: 42}) // => false */ - matchesProperties(properties: any): boolean { + matchesProperties(properties: Record): boolean { return this._predicate(properties[this._key]) } diff --git a/Logic/Tags/Or.ts b/Logic/Tags/Or.ts index d2cca35a1..ad437cd8b 100644 --- a/Logic/Tags/Or.ts +++ b/Logic/Tags/Or.ts @@ -17,7 +17,7 @@ export class Or extends TagsFilter { return new Or(or) } - matchesProperties(properties: any): boolean { + matchesProperties(properties: Record): boolean { for (const tagsFilter of this.or) { if (tagsFilter.matchesProperties(properties)) { return true @@ -82,7 +82,7 @@ export class Or extends TagsFilter { return [].concat(...this.or.map((subkeys) => subkeys.usedTags())) } - asChange(properties: any): { k: string; v: string }[] { + asChange(properties: Record): { k: string; v: string }[] { const result = [] for (const tagsFilter of this.or) { result.push(...tagsFilter.asChange(properties)) @@ -260,7 +260,7 @@ export class Or extends TagsFilter { return this.or.some((t) => t.isNegative()) } - visit(f: (TagsFilter: any) => void) { + visit(f: (tagsFilter: TagsFilter) => void) { f(this) this.or.forEach((t) => t.visit(f)) } diff --git a/Logic/Tags/RegexTag.ts b/Logic/Tags/RegexTag.ts index c6f448fcb..50a17ddf8 100644 --- a/Logic/Tags/RegexTag.ts +++ b/Logic/Tags/RegexTag.ts @@ -1,5 +1,5 @@ -import { Tag } from "./Tag" -import { TagsFilter } from "./TagsFilter" +import {Tag} from "./Tag" +import {TagsFilter} from "./TagsFilter" export class RegexTag extends TagsFilter { public readonly key: RegExp | string @@ -15,7 +15,20 @@ export class RegexTag extends TagsFilter { this.matchesEmpty = RegexTag.doesMatch("", this.value) } - private static doesMatch(fromTag: string, possibleRegex: string | RegExp): boolean { + /** + * + * Checks that the value provided by the object properties (`fromTag`) match the specified regex `possibleRegex + * + * RegexTag.doesMatch("abc", /abc/) // => true + * RegexTag.doesMatch("ab", /abc/) // => false + * RegexTag.doesMatch("", /.+/) // => false + * RegexTag.doesMatch("", new RegExp(".*")) // => true + * + * @param fromTag + * @param possibleRegex + * @private + */ + private static doesMatch(fromTag: string | number, possibleRegex: string | RegExp): boolean { if (fromTag === undefined) { return } @@ -25,11 +38,8 @@ export class RegexTag extends TagsFilter { if (typeof possibleRegex === "string") { return fromTag === possibleRegex } - if (typeof fromTag.match !== "function") { - console.error("Error: fromTag is not a regex: ", fromTag, possibleRegex) - throw "Error: fromTag is not a regex: " + fromTag + possibleRegex - } - return fromTag.match(possibleRegex) !== null + return possibleRegex.test(fromTag) + } private static source(r: string | RegExp) { @@ -125,10 +135,50 @@ export class RegexTag extends TagsFilter { * * new RegexTag("key","value").matchesProperties({"otherkey":"value"}) // => false * new RegexTag("key","value",true).matchesProperties({"otherkey":"something"}) // => true + * + * const v: string = {someJson: ""} + * new RegexTag("key", new RegExp(".*")).matchesProperties({"key": v}) // => true + * new RegexTag("key", new RegExp(".*")).matchesProperties({"key": ""}) // => true + * new RegexTag("key", new RegExp(".*")).matchesProperties({"key": null}) // => true + * new RegexTag("key", new RegExp(".*")).matchesProperties({"key": undefined}) // => true + * + * const v: string = {someJson: ""} + * new RegexTag("key", new RegExp(".+")).matchesProperties({"key": null}) // => false + * new RegexTag("key", new RegExp(".+")).matchesProperties({"key": undefined}) // => false + * new RegexTag("key", new RegExp(".+")).matchesProperties({"key": v}) // => true + * new RegexTag("key", new RegExp(".+")).matchesProperties({"key": ""}) // => false + * + * // Show work with non-string objects + * new RegexTag("key", "true").matchesProperties({"key": true}) // => true + * new RegexTag("key", "true", true).matchesProperties({"key": true}) // => false */ - matchesProperties(tags: any): boolean { + matchesProperties(tags: Record): boolean { if (typeof this.key === "string") { - const value = tags[this.key] ?? "" + let value = tags[this.key] + if(!value || value === ""){ + // No tag is known, so we assume the empty string + // If this regexTag matches the empty string, we return true, otherwise false + // (Note: if inverted, we must reverse this) + return this.invert !== this.matchesEmpty + } + + if (typeof value === "string") { + return RegexTag.doesMatch(value, this.value) != this.invert + } + + // The value under test is _not_ a string; it can be a culculated tag, thus be e.g. a number or a boolean + // It might also be an object + + if (typeof this.value !== "string") { + const regExp = this.value + if (regExp.source === ".*") { + // We match anything, and we do have some value + return !this.invert + } + } + if(typeof value !== "string"){ + value = JSON.stringify(value) + } return RegexTag.doesMatch(value, this.value) != this.invert } @@ -137,7 +187,10 @@ export class RegexTag extends TagsFilter { continue } if (RegexTag.doesMatch(key, this.key)) { - const value = tags[key] ?? "" + let value = tags[key] ?? "" + if(typeof value !== "string"){ + value = JSON.stringify(value) + } return RegexTag.doesMatch(value, this.value) != this.invert } } @@ -248,7 +301,7 @@ export class RegexTag extends TagsFilter { return [] } - asChange(properties: any): { k: string; v: string }[] { + asChange(): { k: string; v: string }[] { if (this.invert) { return [] } diff --git a/Logic/Tags/SubstitutingTag.ts b/Logic/Tags/SubstitutingTag.ts index 50ea30193..7d5435a06 100644 --- a/Logic/Tags/SubstitutingTag.ts +++ b/Logic/Tags/SubstitutingTag.ts @@ -22,7 +22,7 @@ export default class SubstitutingTag implements TagsFilter { this._invert = invert } - private static substituteString(template: string, dict: any): string { + private static substituteString(template: string, dict: Record): string { for (const k in dict) { template = template.replace(new RegExp("\\{" + k + "\\}", "g"), dict[k]) } @@ -72,7 +72,7 @@ export default class SubstitutingTag implements TagsFilter { * assign.matchesProperties({"_date:now": "2021-03-29"}) // => false * assign.matchesProperties({"some_key": "2021-03-29"}) // => false */ - matchesProperties(properties: any): boolean { + matchesProperties(properties: Record): boolean { const value = properties[this._key] if (value === undefined || value === "") { return false @@ -89,7 +89,7 @@ export default class SubstitutingTag implements TagsFilter { return [] } - asChange(properties: any): { k: string; v: string }[] { + asChange(properties: Record): { k: string; v: string }[] { if (this._invert) { throw "An inverted substituting tag can not be used to create a change" } @@ -108,7 +108,7 @@ export default class SubstitutingTag implements TagsFilter { return false } - visit(f: (TagsFilter: any) => void) { + visit(f: (tagsFilter: TagsFilter) => void) { f(this) } } diff --git a/Logic/Tags/Tag.ts b/Logic/Tags/Tag.ts index 945bd49b2..3db63a9c3 100644 --- a/Logic/Tags/Tag.ts +++ b/Logic/Tags/Tag.ts @@ -4,7 +4,6 @@ import { TagsFilter } from "./TagsFilter" export class Tag extends TagsFilter { public key: string public value: string - public static newlyCreated = new Tag("_newly_created", "yes") constructor(key: string, value: string) { super() this.key = key @@ -36,15 +35,27 @@ export class Tag extends TagsFilter { * isEmpty.matchesProperties({"other_key": "value"}) // => true * isEmpty.matchesProperties({"key": undefined}) // => true * + * const isTrue = new Tag("key": "true") + * isTrue.matchesProperties({"key":"true"}) // => true + * isTrue.matchesProperties({"key": true}) // => true */ - matchesProperties(properties: any): boolean { - const foundValue = properties[this.key] + matchesProperties(properties: Record): boolean { + let foundValue = properties[this.key] + if (foundValue === undefined && (this.value === "" || this.value === undefined)) { // The tag was not found // and it shouldn't be found! return true } - + if(typeof foundValue !== "string"){ + if(foundValue === true && (this.value === "true" || this.value === "yes" )){ + return true + } + if(foundValue === false && (this.value === "false" || this.value === "no" )){ + return true + } + foundValue = ""+foundValue + } return foundValue === this.value } @@ -62,14 +73,18 @@ export class Tag extends TagsFilter { t.asHumanString() // => "key=value" t.asHumanString(true) // => "key=value" */ - asHumanString(linkToWiki?: boolean, shorten?: boolean, currentProperties?: any) { + asHumanString( + linkToWiki?: boolean, + shorten?: boolean, + currentProperties?: Record + ) { let v = this.value if (shorten) { v = Utils.EllipsesAfter(v, 25) } - if (v === "" || (v === undefined && currentProperties !== undefined)) { + if ((v === "" || v === undefined) && currentProperties !== undefined) { // This tag will be removed if in the properties, so we indicate this with special rendering - if (currentProperties !== undefined && (currentProperties[this.key] ?? "") === "") { + if ((currentProperties[this.key] ?? "") === "") { // This tag is not present in the current properties, so this tag doesn't change anything return "" } @@ -122,7 +137,7 @@ export class Tag extends TagsFilter { return [this] } - asChange(properties: any): { k: string; v: string }[] { + asChange(): { k: string; v: string }[] { return [{ k: this.key, v: this.value }] } @@ -134,7 +149,7 @@ export class Tag extends TagsFilter { return false } - visit(f: (TagsFilter) => void) { + visit(f: (tagsFilter: TagsFilter) => void) { f(this) } } diff --git a/Logic/Tags/TagUtils.ts b/Logic/Tags/TagUtils.ts index b0cc2989b..e3f093310 100644 --- a/Logic/Tags/TagUtils.ts +++ b/Logic/Tags/TagUtils.ts @@ -21,16 +21,16 @@ export class TagUtils { [">", (a, b) => a > b], ] - static KVtoProperties(tags: Tag[]): any { - const properties = {} + static KVtoProperties(tags: Tag[]): Record { + const properties : Record = {} for (const tag of tags) { properties[tag.key] = tag.value } return properties } - static changeAsProperties(kvs: { k: string; v: string }[]): any { - const tags = {} + static changeAsProperties(kvs: { k: string; v: string }[]): Record { + const tags: Record = {} for (const kv of kvs) { tags[kv.k] = kv.v } diff --git a/Logic/Tags/TagsFilter.ts b/Logic/Tags/TagsFilter.ts index 4f8944ff3..b06158b4f 100644 --- a/Logic/Tags/TagsFilter.ts +++ b/Logic/Tags/TagsFilter.ts @@ -9,9 +9,13 @@ export abstract class TagsFilter { */ abstract shadows(other: TagsFilter): boolean - abstract matchesProperties(properties: any): boolean + abstract matchesProperties(properties: Record): boolean - abstract asHumanString(linkToWiki: boolean, shorten: boolean, properties: any): string + abstract asHumanString( + linkToWiki: boolean, + shorten: boolean, + properties: Record + ): string abstract usedKeys(): string[] @@ -27,7 +31,7 @@ export abstract class TagsFilter { * * Note: properties are the already existing tags-object. It is only used in the substituting tag */ - abstract asChange(properties: any): { k: string; v: string }[] + abstract asChange(properties: Record): { k: string; v: string }[] /** * Returns an optimized version (or self) of this tagsFilter @@ -54,5 +58,5 @@ export abstract class TagsFilter { /** * Walks the entire tree, every tagsFilter will be passed into the function once */ - abstract visit(f: (TagsFilter) => void) + abstract visit(f: (tagsFilter: TagsFilter) => void) } diff --git a/Logic/UIEventSource.ts b/Logic/UIEventSource.ts index b161f262b..c9b70de78 100644 --- a/Logic/UIEventSource.ts +++ b/Logic/UIEventSource.ts @@ -63,27 +63,10 @@ export class Stores { stable.setData(undefined) return } - const oldList = stable.data - if (oldList === list) { + if (Utils.sameList(stable.data, list)) { return } - if (oldList == list) { - return - } - if (oldList === undefined || oldList.length !== list.length) { - stable.setData(list) - return - } - - for (let i = 0; i < list.length; i++) { - if (oldList[i] !== list[i]) { - stable.setData(list) - return - } - } - - // No actual changes, so we don't do anything - return + stable.setData(list) }) return stable } @@ -93,7 +76,7 @@ export abstract class Store implements Readable { abstract readonly data: T /** - * OPtional value giving a title to the UIEventSource, mainly used for debugging + * Optional value giving a title to the UIEventSource, mainly used for debugging */ public readonly tag: string | undefined @@ -257,12 +240,19 @@ export abstract class Store implements Readable { return newSource } + /** + * Converts the uiEventSource into a promise. + * The promise will return the value of the store if the given condition evaluates to true + * @param condition: an optional condition, default to 'store.value !== undefined' + * @constructor + */ public AsPromise(condition?: (t: T) => boolean): Promise { const self = this condition = condition ?? ((t) => t !== undefined) return new Promise((resolve) => { - if (condition(self.data)) { - resolve(self.data) + const data = self.data + if (condition(data)) { + resolve(data) } else { self.addCallbackD((data) => { resolve(data) @@ -274,13 +264,15 @@ export abstract class Store implements Readable { /** * Same as 'addCallbackAndRun', added to be compatible with Svelte - * @param run - * @param invalidate */ - public subscribe(run: Subscriber & ((value: T) => void), invalidate?): Unsubscriber { + public subscribe(run: Subscriber & ((value: T) => void), _?): Unsubscriber { // We don't need to do anything with 'invalidate', see // https://github.com/sveltejs/svelte/issues/3859 - return this.addCallbackAndRun(run) + + // Note: run is wrapped in an anonymous function. 'Run' returns the value. If this value happens to be true, it would unsubscribe + return this.addCallbackAndRun((v) => { + run(v) + }) } } @@ -294,7 +286,7 @@ export class ImmutableStore extends Store { this.data = data } - addCallback(callback: (data: T) => void): () => void { + addCallback(_: (data: T) => void): () => void { // pass: data will never change return ImmutableStore.pass } @@ -313,7 +305,7 @@ export class ImmutableStore extends Store { return ImmutableStore.pass } - addCallbackD(callback: (data: T) => void): () => void { + addCallbackD(_: (data: T) => void): () => void { // pass: data will never change return ImmutableStore.pass } @@ -413,7 +405,8 @@ class MappedStore extends Store { f: (t: TIn) => T, extraStores: Store[], upstreamListenerHandler: ListenerTracker | undefined, - initialState: T + initialState: T, + onDestroy?: (f: () => void) => void ) { super() this._upstream = upstream @@ -423,6 +416,9 @@ class MappedStore extends Store { this._upstreamPingCount = upstreamListenerHandler?.pingCount this._extraStores = extraStores this.registerCallbacksToUpstream() + if(onDestroy !== undefined){ + onDestroy(() => this.unregisterFromUpstream()) + } } private _data: T @@ -683,6 +679,7 @@ export class UIEventSource extends Store implements Writable { * Given a function 'f', will construct a new UIEventSource where the contents will always be "f(this.data)' * @param f: The transforming function * @param extraSources: also trigger the update if one of these sources change + * @param onDestroy: a callback that can trigger the destroy function * * const src = new UIEventSource(10) * const store = src.map(i => i * 2) @@ -701,8 +698,8 @@ export class UIEventSource extends Store implements Writable { * srcSeen // => 21 * lastSeen // => 42 */ - public map(f: (t: T) => J, extraSources: Store[] = []): Store { - return new MappedStore(this, f, extraSources, this._callbacks, f(this.data)) + public map(f: (t: T) => J, extraSources: Store[] = [], onDestroy?: (f : () => void ) => void): Store { + return new MappedStore(this, f, extraSources, this._callbacks, f(this.data), onDestroy) } /** * Monoidal map which results in a read-only store. 'undefined' is passed 'as is' @@ -794,4 +791,14 @@ export class UIEventSource extends Store implements Writable { update(f: Updater & ((value: T) => T)): void { this.setData(f(this.data)) } + + /** + * Create a new UIEVentSource. Whenever 'source' changes, the returned UIEventSource will get this value as well. + * However, this value can be overriden without affecting source + */ + static feedFrom(store: Store): UIEventSource { + const src = new UIEventSource(store.data) + store.addCallback((t) => src.setData(t)) + return src + } } diff --git a/Logic/Web/Hash.ts b/Logic/Web/Hash.ts index f89e61630..6c3174661 100644 --- a/Logic/Web/Hash.ts +++ b/Logic/Web/Hash.ts @@ -47,14 +47,6 @@ export default class Hash { hash.setData(newValue) } - window.addEventListener("popstate", (_) => { - let newValue = window.location.hash.substr(1) - if (newValue === "") { - newValue = undefined - } - hash.setData(newValue) - }) - return hash } } diff --git a/Logic/Web/IdbLocalStorage.ts b/Logic/Web/IdbLocalStorage.ts index 2d23db76e..ec417a1f8 100644 --- a/Logic/Web/IdbLocalStorage.ts +++ b/Logic/Web/IdbLocalStorage.ts @@ -38,11 +38,12 @@ export class IdbLocalStorage { return src } - public static SetDirectly(key: string, value) { - idb.set(key, value) + public static SetDirectly(key: string, value: any): Promise { + const copy = Utils.Clone(value) + return idb.set(key, copy) } - static GetDirectly(key: string) { + static GetDirectly(key: string): Promise { return idb.get(key) } } diff --git a/Logic/Web/MangroveReviews.ts b/Logic/Web/MangroveReviews.ts index a0076e027..e2ed56e12 100644 --- a/Logic/Web/MangroveReviews.ts +++ b/Logic/Web/MangroveReviews.ts @@ -1,10 +1,8 @@ import { ImmutableStore, Store, UIEventSource } from "../UIEventSource" import { MangroveReviews, Review } from "mangrove-reviews-typescript" import { Utils } from "../../Utils" -import { Feature, Geometry, Position } from "geojson" +import { Feature, Position } from "geojson" import { GeoOperations } from "../GeoOperations" -import { OsmTags } from "../../Models/OsmFeature" -import { ElementStorage } from "../ElementStorage" export class MangroveIdentity { public readonly keypair: Store @@ -67,11 +65,9 @@ export default class FeatureReviews { private readonly _identity: MangroveIdentity private constructor( - feature: Feature, - state: { - allElements: ElementStorage - mangroveIdentity?: MangroveIdentity - }, + feature: Feature, + tagsSource: UIEventSource>, + mangroveIdentity?: MangroveIdentity, options?: { nameKey?: "name" | string fallbackName?: string @@ -80,8 +76,7 @@ export default class FeatureReviews { ) { const centerLonLat = GeoOperations.centerpointCoordinates(feature) ;[this._lon, this._lat] = centerLonLat - this._identity = - state?.mangroveIdentity ?? new MangroveIdentity(new UIEventSource(undefined)) + this._identity = mangroveIdentity ?? new MangroveIdentity(new UIEventSource(undefined)) const nameKey = options?.nameKey ?? "name" if (feature.geometry.type === "Point") { @@ -108,9 +103,7 @@ export default class FeatureReviews { this._uncertainty = options?.uncertaintyRadius ?? maxDistance } - this._name = state.allElements - .getEventSourceById(feature.properties.id) - .map((tags) => tags[nameKey] ?? options?.fallbackName) + this._name = tagsSource .map((tags) => tags[nameKey] ?? options?.fallbackName) this.subjectUri = this.ConstructSubjectUri() @@ -136,11 +129,9 @@ export default class FeatureReviews { * Construct a featureReviewsFor or fetches it from the cache */ public static construct( - feature: Feature, - state: { - allElements: ElementStorage - mangroveIdentity?: MangroveIdentity - }, + feature: Feature, + tagsSource: UIEventSource>, + mangroveIdentity?: MangroveIdentity, options?: { nameKey?: "name" | string fallbackName?: string @@ -152,7 +143,7 @@ export default class FeatureReviews { if (cached !== undefined) { return cached } - const featureReviews = new FeatureReviews(feature, state, options) + const featureReviews = new FeatureReviews(feature, tagsSource, mangroveIdentity, options) FeatureReviews._featureReviewsCache[key] = featureReviews return featureReviews } diff --git a/Logic/Web/QueryParameters.ts b/Logic/Web/QueryParameters.ts index 29726ae97..3b2fe4439 100644 --- a/Logic/Web/QueryParameters.ts +++ b/Logic/Web/QueryParameters.ts @@ -35,6 +35,14 @@ export class QueryParameters { return source } + public static SetDefaultFor(key: string, value: string) { + if (QueryParameters.defaults[key] === value) { + return + } + QueryParameters.defaults[key] = value + QueryParameters.Serialize() + } + public static GetBooleanQueryParameter( key: string, deflt: boolean, @@ -80,6 +88,11 @@ export class QueryParameters { } } + /** + * Set the query parameters of the page location + * @constructor + * @private + */ private static Serialize() { const parts = [] for (const key of QueryParameters.order) { diff --git a/Logic/Web/ThemeViewStateHashActor.ts b/Logic/Web/ThemeViewStateHashActor.ts new file mode 100644 index 000000000..c6e18b354 --- /dev/null +++ b/Logic/Web/ThemeViewStateHashActor.ts @@ -0,0 +1,180 @@ +import ThemeViewState from "../../Models/ThemeViewState"; +import Hash from "./Hash"; + +export default class ThemeViewStateHashActor { + private readonly _state: ThemeViewState; + + /** + * Converts the hash to the appropriate themeview state and, vice versa, sets the hash. + * + * As the navigator-back-button changes the hash first, this class thus also handles the 'back'-button events. + * + * Note that there is no "real" way to intercept the back button, we can only detect the removal of the hash. + * As such, we use a change in the hash to close the appropriate windows + * + * @param state + */ + constructor(state: ThemeViewState) { + this._state = state; + + // First of all, try to recover the selected element + if (Hash.hash.data) { + const hash = Hash.hash.data + this.loadStateFromHash(hash) + Hash.hash.setData(hash) // reapply the previous hash + state.indexedFeatures.featuresById.addCallbackAndRunD(_ => { + let unregister = this.loadSelectedElementFromHash(hash); + // once that we have found a matching element, we can be sure the indexedFeaturesource was popuplated and that the job is done + return unregister + }) + } + + // Register a hash change listener to correctly handle the back button + Hash.hash.addCallback(hash => { + if (!!hash) { + // There is still a hash + // We _only_ have to (at most) close the overlays in this case + const parts = hash.split(";") + if(parts.indexOf("background") < 0){ + state.guistate.backgroundLayerSelectionIsOpened.setData(false) + } + this.loadSelectedElementFromHash(hash) + } else { + this.back() + } + }) + + // At last, register callbacks on the state to update the hash when they change. + // Note: these should use 'addCallback', not 'addCallbackAndRun' + state.selectedElement.addCallback(_ => this.setHash()) + state.guistate.allToggles.forEach(({toggle, submenu}) => { + submenu?.addCallback(_ => this.setHash()) + toggle.addCallback(_ => this.setHash()); + }) + + // When all is done, set the hash. This must happen last to give the code above correct info + this.setHash() + + + } + + /** + * Selects the appropriate element + * Returns true if this method can be unregistered for the first run + * @param hash + * @private + */ + private loadSelectedElementFromHash(hash: string): boolean { + const state = this._state + const selectedElement = state.selectedElement + // state.indexedFeatures.featuresById.stabilized(250) + + hash = hash.split(";")[0] // The 'selectedElement' is always the _first_ item in the hash (if any) + + // Set the hash based on the selected element... + // ... search and select an element based on the hash + if (selectedElement.data?.properties?.id === hash) { + // We already have the correct hash + return true + } + + const found = state.indexedFeatures.featuresById.data?.get(hash) + if (!found) { + return false + } + if (found.properties.id === "last_click") { + return true + } + const layer = this._state.layout.getMatchingLayer(found.properties) + console.log( + "Setting selected element based on hash", + hash, + "; found", + found, + "got matching layer", + layer.id, + "" + ) + selectedElement.setData(found) + state.selectedLayer.setData(layer) + return true + } + + private loadStateFromHash(hash: string) { + const state = this._state + const parts = hash.split(";") + outer: for (const {toggle, name, showOverOthers, submenu} of state.guistate.allToggles) { + + for (const part of parts) { + if (part === name) { + toggle.setData(true) + continue outer + } + if (part.indexOf(":") < 0) { + continue + } + const [main, submenuValue] = part.split(":") + if (part !== main) { + continue + } + toggle.setData(true) + submenu?.setData(submenuValue) + continue outer + } + + // If we arrive here, the loop above has not found any match + toggle.setData(false) + } + + + } + + private setHash() { + const s = this._state + let h = "" + + for (const {toggle, showOverOthers, name, submenu} of s.guistate.allToggles) { + if (showOverOthers || !toggle.data) { + continue; + } + h = name + if (submenu?.data) { + h += ":" + submenu.data + } + } + + if (s.selectedElement.data !== undefined) { + h = s.selectedElement.data.properties.id + } + + for (const {toggle, showOverOthers, name, submenu} of s.guistate.allToggles) { + if (!showOverOthers || !toggle.data) { + continue; + } + if (h) { + h += ";" + name + } else { + h = name + } + if (submenu?.data) { + h += ":" + submenu.data + } + } + Hash.hash.setData(h) + + } + + private back() { + console.log("Got a back event") + const state = this._state + // history.pushState(null, null, window.location.pathname); + if (state.selectedElement.data) { + state.selectedElement.setData(undefined) + return + } + if (state.guistate.closeAll()) { + return + } + } + +} diff --git a/Logic/Web/Wikidata.ts b/Logic/Web/Wikidata.ts index 8818be52f..aed400358 100644 --- a/Logic/Web/Wikidata.ts +++ b/Logic/Web/Wikidata.ts @@ -1,5 +1,5 @@ import { Utils } from "../../Utils" -import { UIEventSource } from "../UIEventSource" +import { Store, UIEventSource } from "../UIEventSource" import * as wds from "wikidata-sdk" export class WikidataResponse { @@ -131,11 +131,10 @@ export default class Wikidata { "Lexeme:", ].map((str) => str.toLowerCase()) - private static readonly _cache = new Map< + private static readonly _storeCache = new Map< string, - UIEventSource<{ success: WikidataResponse } | { error: any }> + Store<{ success: WikidataResponse } | { error: any }> >() - /** * Same as LoadWikidataEntry, but wrapped into a UIEventSource * @param value @@ -143,14 +142,14 @@ export default class Wikidata { */ public static LoadWikidataEntry( value: string | number - ): UIEventSource<{ success: WikidataResponse } | { error: any }> { + ): Store<{ success: WikidataResponse } | { error: any }> { const key = this.ExtractKey(value) - const cached = Wikidata._cache.get(key) - if (cached !== undefined) { + const cached = Wikidata._storeCache.get(key) + if (cached) { return cached } const src = UIEventSource.FromPromiseWithErr(Wikidata.LoadWikidataEntryAsync(key)) - Wikidata._cache.set(key, src) + Wikidata._storeCache.set(key, src) return src } @@ -278,6 +277,9 @@ export default class Wikidata { * * Wikidata.ExtractKey("https://www.wikidata.org/wiki/Lexeme:L614072") // => "L614072" * Wikidata.ExtractKey("http://www.wikidata.org/entity/Q55008046") // => "Q55008046" + * Wikidata.ExtractKey("Q55008046") // => "Q55008046" + * Wikidata.ExtractKey("A55008046") // => undefined + * Wikidata.ExtractKey("Q55008046X") // => undefined */ public static ExtractKey(value: string | number): string { if (typeof value === "number") { @@ -385,11 +387,24 @@ export default class Wikidata { return result.results.bindings } + private static _cache = new Map>() + public static async LoadWikidataEntryAsync(value: string | number): Promise { + const key = "" + value + const cached = Wikidata._cache.get(key) + if (cached) { + return cached + } + const uncached = Wikidata.LoadWikidataEntryUncachedAsync(value) + Wikidata._cache.set(key, uncached) + return uncached + } /** * Loads a wikidata page * @returns the entity of the given value */ - public static async LoadWikidataEntryAsync(value: string | number): Promise { + private static async LoadWikidataEntryUncachedAsync( + value: string | number + ): Promise { const id = Wikidata.ExtractKey(value) if (id === undefined) { console.warn("Could not extract a wikidata entry from", value) diff --git a/Logic/Web/Wikipedia.ts b/Logic/Web/Wikipedia.ts index 00bc1b798..9d8b6bb09 100644 --- a/Logic/Web/Wikipedia.ts +++ b/Logic/Web/Wikipedia.ts @@ -1,9 +1,17 @@ -/** - * Some usefull utility functions around the wikipedia API - */ import { Utils } from "../../Utils" -import { UIEventSource } from "../UIEventSource" -import { WikipediaBoxOptions } from "../../UI/Wikipedia/WikipediaBox" +import Wikidata, { WikidataResponse } from "./Wikidata" +import { Store, UIEventSource } from "../UIEventSource" + +export interface FullWikipediaDetails { + articleUrl?: string + language?: string + pagename?: string + fullArticle?: string + firstParagraph?: string + restOfArticle?: string + wikidata?: WikidataResponse + title?: string +} export default class Wikipedia { /** @@ -26,11 +34,8 @@ export default class Wikipedia { private static readonly idsToRemove = ["sjabloon_zie"] - private static readonly _cache = new Map< - string, - UIEventSource<{ success: string } | { error: any }> - >() - + private static readonly _cache = new Map>() + private static _fullDetailsCache = new Map>() public readonly backend: string constructor(options?: { language?: "en" | string } | { backend?: string }) { @@ -56,23 +61,81 @@ export default class Wikipedia { } /** - * Extracts the actual pagename; returns undefined if this came from a different wikimedia entry + * Fetch all useful information for the given entity. * - * new Wikipedia({backend: "https://wiki.openstreetmap.org"}).extractPageName("https://wiki.openstreetmap.org/wiki/NL:Speelbos") // => "NL:Speelbos" - * new Wikipedia().extractPageName("https://wiki.openstreetmap.org/wiki/NL:Speelbos") // => undefined */ - public extractPageName(input: string): string | undefined { - if (!input.startsWith(this.backend)) { - return undefined + public static fetchArticleAndWikidata( + wikidataOrPageId: string, + preferedLanguage: string + ): Store { + const cachekey = preferedLanguage + wikidataOrPageId + const cached = Wikipedia._fullDetailsCache.get(cachekey) + if (cached) { + return cached } - input = input.substring(this.backend.length) + console.log("Constructing store for", cachekey) + const store = new UIEventSource({}, cachekey) + Wikipedia._fullDetailsCache.set(cachekey, store) - const matched = input.match("/?wiki/(.+)") - if (matched === undefined || matched === null) { - return undefined + // Are we dealing with a wikidata item? + const wikidataId = Wikidata.ExtractKey(wikidataOrPageId) + if (!wikidataId) { + // We are dealing with a wikipedia identifier, e.g. 'NL:articlename', 'https://nl.wikipedia.org/wiki/article', ... + const { language, pageName } = Wikipedia.extractLanguageAndName(wikidataOrPageId) + store.data.articleUrl = new Wikipedia({ language }).getPageUrl(pageName) + store.data.language = language + store.data.pagename = pageName + store.data.title = pageName + } else { + // Jup, this is a wikidata item + // Lets fetch the wikidata + store.data.title = wikidataId + Wikidata.LoadWikidataEntryAsync(wikidataId).then((wikidata) => { + store.data.wikidata = wikidata + store.ping() + // With the wikidata, we can search for the appropriate wikipedia page + const preferredLanguage = [ + preferedLanguage, + "en", + Array.from(wikidata.wikisites.keys())[0], + ] + + for (const language of preferredLanguage) { + const pagetitle = wikidata.wikisites.get(language) + if (pagetitle) { + store.data.articleUrl = new Wikipedia({ language }).getPageUrl(pagetitle) + store.data.pagename = pagetitle + store.data.language = language + store.data.title = pagetitle + store.ping() + break + } + } + }) } - const [_, pageName] = matched - return pageName + + // Now that the pageURL has been setup, we can focus on downloading the actual article + // We setup a listener. As soon as the article-URL is know, we'll fetch the actual page + // This url can either be set by the Wikidata-response or directly if we are dealing with a wikipedia-url + store.addCallbackAndRun((data) => { + if (data.language === undefined || data.pagename === undefined) { + return + } + const wikipedia = new Wikipedia({ language: data.language }) + wikipedia.GetArticleHtml(data.pagename).then((article) => { + data.fullArticle = article + const content = document.createElement("div") + content.innerHTML = article + const firstParagraph = content.getElementsByTagName("p").item(0) + data.firstParagraph = firstParagraph.innerHTML + content.removeChild(firstParagraph) + data.restOfArticle = content.innerHTML + store.ping() + }) + return true // unregister + }) + + return store } private static getBackendUrl( @@ -90,18 +153,24 @@ export default class Wikipedia { return backend } - public GetArticle( - pageName: string, - options: WikipediaBoxOptions - ): UIEventSource<{ success: string } | { error: any }> { - const key = this.backend + ":" + pageName + ":" + (options.firstParagraphOnly ?? false) - const cached = Wikipedia._cache.get(key) - if (cached !== undefined) { - return cached + /** + * Extracts the actual pagename; returns undefined if this came from a different wikimedia entry + * + * new Wikipedia({backend: "https://wiki.openstreetmap.org"}).extractPageName("https://wiki.openstreetmap.org/wiki/NL:Speelbos") // => "NL:Speelbos" + * new Wikipedia().extractPageName("https://wiki.openstreetmap.org/wiki/NL:Speelbos") // => undefined + */ + public extractPageName(input: string): string | undefined { + if (!input.startsWith(this.backend)) { + return undefined } - const v = UIEventSource.FromPromiseWithErr(this.GetArticleAsync(pageName, options)) - Wikipedia._cache.set(key, v) - return v + input = input.substring(this.backend.length) + + const matched = input.match("/?wiki/(.+)") + if (matched === undefined || matched === null) { + return undefined + } + const [_, pageName] = matched + return pageName } public getDataUrl(pageName: string): string { @@ -172,12 +241,23 @@ export default class Wikipedia { }) } - public async GetArticleAsync( - pageName: string, - options: { - firstParagraphOnly?: false | boolean + /** + * Returns the innerHTML for the given article as string. + * Some cleanup is applied to this. + * + * This method uses a static, local cache, so each article will be retrieved only once via the network + */ + public GetArticleHtml(pageName: string): Promise { + const cacheKey = this.backend + "/" + pageName + if (Wikipedia._cache.has(cacheKey)) { + return Wikipedia._cache.get(cacheKey) } - ): Promise { + const promise = this.GetArticleUncachedAsync(pageName) + Wikipedia._cache.set(cacheKey, promise) + return promise + } + + private async GetArticleUncachedAsync(pageName: string): Promise { const response = await Utils.downloadJson(this.getDataUrl(pageName)) if (response?.parse?.text === undefined) { return undefined @@ -213,10 +293,6 @@ export default class Wikipedia { link.href = `${this.backend}${link.getAttribute("href")}` }) - if (options?.firstParagraphOnly) { - return content.getElementsByTagName("p").item(0).innerHTML - } - return content.innerHTML } } diff --git a/Models/BaseLayer.ts b/Models/BaseLayer.ts deleted file mode 100644 index 1e4c2a933..000000000 --- a/Models/BaseLayer.ts +++ /dev/null @@ -1,10 +0,0 @@ -export default interface BaseLayer { - id: string - name: string - layer: () => any /*leaflet.TileLayer - not importing as it breaks scripts*/ - max_zoom: number - min_zoom: number - feature: any - isBest?: boolean - category?: "map" | "osmbasedmap" | "photo" | "historicphoto" | string -} diff --git a/Models/Constants.ts b/Models/Constants.ts index 7e44f7276..2d31e12b1 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -1,7 +1,10 @@ -import { Utils } from "../Utils" +import {Utils} from "../Utils" +import * as meta from "../package.json" + +export type PriviligedLayerType = typeof Constants.priviliged_layers[number] export default class Constants { - public static vNumber = "0.27.4" + public static vNumber = meta.version public static ImgurApiKey = "7070e7167f0a25a" public static readonly mapillary_client_token_v4 = @@ -26,31 +29,34 @@ export default class Constants { // Doesn't support nwr: "https://overpass.openstreetmap.fr/api/interpreter" ] - public static readonly added_by_default: string[] = [ + public static readonly added_by_default = [ "selected_element", "gps_location", "gps_location_history", "home_location", "gps_track", - ] - public static readonly no_include: string[] = [ + "range", + "last_click", + ] as const + /** + * Special layers which are not included in a theme by default + */ + public static readonly no_include = [ "conflation", - "left_right_style", "split_point", + "split_road", "current_view", "matchpoint", - ] + "import_candidate", + "usersettings", + ] as const /** * Layer IDs of layers which have special properties through built-in hooks */ - public static readonly priviliged_layers: string[] = [ + public static readonly priviliged_layers = [ ...Constants.added_by_default, - "type_node", - "note", - "import_candidate", - "direction", ...Constants.no_include, - ] + ] as const // The user journey states thresholds when a new feature gets unlocked public static userJourney = { @@ -65,10 +71,10 @@ export default class Constants { themeGeneratorReadOnlyUnlock: 50, themeGeneratorFullUnlock: 500, addNewPointWithUnreadMessagesUnlock: 500, - minZoomLevelToAddNewPoints: Constants.isRetina() ? 18 : 19, importHelperUnlock: 5000, } + static readonly minZoomLevelToAddNewPoint = Constants.isRetina() ? 18 : 19 /** * Used by 'PendingChangesUploader', which waits this amount of seconds to upload changes. * (Note that pendingChanges might upload sooner if the popup is closed or similar) @@ -110,6 +116,11 @@ export default class Constants { static countryCoderEndpoint: string = "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/latlon2country" public static readonly OsmPreferenceKeyPicturesLicense = "pictures-license" + /** + * These are the values that are allowed to use as 'backdrop' icon for a map pin + */ + private static readonly _defaultPinIcons = ["square", "circle", "none", "pin", "person", "plus", "ring", "star", "teardrop", "triangle", "crosshair",] as const + public static readonly defaultPinIcons: string[] = Constants._defaultPinIcons private static isRetina(): boolean { if (Utils.runningFromConsole) { @@ -120,8 +131,8 @@ export default class Constants { return ( (window.matchMedia && (window.matchMedia( - "only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx), only screen and (min-resolution: 75.6dpcm)" - ).matches || + "only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx), only screen and (min-resolution: 75.6dpcm)" + ).matches || window.matchMedia( "only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min--moz-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2)" ).matches)) || diff --git a/Models/Denomination.ts b/Models/Denomination.ts index f3466515b..c4d119ea7 100644 --- a/Models/Denomination.ts +++ b/Models/Denomination.ts @@ -23,7 +23,7 @@ export class Denomination { } this._canonicalSingular = json.canonicalDenominationSingular?.trim() - json.alternativeDenomination.forEach((v, i) => { + json.alternativeDenomination?.forEach((v, i) => { if ((v?.trim() ?? "") === "") { throw `${context}.alternativeDenomination.${i}: invalid alternative denomination: undefined, null or only whitespace` } @@ -51,12 +51,6 @@ export class Denomination { return (this._humanSingular ?? this._human).Clone() } - getToggledHuman(isSingular: Store): BaseUIElement { - if (this._humanSingular === undefined) { - return this.human - } - return new Toggle(this.humanSingular, this.human, isSingular) - } /** * Create a representation of the given value @@ -165,7 +159,7 @@ export class Denomination { return null } - isDefaultUnit(country: () => string) { + isDefaultDenomination(country: () => string) { if (this.useIfNoUnitGiven === true) { return true } diff --git a/Models/FilteredLayer.ts b/Models/FilteredLayer.ts index 3263c35ae..b84ebd663 100644 --- a/Models/FilteredLayer.ts +++ b/Models/FilteredLayer.ts @@ -1,14 +1,254 @@ -import { UIEventSource } from "../Logic/UIEventSource" +import { Store, UIEventSource } from "../Logic/UIEventSource" import LayerConfig from "./ThemeConfig/LayerConfig" +import { OsmConnection } from "../Logic/Osm/OsmConnection" +import { LocalStorageSource } from "../Logic/Web/LocalStorageSource" +import { QueryParameters } from "../Logic/Web/QueryParameters" +import { FilterConfigOption } from "./ThemeConfig/FilterConfig" import { TagsFilter } from "../Logic/Tags/TagsFilter" +import { Utils } from "../Utils" +import { TagUtils } from "../Logic/Tags/TagUtils" +import { And } from "../Logic/Tags/And" +import { GlobalFilter } from "./GlobalFilter" -export interface FilterState { - currentFilter: TagsFilter - state: string | number -} - -export default interface FilteredLayer { +export default class FilteredLayer { + /** + * Wether or not the specified layer is shown + */ readonly isDisplayed: UIEventSource - readonly appliedFilters: UIEventSource> + /** + * Maps the filter.option.id onto the actual used state. + * This state is either the chosen option (as number) or a representation of the fields + */ + readonly appliedFilters: ReadonlyMap> readonly layerDef: LayerConfig + + /** + * Indicates if some filter is set. + * If this is the case, adding a new element of this type might be a bad idea + */ + readonly hasFilter: Store + + /** + * Contains the current properties a feature should fulfill in order to match the filter + */ + readonly currentFilter: Store + + constructor( + layer: LayerConfig, + appliedFilters?: ReadonlyMap>, + isDisplayed?: UIEventSource + ) { + this.layerDef = layer + this.isDisplayed = isDisplayed ?? new UIEventSource(true) + if (!appliedFilters) { + const appliedFiltersWritable = new Map< + string, + UIEventSource + >() + for (const filter of this.layerDef.filters) { + appliedFiltersWritable.set(filter.id, new UIEventSource(undefined)) + } + appliedFilters = appliedFiltersWritable + } + this.appliedFilters = appliedFilters + + const self = this + const currentTags = new UIEventSource(undefined) + this.appliedFilters.forEach((filterSrc) => { + filterSrc.addCallbackAndRun((_) => { + currentTags.setData(self.calculateCurrentTags()) + }) + }) + this.hasFilter = currentTags.map((ct) => ct !== undefined) + this.currentFilter = currentTags + } + + public static fieldsToString(values: Record): string { + for (const key in values) { + if (values[key] === "") { + delete values[key] + } + } + return JSON.stringify(values) + } + + /** + * Creates a FilteredLayer which is tied into the QueryParameters and/or user preferences + */ + public static initLinkedState( + layer: LayerConfig, + context: string, + osmConnection: OsmConnection + ) { + let isDisplayed: UIEventSource + if (layer.syncSelection === "local") { + isDisplayed = LocalStorageSource.GetParsed( + context + "-layer-" + layer.id + "-enabled", + layer.shownByDefault + ) + } else if (layer.syncSelection === "theme-only") { + isDisplayed = FilteredLayer.getPref( + osmConnection, + context + "-layer-" + layer.id + "-enabled", + layer + ) + } else if (layer.syncSelection === "global") { + isDisplayed = FilteredLayer.getPref( + osmConnection, + "layer-" + layer.id + "-enabled", + layer + ) + } else { + isDisplayed = QueryParameters.GetBooleanQueryParameter( + "layer-" + layer.id, + layer.shownByDefault, + "Whether or not layer " + layer.id + " is shown" + ) + } + + const appliedFilters = new Map>() + for (const subfilter of layer.filters) { + appliedFilters.set(subfilter.id, subfilter.initState(layer.id)) + } + return new FilteredLayer(layer, appliedFilters, isDisplayed) + } + + private static stringToFieldProperties(value: string): Record { + const values = JSON.parse(value) + for (const key in values) { + if (values[key] === "") { + delete values[key] + } + } + return values + } + + private static fieldsToTags( + option: FilterConfigOption, + fieldstate: string | Record + ): TagsFilter | undefined { + let properties: Record + if (typeof fieldstate === "string") { + properties = FilteredLayer.stringToFieldProperties(fieldstate) + } else { + properties = fieldstate + } + const missingKeys = option.fields + .map((f) => f.name) + .filter((key) => properties[key] === undefined) + if (missingKeys.length > 0) { + return undefined + } + const tagsSpec = Utils.WalkJson(option.originalTagsSpec, (v) => { + if (typeof v !== "string") { + return v + } + + for (const key in properties) { + v = (v).replace("{" + key + "}", properties[key]) + } + + return v + }) + return TagUtils.Tag(tagsSpec) + } + + private static getPref( + osmConnection: OsmConnection, + key: string, + layer: LayerConfig + ): UIEventSource { + return osmConnection.GetPreference(key, layer.shownByDefault + "").sync( + (v) => { + if (v === undefined) { + return undefined + } + return v === "true" + }, + [], + (b) => { + if (b === undefined) { + return undefined + } + return "" + b + } + ) + } + + public disableAllFilters(): void { + this.appliedFilters.forEach((value) => value.setData(undefined)) + } + + /** + * Returns true if the given tags match + * - the current filters + * - the specified 'global filters' + * - the 'isShown'-filter set by the layer + */ + public isShown(properties: Record, globalFilters?: GlobalFilter[]): boolean { + if (properties._deleted === "yes") { + return false + } + for (const globalFilter of globalFilters ?? []) { + const neededTags = globalFilter.osmTags + if (neededTags !== undefined && !neededTags.matchesProperties(properties)) { + return false + } + } + { + const isShown: TagsFilter = this.layerDef.isShown + if (isShown !== undefined && !isShown.matchesProperties(properties)) { + return false + } + } + + { + let neededTags: TagsFilter = this.currentFilter.data + if (neededTags !== undefined && !neededTags.matchesProperties(properties)) { + return false + } + } + + return true + } + + private calculateCurrentTags(): TagsFilter { + let needed: TagsFilter[] = [] + for (const filter of this.layerDef.filters) { + const state = this.appliedFilters.get(filter.id) + if (state.data === undefined) { + continue + } + if (filter.options[0].fields.length > 0) { + // This is a filter with fields + // We calculate the fields + const fieldProperties = FilteredLayer.stringToFieldProperties(state.data) + const asTags = FilteredLayer.fieldsToTags(filter.options[0], fieldProperties) + if (asTags) { + needed.push(asTags) + } + continue + } + needed.push(filter.options[state.data].osmTags) + } + needed = Utils.NoNull(needed) + if (needed.length == 0) { + return undefined + } + let tags: TagsFilter + + if (needed.length == 1) { + tags = needed[0] + } else { + tags = new And(needed) + } + let optimized = tags.optimize() + if (optimized === true) { + return undefined + } + if (optimized === false) { + return tags + } + return optimized + } } diff --git a/Models/GlobalFilter.ts b/Models/GlobalFilter.ts new file mode 100644 index 000000000..ce837acca --- /dev/null +++ b/Models/GlobalFilter.ts @@ -0,0 +1,15 @@ +import { Translation, TypedTranslation } from "../UI/i18n/Translation" +import { Tag } from "../Logic/Tags/Tag" +import { TagsFilter } from "../Logic/Tags/TagsFilter" + +export interface GlobalFilter { + osmTags: TagsFilter + state: number | string | undefined + id: string + onNewPoint: { + safetyCheck: Translation + icon: string + confirmAddNew: TypedTranslation<{ preset: Translation }> + tags: Tag[] + } +} diff --git a/Models/LeafletMap.ts b/Models/LeafletMap.ts deleted file mode 100644 index e3f0ae850..000000000 --- a/Models/LeafletMap.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default interface LeafletMap { - getBounds(): [[number, number], [number, number]] -} diff --git a/Models/Loc.ts b/Models/Loc.ts deleted file mode 100644 index 7b78d642a..000000000 --- a/Models/Loc.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default interface Loc { - lat: number - lon: number - zoom: number -} diff --git a/Models/MapProperties.ts b/Models/MapProperties.ts new file mode 100644 index 000000000..a6b4058bc --- /dev/null +++ b/Models/MapProperties.ts @@ -0,0 +1,22 @@ +import { Store, UIEventSource } from "../Logic/UIEventSource" +import { BBox } from "../Logic/BBox" +import { RasterLayerPolygon } from "./RasterLayers" + +export interface MapProperties { + readonly location: UIEventSource<{ lon: number; lat: number }> + readonly zoom: UIEventSource + readonly minzoom: UIEventSource + readonly maxzoom: UIEventSource + readonly bounds: UIEventSource + readonly rasterLayer: UIEventSource + readonly maxbounds: UIEventSource + readonly allowMoving: UIEventSource + + readonly lastClickLocation: Store<{ lon: number; lat: number }> + + readonly allowZooming: UIEventSource +} + +export interface ExportableMap { + exportAsPng(dpiFactor: number): Promise +} diff --git a/Models/MenuState.ts b/Models/MenuState.ts new file mode 100644 index 000000000..1c264e17d --- /dev/null +++ b/Models/MenuState.ts @@ -0,0 +1,137 @@ +import LayerConfig from "./ThemeConfig/LayerConfig" +import {UIEventSource} from "../Logic/UIEventSource" +import UserRelatedState from "../Logic/State/UserRelatedState" +import {Utils} from "../Utils" +import {LocalStorageSource} from "../Logic/Web/LocalStorageSource" + +export type ThemeViewTabStates = typeof MenuState._themeviewTabs[number] +export type MenuViewTabStates = typeof MenuState._menuviewTabs[number] + +/** + * Indicates if a menu is open, and if so, which tab is selected; + * Some tabs allow to highlight an element. + * + * Some convenience methods are provided for this as well + */ +export class MenuState { + public static readonly _themeviewTabs = ["intro", "filters", "download", "copyright","share"] as const + public static readonly _menuviewTabs = ["about", "settings", "community", "privacy","advanced"] as const + public readonly themeIsOpened: UIEventSource + public readonly themeViewTabIndex: UIEventSource + public readonly themeViewTab: UIEventSource + public readonly menuIsOpened: UIEventSource + public readonly menuViewTabIndex: UIEventSource + public readonly menuViewTab: UIEventSource + + public readonly backgroundLayerSelectionIsOpened: UIEventSource = new UIEventSource(false) + + public readonly allToggles: { + toggle: UIEventSource, name: string, + submenu?: UIEventSource, + showOverOthers?: boolean + }[] + + public readonly highlightedLayerInFilters: UIEventSource = new UIEventSource( + undefined + ) + public highlightedUserSetting: UIEventSource = new UIEventSource(undefined) + + constructor(themeid: string = "") { + if (themeid) { + themeid += "-" + } + this.themeIsOpened = LocalStorageSource.GetParsed(themeid + "thememenuisopened", true) + this.themeViewTabIndex = LocalStorageSource.GetParsed(themeid + "themeviewtabindex", 0) + this.themeViewTab = this.themeViewTabIndex.sync( + (i) => MenuState._themeviewTabs[i], + [], + (str) => MenuState._themeviewTabs.indexOf(str) + ) + + this.menuIsOpened = LocalStorageSource.GetParsed(themeid + "menuisopened", false) + this.menuViewTabIndex = LocalStorageSource.GetParsed(themeid + "menuviewtabindex", 0) + this.menuViewTab = this.menuViewTabIndex.sync( + (i) => MenuState._menuviewTabs[i], + [], + (str) => MenuState._menuviewTabs.indexOf(str) + ) + this.menuIsOpened.addCallbackAndRun((isOpen) => { + if (!isOpen) { + this.highlightedUserSetting.setData(undefined) + } + }) + this.themeViewTab.addCallbackAndRun((tab) => { + if (tab !== "filters") { + this.highlightedLayerInFilters.setData(undefined) + } + }) + + this.menuIsOpened.addCallbackAndRunD((opened) => { + if (opened) { + this.themeIsOpened.setData(false) + } + }) + this.themeIsOpened.addCallbackAndRunD((opened) => { + if (opened) { + this.menuIsOpened.setData(false) + } + }) + + this.allToggles = [ + { + toggle: this.menuIsOpened, + name: "menu", + submenu: this.menuViewTab + }, { + toggle: this.themeIsOpened, + name: "theme-menu", + submenu: this.themeViewTab + }, { + toggle: this.backgroundLayerSelectionIsOpened, + name: "background", + showOverOthers: true + }] + } + + public openFilterView(highlightLayer?: LayerConfig | string) { + this.themeIsOpened.setData(true) + this.themeViewTab.setData("filters") + if (highlightLayer) { + if (typeof highlightLayer !== "string") { + highlightLayer = highlightLayer.id + } + this.highlightedLayerInFilters.setData(highlightLayer) + } + } + + public openUsersettings(highlightTagRendering?: string) { + this.menuIsOpened.setData(true) + this.menuViewTab.setData("settings") + if ( + highlightTagRendering !== undefined && + !UserRelatedState.availableUserSettingsIds.some((tr) => tr === highlightTagRendering) + ) { + console.error( + "No tagRendering with id '" + highlightTagRendering + "'; maybe you meant:", + Utils.sortedByLevenshteinDistance( + highlightTagRendering, + UserRelatedState.availableUserSettingsIds, + (x) => x + ) + ) + } + this.highlightedUserSetting.setData(highlightTagRendering) + } + + /** + * Close all floatOvers. + * Returns 'true' if at least one menu was opened + */ + public closeAll(): boolean { + const toggles = [this.menuIsOpened, this.themeIsOpened, this.backgroundLayerSelectionIsOpened] + const somethingIsOpen = toggles.some(t => t.data) + toggles.forEach(t => t.setData(false)) + return somethingIsOpen + } + +} diff --git a/Models/OsmFeature.ts b/Models/OsmFeature.ts index aee5f08fb..d8ff8928e 100644 --- a/Models/OsmFeature.ts +++ b/Models/OsmFeature.ts @@ -1,4 +1,4 @@ -import { Feature, Geometry } from "@turf/turf" +import { Feature, Geometry } from "geojson" export type RelationId = `relation/${number}` export type WayId = `way/${number}` diff --git a/Models/RasterLayerProperties.ts b/Models/RasterLayerProperties.ts new file mode 100644 index 000000000..2686ebe2a --- /dev/null +++ b/Models/RasterLayerProperties.ts @@ -0,0 +1,34 @@ +export type EliCategory = + | "photo" + | "map" + | "historicmap" + | "osmbasedmap" + | "historicphoto" + | "qa" + | "elevation" + | "other" +export interface RasterLayerProperties { + /** + * The name of the imagery source + */ + readonly name: string | Record + + readonly isOverlay?: boolean + + readonly id: string + + readonly url: string + readonly category?: string | EliCategory + + readonly attribution?: { + readonly url?: string + readonly text?: string + readonly html?: string + readonly required?: boolean + } + + readonly min_zoom?: number + readonly max_zoom?: number + + readonly best?: boolean +} diff --git a/Models/RasterLayers.ts b/Models/RasterLayers.ts new file mode 100644 index 000000000..e549c6a13 --- /dev/null +++ b/Models/RasterLayers.ts @@ -0,0 +1,282 @@ +import {Feature, Polygon} from "geojson" +import * as editorlayerindex from "../assets/editor-layer-index.json" +import * as globallayers from "../assets/global-raster-layers.json" +import {BBox} from "../Logic/BBox" +import {Store, Stores} from "../Logic/UIEventSource" +import {GeoOperations} from "../Logic/GeoOperations" +import {RasterLayerProperties} from "./RasterLayerProperties" + +export class AvailableRasterLayers { + public static EditorLayerIndex: (Feature & + RasterLayerPolygon)[] = editorlayerindex.features + public static globalLayers: RasterLayerPolygon[] = globallayers.layers.map( + (properties) => + { + type: "Feature", + properties, + geometry: BBox.global.asGeometry(), + } + ) + public static readonly osmCartoProperties: RasterLayerProperties = { + id: "osm", + name: "OpenStreetMap", + url: "https://tile.openstreetmap.org/{z}/{x}/{y}.png", + attribution: { + text: "OpenStreetMap", + url: "https://openStreetMap.org/copyright", + }, + best: true, + max_zoom: 19, + min_zoom: 0, + category: "osmbasedmap", + } + + public static readonly osmCarto: RasterLayerPolygon = { + type: "Feature", + properties: AvailableRasterLayers.osmCartoProperties, + geometry: BBox.global.asGeometry(), + } + + public static readonly maplibre: RasterLayerPolygon = { + type: "Feature", + properties: { + name: "MapTiler", + url: "https://api.maptiler.com/maps/15cc8f61-0353-4be6-b8da-13daea5f7432/style.json?key=GvoVAJgu46I5rZapJuAy", + category: "osmbasedmap", + id: "maptiler", + attribution: { + text: "Maptiler", + url: "https://www.maptiler.com/copyright/" + } + }, + geometry: BBox.global.asGeometry(), + } + + public static layersAvailableAt( + location: Store<{ lon: number; lat: number }> + ): Store { + const availableLayersBboxes = Stores.ListStabilized( + location.mapD((loc) => { + const lonlat: [number, number] = [loc.lon, loc.lat] + return AvailableRasterLayers.EditorLayerIndex.filter((eliPolygon) => + BBox.get(eliPolygon).contains(lonlat) + ) + }) + ) + const available = Stores.ListStabilized( + availableLayersBboxes.map((eliPolygons) => { + const loc = location.data + const lonlat: [number, number] = [loc.lon, loc.lat] + const matching: RasterLayerPolygon[] = eliPolygons.filter((eliPolygon) => { + if (eliPolygon.geometry === null) { + return true // global ELI-layer + } + return GeoOperations.inside(lonlat, eliPolygon) + }) + matching.unshift(AvailableRasterLayers.osmCarto) + matching.unshift(AvailableRasterLayers.maplibre) + matching.push(...AvailableRasterLayers.globalLayers) + return matching + }) + ) + return available + } +} + +export class RasterLayerUtils { + /** + * Selects, from the given list of available rasterLayerPolygons, a rasterLayer. + * This rasterlayer will be of type 'preferredCategory' and will be of the 'best'-layer (if available). + * Returns 'undefined' if no such layer is available + * @param available + * @param preferredCategory + * @param ignoreLayer + */ + public static SelectBestLayerAccordingTo( + available: RasterLayerPolygon[], + preferredCategory: string, + ignoreLayer?: RasterLayerPolygon + ): RasterLayerPolygon { + let secondBest: RasterLayerPolygon = undefined + for (const rasterLayer of available) { + if (rasterLayer === ignoreLayer) { + continue + } + const p = rasterLayer.properties + if (p.category === preferredCategory) { + if (p.best) { + return rasterLayer + } + if (!secondBest) { + secondBest = rasterLayer + } + } + } + return secondBest + } +} + +export type RasterLayerPolygon = Feature + +/** + * Information about a raster tile layer + * + * Based on the spec here https://github.com/osmlab/editor-layer-index/blob/gh-pages/schema.json + * which was then converted with http://borischerny.com/json-schema-to-typescript-browser/ + */ +export interface EditorLayerIndexProperties extends RasterLayerProperties { + /** + * The name of the imagery source + */ + readonly name: string + /** + * Whether the imagery name should be translated + */ + readonly i18n?: boolean + readonly type: "tms" | "wms" | "bing" | "scanex" | "wms_endpoint" | "wmts" + /** + * 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. + */ + readonly category?: + | "photo" + | "map" + | "historicmap" + | "osmbasedmap" + | "historicphoto" + | "qa" + | "elevation" + | "other" + /** + * A URL template for imagery tiles + */ + readonly url: string + readonly min_zoom?: number + readonly max_zoom?: number + /** + * explicit/implicit permission by the owner for use in OSM + */ + readonly permission_osm?: "explicit" | "implicit" | "no" + /** + * A URL for the license or permissions for the imagery + */ + 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. + */ + readonly privacy_policy_url?: string | boolean + /** + * A unique identifier for the source; used in imagery_used changeset tag + */ + readonly id: string + /** + * A short English-language description of the source + */ + readonly description?: string + /** + * The ISO 3166-1 alpha-2 two letter country code in upper case. Use ZZ for unknown or multiple. + */ + readonly country_code?: string + /** + * Whether this imagery should be shown in the default world-wide menu + */ + readonly default?: boolean + /** + * Whether this imagery is the best source for the region + */ + readonly best?: boolean + /** + * The age of the oldest imagery or data in the source, as an RFC3339 date or leading portion of one + */ + readonly start_date?: string + /** + * The age of the newest imagery or data in the source, as an RFC3339 date or leading portion of one + */ + readonly end_date?: string + /** + * HTTP header to check for information if the tile is invalid + */ + readonly no_tile_header?: { + /** + * This interface was referenced by `undefined`'s JSON-Schema definition + * via the `patternProperty` "^.*$". + */ + [k: string]: string[] | null + } + /** + * 'true' if tiles are transparent and can be overlaid on another source + */ + readonly overlay?: boolean & string + readonly available_projections?: string[] + readonly attribution?: { + readonly url?: string + readonly text?: string + readonly html?: string + readonly required?: boolean + } + /** + * A URL for an image, that can be displayed in the list of imagery layers next to the name + */ + 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. + */ + readonly eula?: string + /** + * A URL for an image, that is displayed in the mapview for attribution + */ + readonly "logo-image"?: string + /** + * Customized text for the terms of use link (default is "Background Terms of Use") + */ + 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. + */ + 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 + */ + 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. + */ + readonly "valid-georeference"?: boolean + /** + * Size of individual tiles delivered by a TMS service + */ + 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. + */ + 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. + */ + readonly "custom-http-headers"?: { + readonly "header-name"?: 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) + */ + readonly "default-layers"?: { + layer?: { + "layer-name"?: string + "layer-style"?: string + [k: string]: unknown + } + [k: string]: unknown + }[] + /** + * format to use when connecting tile server (when using WMS_ENDPOINT type) + */ + readonly format?: string + /** + * If `true` transparent tiles will be requested from WMS server + */ + readonly transparent?: boolean & string + /** + * 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 +} diff --git a/Models/ThemeConfig/Conversion/Conversion.ts b/Models/ThemeConfig/Conversion/Conversion.ts index d2a8184e6..66a4135b4 100644 --- a/Models/ThemeConfig/Conversion/Conversion.ts +++ b/Models/ThemeConfig/Conversion/Conversion.ts @@ -297,6 +297,9 @@ export class Fuse extends DesugaringStep { const step = this.steps[i] try { let r = step.convert(json, "While running step " + step.name + ": " + context) + if(r.result["tagRenderings"]?.some(tr => tr === undefined)){ + throw step.name+" introduced an undefined tagRendering" + } errors.push(...(r.errors ?? [])) warnings.push(...(r.warnings ?? [])) information.push(...(r.information ?? [])) diff --git a/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts b/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts index 609e3fafc..59f9b318b 100644 --- a/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts +++ b/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts @@ -1,9 +1,9 @@ -import { Conversion } from "./Conversion" +import {Conversion} from "./Conversion" import LayerConfig from "../LayerConfig" -import { LayerConfigJson } from "../Json/LayerConfigJson" +import {LayerConfigJson} from "../Json/LayerConfigJson" import Translations from "../../../UI/i18n/Translations" import PointRenderingConfigJson from "../Json/PointRenderingConfigJson" -import { Translation, TypedTranslation } from "../../../UI/i18n/Translation" +import {Translation, TypedTranslation} from "../../../UI/i18n/Translation" export default class CreateNoteImportLayer extends Conversion { /** @@ -82,7 +82,7 @@ export default class CreateNoteImportLayer extends Conversion(translation: TypedTranslation, subs: T): object { + function trs(translation: TypedTranslation, subs: T): Record { return { ...translation.Subs(subs).translations, _context: translation.context } } @@ -101,16 +101,20 @@ export default class CreateNoteImportLayer extends Conversion {const lines = feat.properties['_first_comment'].split('\\n'); const matchesMapCompleteURL = lines.map(l => l.match(\".*https://mapcomplete.osm.be/\\([a-zA-Z_-]+\\)\\(.html\\)?.*#import\")); const matchedIndexes = matchesMapCompleteURL.map((doesMatch, i) => [doesMatch !== null, i]).filter(v => v[0]).map(v => v[1]); return matchedIndexes[0] })()", - "_comments_count=feat.get('comments').length", - "_intro=(() => {const lines = feat.get('comments')[0].text.split('\\n'); lines.splice(feat.get('_trigger_index')-1, lines.length); return lines.filter(l => l !== '').join('
');})()", - "_tags=(() => {let lines = feat.get('comments')[0].text.split('\\n').map(l => l.trim()); lines.splice(0, feat.get('_trigger_index') + 1); lines = lines.filter(l => l != ''); return lines.join(';');})()", + "_comments_count=get(feat)('comments').length", + "_intro=(() => {const lines = get(feat)('comments')[0].text.split('\\n'); lines.splice(get(feat)('_trigger_index')-1, lines.length); return lines.filter(l => l !== '').join('
');})()", + "_tags=(() => {let lines = get(feat)('comments')[0].text.split('\\n').map(l => l.trim()); lines.splice(0, get(feat)('_trigger_index') + 1); lines = lines.filter(l => l != ''); return lines.join(';');})()", ], isShown: { and: ["_trigger_index~*", { or: isShownIfAny }], @@ -170,6 +174,17 @@ export default class CreateNoteImportLayer extends Conversion")) { + // These is probably html - we ignore + const doc = parse_html(foundImage.path) + const images = Array.from(doc.getElementsByTagName("img")) + const paths = images.map((i) => i.getAttribute("src")) + cleanedImages.push( + ...paths.map((path) => ({ path, context: foundImage.context + " (in html)" })) + ) + continue + } + // Split "circle:white;./assets/layers/.../something.svg" into ["circle", "./assets/layers/.../something.svg"] const allPaths = Utils.NoNull( Utils.NoEmpty(foundImage.path?.split(";")?.map((part) => part.split(":")[0])) diff --git a/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts b/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts index 3b5ac7f8e..f0f9b805c 100644 --- a/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts +++ b/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts @@ -30,7 +30,7 @@ export class UpdateLegacyLayer extends DesugaringStep< config.source = config.source ?? { osmTags: config["overpassTags"], } - config.source.osmTags = config["overpassTags"] + config.source["osmTags"] = config["overpassTags"] delete config["overpassTags"] } diff --git a/Models/ThemeConfig/Conversion/PrepareLayer.ts b/Models/ThemeConfig/Conversion/PrepareLayer.ts index 0535e61c4..87b62540a 100644 --- a/Models/ThemeConfig/Conversion/PrepareLayer.ts +++ b/Models/ThemeConfig/Conversion/PrepareLayer.ts @@ -23,6 +23,9 @@ import predifined_filters from "../../../assets/layers/filters/filters.json" import { TagConfigJson } from "../Json/TagConfigJson" import PointRenderingConfigJson from "../Json/PointRenderingConfigJson" import LineRenderingConfigJson from "../Json/LineRenderingConfigJson" +import ValidationUtils from "./ValidationUtils" +import {RenderingSpecification} from "../../../UI/SpecialVisualization" +import {QuestionableTagRenderingConfigJson} from "../Json/QuestionableTagRenderingConfigJson" class ExpandFilter extends DesugaringStep { private static readonly predefinedFilters = ExpandFilter.load_filters() @@ -235,7 +238,7 @@ class ExpandTagRendering extends Conversion< matchingTrs = layerTrs } else if (id.startsWith("*")) { const id_ = id.substring(1) - matchingTrs = layerTrs.filter((tr) => tr.group === id_ || tr.labels?.indexOf(id_) >= 0) + matchingTrs = layerTrs.filter((tr) => tr.labels?.indexOf(id_) >= 0) } else { matchingTrs = layerTrs.filter((tr) => tr.id === id || tr.labels?.indexOf(id) >= 0) } @@ -245,10 +248,12 @@ class ExpandTagRendering extends Conversion< let found: TagRenderingConfigJson = Utils.Clone(matchingTrs[i]) if (this._options?.applyCondition) { // The matched tagRenderings are 'stolen' from another layer. This means that they must match the layer condition before being shown - if (found.condition === undefined) { - found.condition = layer.source.osmTags - } else { - found.condition = { and: [found.condition, layer.source.osmTags] } + if (typeof layer.source !== "string") { + if (found.condition === undefined) { + found.condition = layer.source["osmTags"] + } else { + found.condition = { and: [found.condition, layer.source["osmTags"]] } + } } } @@ -269,13 +274,6 @@ class ExpandTagRendering extends Conversion< ctx: string ): TagRenderingConfigJson[] { const state = this._state - if (tr === "questions") { - return [ - { - id: "questions", - }, - ] - } if (typeof tr === "string") { const lookup = this.lookup(tr) @@ -429,6 +427,246 @@ class ExpandTagRendering extends Conversion< } } +class DetectInline extends DesugaringStep { + constructor() { + super( + "If no 'inline' is set on the freeform key, it will be automatically added. If no special renderings are used, it'll be set to true", + ["freeform.inline"], + "DetectInline" + ) + } + + convert( + json: QuestionableTagRenderingConfigJson, + context: string + ): { + result: QuestionableTagRenderingConfigJson + errors?: string[] + warnings?: string[] + information?: string[] + } { + if (json.freeform === undefined) { + return {result: json} + } + let spec: Record + if (typeof json.render === "string") { + spec = {"*": json.render} + } else { + spec = >json.render + } + const errors: string[] = [] + for (const key in spec) { + if (spec[key].indexOf("= 0) { + // We have a link element, it probably contains something that needs to be substituted... + // Let's play this safe and not inline it + return {result: json} + } + const fullSpecification = SpecialVisualizations.constructSpecification(spec[key]) + if (fullSpecification.length > 1) { + // We found a special rendering! + if (json.freeform.inline === true) { + errors.push( + "At " + + context + + ": 'inline' is set, but the rendering contains a special visualisation...\n " + + spec[key] + ) + } + json = JSON.parse(JSON.stringify(json)) + json.freeform.inline = false + return {result: json, errors} + } + } + json = JSON.parse(JSON.stringify(json)) + json.freeform.inline ??= true + return {result: json, errors} + } +} + +export class AddQuestionBox extends DesugaringStep { + constructor() { + super( + "Adds a 'questions'-object if no question element is added yet", + ["tagRenderings"], + "AddQuestionBox" + ) + } + + convert( + json: LayerConfigJson, + context: string + ): { result: LayerConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { + if ( + json.tagRenderings === undefined || + json.tagRenderings.some((tr) => tr["id"] === "leftover-questions") + ) { + return {result: json} + } + json = JSON.parse(JSON.stringify(json)) + const allSpecials: Exclude[] = [] + .concat( + ...json.tagRenderings.map((tr) => + ValidationUtils.getSpecialVisualsationsWithArgs(tr) + ) + ) + .filter((spec) => typeof spec !== "string") + + const questionSpecials = allSpecials.filter((sp) => sp.func.funcName === "questions") + const noLabels = questionSpecials.filter( + (sp) => sp.args.length === 0 || sp.args[0].trim() === "" + ) + + const errors: string[] = [] + const warnings: string[] = [] + if (noLabels.length > 1) { + errors.push( + "At " + + context + + ": multiple 'questions'-visualisations found which would show _all_ questions. Don't do this" + ) + } + + // ALl labels that are used in this layer + const allLabels = new Set( + [].concat(...json.tagRenderings.map((tr) => (tr).labels ?? [])) + ) + const seen = new Set() + for (const questionSpecial of questionSpecials) { + if (typeof questionSpecial === "string") { + continue + } + const used = questionSpecial.args[0] + ?.split(";") + ?.map((a) => a.trim()) + ?.filter((s) => s != "") + const blacklisted = questionSpecial.args[1] + ?.split(";") + ?.map((a) => a.trim()) + ?.filter((s) => s != "") + if (blacklisted?.length > 0 && used?.length > 0) { + errors.push( + "At " + + context + + ": the {questions()}-special rendering only supports either a blacklist OR a whitelist, but not both." + + "\n Whitelisted: " + + used.join(", ") + + "\n Blacklisted: " + + blacklisted.join(", ") + ) + } + for (const usedLabel of used) { + if (!allLabels.has(usedLabel)) { + errors.push( + "At " + + context + + ": this layers specifies a special question element for label `" + + usedLabel + + "`, but this label doesn't exist.\n" + + " Available labels are " + + Array.from(allLabels).join(", ") + ) + } + seen.add(usedLabel) + } + } + + if (noLabels.length == 0) { + /* At this point, we know which question labels are not yet handled and which already are handled, and we + * know there is no previous catch-all questions + */ + const question: TagRenderingConfigJson = { + id: "leftover-questions", + render: { + "*": `{questions( ,${Array.from(seen).join(";")})}`, + }, + } + json.tagRenderings.push(question) + } + return { + result: json, + errors, + warnings, + } + } +} + +export class AddEditingElements extends DesugaringStep { + private readonly _desugaring: DesugaringContext + + constructor(desugaring: DesugaringContext) { + super( + "Add some editing elements, such as the delete button or the move button if they are configured. These used to be handled by the feature info box, but this has been replaced by special visualisation elements", + [], + "AddEditingElements" + ) + this._desugaring = desugaring + } + + convert( + json: LayerConfigJson, + context: string + ): { result: LayerConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { + json = JSON.parse(JSON.stringify(json)) + + if ( + json.tagRenderings && + this._desugaring.tagRenderings.has("just_created") && + !json.tagRenderings.some((tr) => tr === "just_created" || tr["id"] === "just_created") + ) { + json.tagRenderings.unshift(this._desugaring.tagRenderings.get("just_created")) + } + + if (json.allowSplit && !ValidationUtils.hasSpecialVisualisation(json, "split_button")) { + json.tagRenderings.push({ + id: "split-button", + render: {"*": "{split_button()}"}, + }) + delete json.allowSplit + } + + if (json.allowMove && !ValidationUtils.hasSpecialVisualisation(json, "move_button")) { + json.tagRenderings.push({ + id: "move-button", + render: {"*": "{move_button()}"}, + }) + } + if (json.deletion && !ValidationUtils.hasSpecialVisualisation(json, "delete_button")) { + json.tagRenderings.push({ + id: "delete-button", + render: {"*": "{delete_button()}"}, + }) + } + + if ( + json.source !== "special" && + json.source !== "special:library" && + json.tagRenderings && + this._desugaring.tagRenderings.has("last_edit") && + !json.tagRenderings.some((tr) => tr["id"] === "last_edit") + ) { + json.tagRenderings.push(this._desugaring.tagRenderings.get("last_edit")) + } + + if (!ValidationUtils.hasSpecialVisualisation(json, "all_tags")) { + const trc: TagRenderingConfigJson = { + id: "all-tags", + render: {"*": "{all_tags()}"}, + + metacondition: { + or: [ + "__featureSwitchIsDebugging=true", + "mapcomplete-show_tags=full", + "mapcomplete-show_debug=yes", + ], + }, + } + json.tagRenderings?.push(trc) + } + + return {result: json} + } +} + export class ExpandRewrite extends Conversion, T[]> { constructor() { super("Applies a rewrite", [], "ExpandRewrite") @@ -719,7 +957,13 @@ export class RewriteSpecial extends DesugaringStep { const param = special[arg.name] if (param === undefined) { errors.push( - `At ${context}: Obligated parameter '${arg.name}' in special rendering of type ${vis.funcName} not found.\n${arg.doc}` + `At ${context}: Obligated parameter '${ + arg.name + }' in special rendering of type ${ + vis.funcName + } not found.\n The full special rendering specification is: '${JSON.stringify( + input + )}'\n ${arg.name}: ${arg.doc}` ) } } @@ -915,6 +1159,73 @@ class PreparePointRendering extends Fuse { + constructor() { + super("sets the fullNodeDatabase-bit if needed", + ["fullNodeDatabase"], + "SetFullNodeDatabase") + } + + convert(json: LayerConfigJson, context: string): { + result: LayerConfigJson; + errors?: string[]; + warnings?: string[]; + information?: string[] + } { + const needsSpecial = json.tagRenderings?.some(tr => { + if (typeof tr === "string") { + return false + } + const specs = ValidationUtils.getSpecialVisualisations(tr) + return specs?.some(sp => sp.needsNodeDatabase) + }) ?? false + if (!needsSpecial) { + return {result: json} + } + return { + result: {...json, fullNodeDatabase: true}, + information: ["Layer " + json.id + " needs the fullNodeDatabase"] + }; + } +} + +export class AddMiniMap extends DesugaringStep { + private readonly _state: DesugaringContext + + constructor(state: DesugaringContext) { + super( + "Adds a default 'minimap'-element to the tagrenderings if none of the elements define such a minimap", + ["tagRenderings"], + "AddMiniMap" + ) + this._state = state + } + + convert(layerConfig: LayerConfigJson, context: string): { result: LayerConfigJson } { + if (!layerConfig.tagRenderings || layerConfig.source === "special") { + return {result: layerConfig} + } + const state = this._state + const hasMinimap = ValidationUtils.hasSpecialVisualisation(layerConfig, "minimap") + if (!hasMinimap) { + layerConfig = {...layerConfig} + layerConfig.tagRenderings = [...layerConfig.tagRenderings] + const minimap = state.tagRenderings.get("minimap") + if (minimap === undefined) { + if (state.tagRenderings.size > 0) { + throw "The 'minimap'-builtin tagrendering is not defined. As such, it cannot be added automatically" + } + } else { + layerConfig.tagRenderings.push(minimap) + } + } + + return { + result: layerConfig, + } + } +} + export class PrepareLayer extends Fuse { constructor(state: DesugaringContext) { super( @@ -922,6 +1233,11 @@ export class PrepareLayer extends Fuse { new On("tagRenderings", new Each(new RewriteSpecial())), new On("tagRenderings", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)), new On("tagRenderings", (layer) => new Concat(new ExpandTagRendering(state, layer))), + new On("tagRenderings", new Each(new DetectInline())), + new AddQuestionBox(), + new AddMiniMap(state), + new AddEditingElements(state), + new SetFullNodeDatabase(), new On("mapRendering", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)), new On<(PointRenderingConfigJson | LineRenderingConfigJson)[], LayerConfigJson>( "mapRendering", diff --git a/Models/ThemeConfig/Conversion/PrepareTheme.ts b/Models/ThemeConfig/Conversion/PrepareTheme.ts index f65a768da..8ef58830a 100644 --- a/Models/ThemeConfig/Conversion/PrepareTheme.ts +++ b/Models/ThemeConfig/Conversion/PrepareTheme.ts @@ -17,9 +17,9 @@ import Constants from "../../Constants" import CreateNoteImportLayer from "./CreateNoteImportLayer" import LayerConfig from "../LayerConfig" import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson" -import { SubstitutedTranslation } from "../../../UI/SubstitutedTranslation" import DependencyCalculator from "../DependencyCalculator" import { AddContextToTranslations } from "./AddContextToTranslations" +import ValidationUtils from "./ValidationUtils" class SubstituteLayer extends Conversion { private readonly _state: DesugaringContext @@ -175,7 +175,7 @@ class SubstituteLayer extends Conversion { - private _state: DesugaringContext + private readonly _state: DesugaringContext constructor(state: DesugaringContext) { super( @@ -255,7 +255,7 @@ class AddImportLayers extends DesugaringStep { const creator = new CreateNoteImportLayer() for (let i1 = 0; i1 < allLayers.length; i1++) { const layer = allLayers[i1] - if (Constants.priviliged_layers.indexOf(layer.id) >= 0) { + if (layer.source === undefined) { // Priviliged layers are skipped continue } @@ -295,80 +295,7 @@ class AddImportLayers extends DesugaringStep { } } -export class AddMiniMap extends DesugaringStep { - private readonly _state: DesugaringContext - - constructor(state: DesugaringContext) { - super( - "Adds a default 'minimap'-element to the tagrenderings if none of the elements define such a minimap", - ["tagRenderings"], - "AddMiniMap" - ) - this._state = state - } - - /** - * Returns true if this tag rendering has a minimap in some language. - * Note: this minimap can be hidden by conditions - * - * AddMiniMap.hasMinimap({render: "{minimap()}"}) // => true - * AddMiniMap.hasMinimap({render: {en: "{minimap()}"}}) // => true - * AddMiniMap.hasMinimap({render: {en: "{minimap()}", nl: "{minimap()}"}}) // => true - * AddMiniMap.hasMinimap({render: {en: "{minimap()}", nl: "No map for the dutch!"}}) // => true - * AddMiniMap.hasMinimap({render: "{minimap()}"}) // => true - * AddMiniMap.hasMinimap({render: "{minimap(18,featurelist)}"}) // => true - * AddMiniMap.hasMinimap({mappings: [{if: "xyz=abc",then: "{minimap(18,featurelist)}"}]}) // => true - * AddMiniMap.hasMinimap({render: "Some random value {key}"}) // => false - * AddMiniMap.hasMinimap({render: "Some random value {minimap}"}) // => false - */ - static hasMinimap(renderingConfig: TagRenderingConfigJson): boolean { - const translations: any[] = Utils.NoNull([ - renderingConfig.render, - ...(renderingConfig.mappings ?? []).map((m) => m.then), - ]) - for (let translation of translations) { - if (typeof translation == "string") { - translation = { "*": translation } - } - - for (const key in translation) { - if (!translation.hasOwnProperty(key)) { - continue - } - - const template = translation[key] - const parts = SubstitutedTranslation.ExtractSpecialComponents(template) - const hasMiniMap = parts - .filter((part) => part.special !== undefined) - .some((special) => special.special.func.funcName === "minimap") - if (hasMiniMap) { - return true - } - } - } - return false - } - - convert(layerConfig: LayerConfigJson, context: string): { result: LayerConfigJson } { - const state = this._state - const hasMinimap = - layerConfig.tagRenderings?.some((tr) => - AddMiniMap.hasMinimap(tr) - ) ?? true - if (!hasMinimap) { - layerConfig = { ...layerConfig } - layerConfig.tagRenderings = [...layerConfig.tagRenderings] - layerConfig.tagRenderings.push(state.tagRenderings.get("questions")) - layerConfig.tagRenderings.push(state.tagRenderings.get("minimap")) - } - - return { - result: layerConfig, - } - } -} - -class AddContextToTransltionsInLayout extends DesugaringStep { +class AddContextToTranslationsInLayout extends DesugaringStep { constructor() { super( "Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too", @@ -430,7 +357,7 @@ class AddDependencyLayersToTheme extends DesugaringStep { constructor(state: DesugaringContext) { super( `If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically) - + Note that these layers are added _at the start_ of the layer list, meaning that they will see _every_ feature. Furthermore, \`passAllFeatures\` will be set, so that they won't steal away features from further layers. Some layers (e.g. \`all_buildings_and_walls\' or \'streets_with_a_name\') are invisible, so by default, \'force_load\' is set too. @@ -600,7 +527,7 @@ class PreparePersonalTheme extends DesugaringStep { // All other preparations are done by the 'override-all'-block in personal.json json.layers = Array.from(this._state.sharedLayers.keys()) - .filter((l) => Constants.priviliged_layers.indexOf(l) < 0) + .filter((l) => this._state.sharedLayers.get(l).source !== null) .filter((l) => this._state.publicLayers.has(l)) return { result: json, @@ -668,7 +595,7 @@ export class PrepareTheme extends Fuse { super( "Fully prepares and expands a theme", - new AddContextToTransltionsInLayout(), + new AddContextToTranslationsInLayout(), new PreparePersonalTheme(state), new WarnForUnsubstitutedLayersInTheme(), new On("layers", new Concat(new SubstituteLayer(state))), @@ -683,8 +610,31 @@ export class PrepareTheme extends Fuse { ? new Pass("AddDefaultLayers is disabled due to the set flag") : new AddDefaultLayers(state), new AddDependencyLayersToTheme(state), - new AddImportLayers(), - new On("layers", new Each(new AddMiniMap(state))) + new AddImportLayers() ) } + + convert( + json: LayoutConfigJson, + context: string + ): { result: LayoutConfigJson; errors: string[]; warnings: string[]; information: string[] } { + const result = super.convert(json, context) + + const needsNodeDatabase = result.result.layers?.some((l: LayerConfigJson) => + l.tagRenderings?.some((tr: TagRenderingConfigJson) => + ValidationUtils.getSpecialVisualisations(tr)?.some( + (special) => special.needsNodeDatabase + ) + ) + ) + if (needsNodeDatabase) { + result.information.push( + context + + ": setting 'enableNodeDatabase' as this theme uses a special visualisation which needs to keep track of _all_ nodes" + ) + result.result.enableNodeDatabase = true + } + + return result + } } diff --git a/Models/ThemeConfig/Conversion/Validation.ts b/Models/ThemeConfig/Conversion/Validation.ts index 5e5a92d34..c61f06e45 100644 --- a/Models/ThemeConfig/Conversion/Validation.ts +++ b/Models/ThemeConfig/Conversion/Validation.ts @@ -3,7 +3,7 @@ import { LayerConfigJson } from "../Json/LayerConfigJson" import LayerConfig from "../LayerConfig" import { Utils } from "../../../Utils" import Constants from "../../Constants" -import { Translation, TypedTranslation } from "../../../UI/i18n/Translation" +import { Translation } from "../../../UI/i18n/Translation" import { LayoutConfigJson } from "../Json/LayoutConfigJson" import LayoutConfig from "../LayoutConfig" import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson" @@ -15,6 +15,7 @@ import Svg from "../../../Svg" import FilterConfigJson from "../Json/FilterConfigJson" import DeleteConfig from "../DeleteConfig" import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson" +import Validators from "../../../UI/InputElement/Validators" class ValidateLanguageCompleteness extends DesugaringStep { private readonly _languages: string[] @@ -100,6 +101,11 @@ export class DoesImageExist extends DesugaringStep { } } + if (image.startsWith("<") && image.endsWith(">")) { + // This is probably HTML, you're on your own here + return { result: image } + } + if (!this._knownImagePaths.has(image)) { if (this.doesPathExist === undefined) { errors.push( @@ -296,7 +302,7 @@ class OverrideShadowingCheck extends DesugaringStep { convert( json: LayoutConfigJson, - context: string + _: string ): { result: LayoutConfigJson; errors?: string[]; warnings?: string[] } { const overrideAll = json.overrideAll if (overrideAll === undefined) { @@ -594,6 +600,7 @@ export class DetectMappingsWithImages extends DesugaringStep { private _options: { noQuestionHintCheck: boolean } + constructor(options: { noQuestionHintCheck: boolean }) { super("Miscellaneous checks on the tagrendering", ["special"], "MiscTagRenderingChecks") this._options = options @@ -617,24 +624,26 @@ class MiscTagRenderingChecks extends DesugaringStep { ': detected `special` on the top level. Did you mean `{"render":{ "special": ... }}`' ) } - if (json["question"] && !this._options?.noQuestionHintCheck) { - const question = Translations.T( - new TypedTranslation(json["question"]), - context + ".question" + if (json["group"]) { + errors.push( + "At " + + context + + ': groups are deprecated, use `"label": ["' + + json["group"] + + '"]` instead' ) - for (const lng of question.SupportedLanguages()) { - const html = document.createElement("p") - html.innerHTML = question.textFor(lng) - const divs = Array.from(html.getElementsByTagName("div")) - const spans = Array.from(html.getElementsByTagName("span")) - const brs = Array.from(html.getElementsByTagName("br")) - const subtles = Array.from(html.getElementsByClassName("subtle")) - if (divs.length + spans.length + brs.length + subtles.length > 0) { - warnings.push( - `At ${context}: the question for ${lng} contains a div, a span, a br or an element with class 'subtle'. Please, use a \`questionHint\` instead. - The question is: ${question.textFor(lng)}` - ) - } + } + const freeformType = json["freeform"]?.["type"] + if (freeformType) { + if (Validators.availableTypes.indexOf(freeformType) < 0) { + throw ( + "At " + + context + + ".freeform.type is an unknown type: " + + freeformType + + "; try one of " + + Validators.availableTypes.join(", ") + ) } } return { @@ -692,6 +701,17 @@ export class ValidateLayer extends DesugaringStep { } } + if (json.source === "special") { + if (!Constants.priviliged_layers.find((x) => x == json.id)) { + errors.push( + context + + ": layer " + + json.id + + " uses 'special' as source.osmTags. However, this layer is not a priviliged layer" + ) + } + } + if (json.tagRenderings !== undefined && json.tagRenderings.length > 0) { if (json.title === undefined) { errors.push( @@ -715,9 +735,9 @@ export class ValidateLayer extends DesugaringStep { } } - if (json.minzoom > Constants.userJourney.minZoomLevelToAddNewPoints) { + if (json.minzoom > Constants.minZoomLevelToAddNewPoint) { ;(json.presets?.length > 0 ? errors : warnings).push( - `At ${context}: minzoom is ${json.minzoom}, this should be at most ${Constants.userJourney.minZoomLevelToAddNewPoints} as a preset is set. Why? Selecting the pin for a new item will zoom in to level before adding the point. Having a greater minzoom will hide the points, resulting in possible duplicates` + `At ${context}: minzoom is ${json.minzoom}, this should be at most ${Constants.minZoomLevelToAddNewPoint} as a preset is set. Why? Selecting the pin for a new item will zoom in to level before adding the point. Having a greater minzoom will hide the points, resulting in possible duplicates` ) } { @@ -830,7 +850,7 @@ export class ValidateLayer extends DesugaringStep { } if (json.description === undefined) { - if (Constants.priviliged_layers.indexOf(json.id) >= 0) { + if (typeof json.source === null) { errors.push(context + ": A priviliged layer must have a description") } else { warnings.push(context + ": A builtin layer should have a description") @@ -867,8 +887,11 @@ export class ValidateLayer extends DesugaringStep { } if (json.presets !== undefined) { + if (typeof json.source === "string") { + throw "A special layer cannot have presets" + } // Check that a preset will be picked up by the layer itself - const baseTags = TagUtils.Tag(json.source.osmTags) + const baseTags = TagUtils.Tag(json.source["osmTags"]) for (let i = 0; i < json.presets.length; i++) { const preset = json.presets[i] const tags: { k: string; v: string }[] = new And( @@ -905,6 +928,37 @@ export class ValidateLayer extends DesugaringStep { } } +export class ValidateFilter extends DesugaringStep { + constructor() { + super("Detect common errors in the filters", [], "ValidateFilter") + } + + convert( + filter: FilterConfigJson, + context: string + ): { + result: FilterConfigJson + errors?: string[] + warnings?: string[] + information?: string[] + } { + const errors = [] + for (const option of filter.options) { + for (let i = 0; i < option.fields.length; i++) { + const field = option.fields[i] + const type = field.type ?? "string" + if (Validators.availableTypes.find((t) => t === type) === undefined) { + const err = `Invalid filter: ${type} is not a valid textfield type (at ${context}.fields[${i}])\n\tTry one of ${Array.from( + Validators.availableTypes + ).join(",")}` + errors.push(err) + } + } + } + return { result: filter, errors } + } +} + export class DetectDuplicateFilters extends DesugaringStep<{ layers: LayerConfigJson[] themes: LayoutConfigJson[] @@ -919,7 +973,7 @@ export class DetectDuplicateFilters extends DesugaringStep<{ convert( json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] }, - context: string + __: string ): { result: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] } errors?: string[] diff --git a/Models/ThemeConfig/Conversion/ValidationUtils.ts b/Models/ThemeConfig/Conversion/ValidationUtils.ts new file mode 100644 index 000000000..248a3a577 --- /dev/null +++ b/Models/ThemeConfig/Conversion/ValidationUtils.ts @@ -0,0 +1,63 @@ +import {TagRenderingConfigJson} from "../Json/TagRenderingConfigJson" +import {Utils} from "../../../Utils" +import SpecialVisualizations from "../../../UI/SpecialVisualizations" +import {RenderingSpecification, SpecialVisualization} from "../../../UI/SpecialVisualization" +import {LayerConfigJson} from "../Json/LayerConfigJson" + +export default class ValidationUtils { + public static hasSpecialVisualisation( + layer: LayerConfigJson, + specialVisualisation: string + ): boolean { + return ( + layer.tagRenderings?.some((tagRendering) => { + if(tagRendering === undefined){ + return false + } + + const spec = ValidationUtils.getSpecialVisualisations(tagRendering) + return spec.some((vis) => vis.funcName === specialVisualisation); + } + ) ?? false + ) + } + + /** + * Gives all the (function names of) used special visualisations + * @param renderingConfig + */ + public static getSpecialVisualisations( + renderingConfig: TagRenderingConfigJson + ): SpecialVisualization[] { + return ValidationUtils.getSpecialVisualsationsWithArgs(renderingConfig).map( + (spec) => spec["func"] + ) + } + + public static getSpecialVisualsationsWithArgs( + renderingConfig: TagRenderingConfigJson + ): RenderingSpecification[] { + const translations: any[] = Utils.NoNull([ + renderingConfig.render, + ...(renderingConfig.mappings ?? []).map((m) => m.then), + ]) + const all: RenderingSpecification[] = [] + for (let translation of translations) { + if (typeof translation == "string") { + translation = {"*": translation} + } + + for (const key in translation) { + if (!translation.hasOwnProperty(key)) { + continue + } + + const template = translation[key] + const parts = SpecialVisualizations.constructSpecification(template) + const specials = parts.filter((p) => typeof p !== "string") + all.push(...specials) + } + } + return all + } +} diff --git a/Models/ThemeConfig/DeleteConfig.ts b/Models/ThemeConfig/DeleteConfig.ts index 39d7359dd..f5b2db036 100644 --- a/Models/ThemeConfig/DeleteConfig.ts +++ b/Models/ThemeConfig/DeleteConfig.ts @@ -3,8 +3,12 @@ import { TagsFilter } from "../../Logic/Tags/TagsFilter" import { DeleteConfigJson } from "./Json/DeleteConfigJson" import Translations from "../../UI/i18n/Translations" import { TagUtils } from "../../Logic/Tags/TagUtils" +import TagRenderingConfig from "./TagRenderingConfig"; +import {QuestionableTagRenderingConfigJson} from "./Json/QuestionableTagRenderingConfigJson"; +import {TagConfigJson} from "./Json/TagConfigJson"; export default class DeleteConfig { + public static readonly deleteReasonKey = "_delete_reason" private static readonly defaultDeleteReasons: { changesetMessage: string explanation: Translation @@ -32,7 +36,7 @@ export default class DeleteConfig { changesetMessage: string }[] - public readonly nonDeleteMappings?: { if: TagsFilter; then: TypedTranslation }[] + private readonly nonDeleteMappings?: { if: TagConfigJson; then: Translation }[] public readonly softDeletionTags?: TagsFilter public readonly neededChangesets?: number @@ -61,8 +65,9 @@ export default class DeleteConfig { this.nonDeleteMappings = (json.nonDeleteMappings ?? []).map((nonDelete, i) => { const ctx = `${context}.extraDeleteReasons[${i}]` + TagUtils.Tag(nonDelete.if, ctx + ".if") // for validation only return { - if: TagUtils.Tag(nonDelete.if, ctx + ".if"), + if: nonDelete.if, then: Translations.T(nonDelete.then, ctx + ".then"), } }) @@ -88,4 +93,29 @@ export default class DeleteConfig { } this.neededChangesets = json.neededChangesets } + + public constructTagRendering(): TagRenderingConfig { + const t = Translations.t.delete + + const mappings: {if: TagConfigJson, then: Record} []= [] + for (const nonDeleteMapping of this.nonDeleteMappings) { + mappings.push({ + if: nonDeleteMapping.if, + then: nonDeleteMapping.then.translations + }) + } + + for (const deleteReason of this.deleteReasons) { + mappings.push({ + if: DeleteConfig.deleteReasonKey+ "="+ deleteReason.changesetMessage, + then: deleteReason.explanation.translations + }) + } + + const config: QuestionableTagRenderingConfigJson = { + question: t.whyDelete.translations, + mappings + } + return new TagRenderingConfig(config) + } } diff --git a/Models/ThemeConfig/DependencyCalculator.ts b/Models/ThemeConfig/DependencyCalculator.ts index 1e305a036..3267abef3 100644 --- a/Models/ThemeConfig/DependencyCalculator.ts +++ b/Models/ThemeConfig/DependencyCalculator.ts @@ -1,8 +1,8 @@ -import { SubstitutedTranslation } from "../../UI/SubstitutedTranslation" import TagRenderingConfig from "./TagRenderingConfig" import { ExtraFuncParams, ExtraFunctions } from "../../Logic/ExtraFunctions" import LayerConfig from "./LayerConfig" import { SpecialVisualization } from "../../UI/SpecialVisualization" +import SpecialVisualizations from "../../UI/SpecialVisualizations" export default class DependencyCalculator { public static GetTagRenderingDependencies(tr: TagRenderingConfig): string[] { @@ -16,8 +16,9 @@ export default class DependencyCalculator { for (const part of parts) { const specialVizs: { func: SpecialVisualization; args: string[] }[] = - SubstitutedTranslation.ExtractSpecialComponents(part) - .map((o) => o.special) + SpecialVisualizations.constructSpecification(part) + .filter((p) => typeof p !== "string") + .map((p) => <{ func: SpecialVisualization; args: string[] }>p) .filter((o) => o?.func?.getLayerDependencies !== undefined) for (const specialViz of specialVizs) { deps.push(...specialViz.func.getLayerDependencies(specialViz.args)) @@ -94,18 +95,16 @@ export default class DependencyCalculator { return [] }, - memberships: undefined, } - // Init the extra patched functions... - ExtraFunctions.FullPatchFeature(params, obj) + const helpers = ExtraFunctions.constructHelpers(params) // ... Run the calculated tag code, which will trigger the getFeaturesWithin above... for (let i = 0; i < layer.calculatedTags.length; i++) { const [key, code] = layer.calculatedTags[i] currentLine = i // Leak the state... currentKey = key try { - const func = new Function("feat", "return " + code + ";") - const result = func(obj) + const func = new Function("feat", "{"+ExtraFunctions.types.join(",")+"}", "return " + code + ";") + const result = func(obj, helpers) obj.properties[key] = JSON.stringify(result) } catch (e) {} } diff --git a/Models/ThemeConfig/FilterConfig.ts b/Models/ThemeConfig/FilterConfig.ts index 989d49f5b..f23e9943c 100644 --- a/Models/ThemeConfig/FilterConfig.ts +++ b/Models/ThemeConfig/FilterConfig.ts @@ -3,25 +3,24 @@ import { TagsFilter } from "../../Logic/Tags/TagsFilter" import FilterConfigJson from "./Json/FilterConfigJson" import Translations from "../../UI/i18n/Translations" import { TagUtils } from "../../Logic/Tags/TagUtils" -import ValidatedTextField from "../../UI/Input/ValidatedTextField" import { TagConfigJson } from "./Json/TagConfigJson" import { UIEventSource } from "../../Logic/UIEventSource" -import { FilterState } from "../FilteredLayer" import { QueryParameters } from "../../Logic/Web/QueryParameters" import { Utils } from "../../Utils" import { RegexTag } from "../../Logic/Tags/RegexTag" import BaseUIElement from "../../UI/BaseUIElement" import Table from "../../UI/Base/Table" import Combine from "../../UI/Base/Combine" - +export type FilterConfigOption = { + question: Translation + osmTags: TagsFilter | undefined + /* Only set if fields are present. Used to create `osmTags` (which are used to _actually_ filter) when the field is written*/ + readonly originalTagsSpec: TagConfigJson + fields: { name: string; type: string }[] +} export default class FilterConfig { public readonly id: string - public readonly options: { - question: Translation - osmTags: TagsFilter | undefined - originalTagsSpec: TagConfigJson - fields: { name: string; type: string }[] - }[] + public readonly options: FilterConfigOption[] public readonly defaultSelection?: number constructor(json: FilterConfigJson, context: string) { @@ -54,11 +53,7 @@ export default class FilterConfig { const fields: { name: string; type: string }[] = (option.fields ?? []).map((f, i) => { const type = f.type ?? "string" - if (!ValidatedTextField.ForType(type) === undefined) { - throw `Invalid filter: ${type} is not a valid validated textfield type (at ${ctx}.fields[${i}])\n\tTry one of ${Array.from( - ValidatedTextField.AvailableTypes() - ).join(",")}` - } + // Type is validated against 'ValidatedTextField' in Validation.ts, in ValidateFilterConfig if (f.name === undefined || f.name === "" || f.name.match(/[a-z0-9_-]+/) == null) { throw `Invalid filter: a variable name should match [a-z0-9_-]+ at ${ctx}.fields[${i}]` } @@ -149,36 +144,27 @@ export default class FilterConfig { }) } - public initState(): UIEventSource { - function reset(state: FilterState): string { - if (state === undefined) { - return "" - } - return "" + state.state - } - + public initState(layerId: string): UIEventSource { let defaultValue = "" if (this.options.length > 1) { defaultValue = "" + (this.defaultSelection ?? 0) + } else if (this.options[0].fields?.length > 0) { + defaultValue = "{}" } else { // Only a single option if (this.defaultSelection === 0) { defaultValue = "true" + } else { + defaultValue = "false" } } const qp = QueryParameters.GetQueryParameter( - "filter-" + this.id, + `filter-${layerId}-${this.id}`, defaultValue, "State of filter " + this.id ) if (this.options.length > 1) { - // This is a multi-option filter; state should be a number which selects the correct entry - const possibleStates: FilterState[] = this.options.map((opt, i) => ({ - currentFilter: opt.osmTags, - state: i, - })) - // We map the query parameter for this case return qp.sync( (str) => { @@ -187,62 +173,29 @@ export default class FilterConfig { // Nope, not a correct number! return undefined } - return possibleStates[parsed] + return parsed }, [], - reset + (n) => "" + n ) } const option = this.options[0] if (option.fields.length > 0) { - return qp.sync( - (str) => { - // There are variables in play! - // str should encode a json-hash - try { - const props = JSON.parse(str) - - const origTags = option.originalTagsSpec - const rewrittenTags = Utils.WalkJson(origTags, (v) => { - if (typeof v !== "string") { - return v - } - for (const key in props) { - v = (v).replace("{" + key + "}", props[key]) - } - return v - }) - const parsed = TagUtils.Tag(rewrittenTags) - return { - currentFilter: parsed, - state: str, - } - } catch (e) { - return undefined - } - }, - [], - reset - ) + return qp } - // The last case is pretty boring: it is checked or it isn't - const filterState: FilterState = { - currentFilter: option.osmTags, - state: "true", - } return qp.sync( (str) => { // Only a single option exists here if (str === "true") { - return filterState + return 0 } return undefined }, [], - reset + (n) => (n === undefined ? "false" : "true") ) } diff --git a/Models/ThemeConfig/Json/LayerConfigJson.ts b/Models/ThemeConfig/Json/LayerConfigJson.ts index 4baee1063..2bbee874f 100644 --- a/Models/ThemeConfig/Json/LayerConfigJson.ts +++ b/Models/ThemeConfig/Json/LayerConfigJson.ts @@ -25,13 +25,13 @@ export interface LayerConfigJson { * * If not given, will be hidden (and thus not toggable) in the layer control */ - name?: string | any + name?: string | Record /** * A description for this layer. * Shown in the layer selections and in the personel theme */ - description?: string | any + description?: string | Record /** * This determines where the data for the layer is fetched: from OSM or from an external geojson dataset. @@ -40,70 +40,57 @@ export interface LayerConfigJson { * * Every source _must_ define which tags _must_ be present in order to be picked up. * + * Note: a source must always be defined. 'special' is only allowed if this is a builtin-layer */ - source: { - /** - * Every source must set which tags have to be present in order to load the given layer. - */ - osmTags: TagConfigJson - /** - * The maximum amount of seconds that a tile is allowed to linger in the cache - */ - maxCacheAge?: number - } & ( - | { - /** - * If set, this custom overpass-script will be used instead of building one by using the OSM-tags. - * Specifying OSM-tags is still obligatory and will still hide non-matching items and they will be used for the rest of the pipeline. - * _This should be really rare_. - * - * For example, when you want to fetch all grass-areas in parks and which are marked as publicly accessible: - * ``` - * "source": { - * "overpassScript": - * "way[\"leisure\"=\"park\"];node(w);is_in;area._[\"leisure\"=\"park\"];(way(area)[\"landuse\"=\"grass\"]; node(w); );", - * "osmTags": "access=yes" - * } - * ``` - * - */ - overpassScript?: string - } - | { - /** - * The actual source of the data to load, if loaded via geojson. - * - * # A single geojson-file - * source: {geoJson: "https://my.source.net/some-geo-data.geojson"} - * fetches a geojson from a third party source - * - * # A tiled geojson source - * source: {geoJson: "https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson", geoJsonZoomLevel: 14} - * to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer - * - * Some API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max} - */ - geoJson: string - /** - * To load a tiled geojson layer, set the zoomlevel of the tiles - */ - geoJsonZoomLevel?: number - /** - * Indicates that the upstream geojson data is OSM-derived. - * Useful for e.g. merging or for scripts generating this cache - */ - isOsmCache?: boolean - /** - * Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this - */ - mercatorCrs?: boolean - /** - * Some API's have an id-field, but give it a different name. - * Setting this key will rename this field into 'id' - */ - idKey?: string - } - ) + source: + | "special" + | "special:library" + | ( + | { + /** + * Every source must set which tags have to be present in order to load the given layer. + */ + osmTags: TagConfigJson + /** + * The maximum amount of seconds that a tile is allowed to linger in the cache + */ + maxCacheAge?: number + } + | { + /** + * The actual source of the data to load, if loaded via geojson. + * + * # A single geojson-file + * source: {geoJson: "https://my.source.net/some-geo-data.geojson"} + * fetches a geojson from a third party source + * + * # A tiled geojson source + * source: {geoJson: "https://my.source.net/some-tile-geojson-{layer}-{z}-{x}-{y}.geojson", geoJsonZoomLevel: 14} + * to use a tiled geojson source. The web server must offer multiple geojsons. {z}, {x} and {y} are substituted by the location; {layer} is substituted with the id of the loaded layer + * + * Some API's use a BBOX instead of a tile, this can be used by specifying {y_min}, {y_max}, {x_min} and {x_max} + */ + geoJson: string + /** + * To load a tiled geojson layer, set the zoomlevel of the tiles + */ + geoJsonZoomLevel?: number + /** + * Indicates that the upstream geojson data is OSM-derived. + * Useful for e.g. merging or for scripts generating this cache + */ + isOsmCache?: boolean + /** + * Some API's use a mercator-projection (EPSG:900913) instead of WGS84. Set the flag `mercatorCrs: true` in the source for this + */ + mercatorCrs?: boolean + /** + * Some API's have an id-field, but give it a different name. + * Setting this key will rename this field into 'id' + */ + idKey?: string + } + ) /** * @@ -137,9 +124,6 @@ export interface LayerConfigJson { * If set, only features matching this extra tag will be shown. * This is useful to hide certain features from view. * - * Important: hiding features does not work dynamically, but is only calculated when the data is first renders. - * This implies that it is not possible to hide a feature after a tagging change - * * The default value is 'yes' */ isShown?: TagConfigJson @@ -152,7 +136,7 @@ export interface LayerConfigJson { forceLoad?: false | boolean /** - * The minimum needed zoomlevel required before loading of the data start + * The minimum needed zoomlevel required before loading the data * Default: 0 */ minzoom?: number @@ -228,7 +212,7 @@ export interface LayerConfigJson { * * Do _not_ indicate 'new': 'add a new shop here' is incorrect, as the shop might have existed forever, it could just be unmapped! */ - title: string | any + title: string | Record /** * The tags to add. It determines the icon too */ @@ -239,7 +223,7 @@ export interface LayerConfigJson { * * (The first sentence is until the first '.'-character in the description) */ - description?: string | any + description?: string | Record /** * Example images, which show real-life pictures of what such a feature might look like @@ -412,4 +396,14 @@ export interface LayerConfigJson { * no-question-hint-check: disables a check in MiscTagRenderingChecks which complains about 'div', 'span' or 'class=subtle'-HTML elements in the tagRendering */ "#"?: string | "no-question-hint-check" + + /** + * If set, open the selectedElementView in a floatOver instead of on the right + */ + popupInFloatover?: boolean + + /** + * _Set automatically by MapComplete, please ignore_ + */ + fullNodeDatabase?: boolean } diff --git a/Models/ThemeConfig/Json/LayoutConfigJson.ts b/Models/ThemeConfig/Json/LayoutConfigJson.ts index 4a2a761b7..ad6f6a517 100644 --- a/Models/ThemeConfig/Json/LayoutConfigJson.ts +++ b/Models/ThemeConfig/Json/LayoutConfigJson.ts @@ -1,7 +1,8 @@ import { LayerConfigJson } from "./LayerConfigJson" -import TilesourceConfigJson from "./TilesourceConfigJson" import ExtraLinkConfigJson from "./ExtraLinkConfigJson" +import { RasterLayerProperties } from "../../RasterLayerProperties" + /** * Defines the entire theme. * @@ -41,23 +42,23 @@ export interface LayoutConfigJson { /** * The title, as shown in the welcome message and the more-screen. */ - title: string | any + title: string | Record /** * A short description, showed as social description and in the 'more theme'-buttons. * Note that if this one is not defined, the first sentence of 'description' is used */ - shortDescription?: string | any + shortDescription?: string | Record /** * The description, as shown in the welcome message and the more-screen */ - description: string | any + description: string | Record /** * A part of the description, shown under the login-button. */ - descriptionTail?: string | any + descriptionTail?: string | Record /** * The icon representing this theme. @@ -148,7 +149,7 @@ export interface LayoutConfigJson { /** * Define some (overlay) slippy map tilesources */ - tileLayerSources?: TilesourceConfigJson[] + tileLayerSources?: (RasterLayerProperties & { defaultState?: true | boolean })[] /** * The layers to display. @@ -196,7 +197,7 @@ export interface LayoutConfigJson { | string | { builtin: string | string[] - override: any + override: Partial /** * TagRenderings with any of these labels will be removed from the layer. * Note that the 'id' and 'group' are considered labels too @@ -205,25 +206,6 @@ export interface LayoutConfigJson { } )[] - /** - * If defined, data will be clustered. - * Defaults to {maxZoom: 16, minNeeded: 500} - */ - clustering?: - | { - /** - * All zoom levels above 'maxzoom' are not clustered anymore. - * Defaults to 18 - */ - maxZoom?: number - /** - * The number of elements per tile needed to start clustering - * If clustering is defined, defaults to 250 - */ - minNeededElements?: number - } - | false - /** * The URL of a custom CSS stylesheet to modify the layout */ @@ -294,11 +276,11 @@ export interface LayoutConfigJson { /** * If set to true, download button for the data will be shown (offers downloading as geojson and csv) */ - enableDownload?: false | boolean + enableDownload?: true | boolean /** * If set to true, exporting a pdf is enabled */ - enablePdfDownload?: false | boolean + enablePdfDownload?: true | boolean /** * If true, notes will be loaded and parsed. If a note is an import (as created by the import_helper.html-tool from mapcomplete), @@ -316,4 +298,12 @@ export interface LayoutConfigJson { * Set a different timeout for overpass queries - in seconds. Default: 30s */ overpassTimeout?: number + + /** + * Enables tracking of all nodes when data is loaded. + * This is useful for the 'ImportWay' and 'ConflateWay'-buttons who need this database. + * + * Note: this flag will be automatically set. + */ + enableNodeDatabase?: boolean } diff --git a/Models/ThemeConfig/Json/LineRenderingConfigJson.ts b/Models/ThemeConfig/Json/LineRenderingConfigJson.ts index 6a359792b..d93c31215 100644 --- a/Models/ThemeConfig/Json/LineRenderingConfigJson.ts +++ b/Models/ThemeConfig/Json/LineRenderingConfigJson.ts @@ -31,14 +31,11 @@ export default interface LineRenderingConfigJson { */ lineCap?: "round" | "square" | "butt" | string | TagRenderingConfigJson - /** - * Whether or not to fill polygons - */ - fill?: "yes" | "no" | TagRenderingConfigJson /** * The color to fill a polygon with. - * If undefined, this will be slightly more opaque version of the stroke line + * If undefined, this will be slightly more opaque version of the stroke line. + * Use '#00000000' to make the fill invisible */ fillColor?: string | TagRenderingConfigJson diff --git a/Models/ThemeConfig/Json/PointRenderingConfigJson.ts b/Models/ThemeConfig/Json/PointRenderingConfigJson.ts index 7fe5e62e8..54ad00db9 100644 --- a/Models/ThemeConfig/Json/PointRenderingConfigJson.ts +++ b/Models/ThemeConfig/Json/PointRenderingConfigJson.ts @@ -12,8 +12,11 @@ import { TagConfigJson } from "./TagConfigJson" export default interface PointRenderingConfigJson { /** * All the locations that this point should be rendered at. - * Using `location: ["point", "centroid"] will always render centerpoint. - * 'projected_centerpoint' will show an item on the line itself, near the middle of the line. (LineStrings only) + * Possible values are: + * - `point`: only renders points at their location + * - `centroid`: show a symbol at the centerpoint of a (multi)Linestring and (multi)polygon. Points will _not_ be rendered with this + * - `projected_centerpoint`: Only on (multi)linestrings: calculate the centerpoint and snap it to the way + * - `start` and `end`: only on linestrings: add a point to the first/last coordinate of the LineString */ location: ("point" | "centroid" | "start" | "end" | "projected_centerpoint" | string)[] @@ -66,12 +69,33 @@ export default interface PointRenderingConfigJson { label?: string | TagRenderingConfigJson /** - * A snippet of css code + * A snippet of css code which is applied onto the container of the entire marker */ css?: string | TagRenderingConfigJson /** - * A snippet of css-classes. They can be space-separated + * A snippet of css-classes which are applied onto the container of the entire marker. They can be space-separated */ cssClasses?: string | TagRenderingConfigJson + + /** + * Css that is applied onto the label + */ + labelCss?: string | TagRenderingConfigJson + + /** + * Css classes that are applied onto the label; can be space-separated + */ + labelCssClasses?: string | TagRenderingConfigJson + + /** + * If the map is pitched, the marker will stay parallel to the screen. + * Set to 'map' if you want to put it flattened on the map + */ + pitchAlignment?: "canvas" | "map" | TagRenderingConfigJson + + /** + * If the map is rotated, the icon will still point to the north if no rotation was applied + */ + rotationAlignment?: "map" | "canvas" | TagRenderingConfigJson } diff --git a/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.ts b/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.ts index 0d1db2595..c44df3235 100644 --- a/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.ts +++ b/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson.ts @@ -10,7 +10,7 @@ export interface MappingConfigJson { * Shown if the 'if is fulfilled * Type: rendered */ - then: string | any + then: string | Record /** * An extra icon supporting the choice * Type: icon @@ -186,9 +186,10 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs /** * When set, influences the way a question is asked. - * Instead of showing a full-widht text field, the text field will be shown within the rendering of the question. + * Instead of showing a full-width text field, the text field will be shown within the rendering of the question. * * This combines badly with special input elements, as it'll distort the layout. + * Note that this will be set automatically if no special elements are present. */ inline?: boolean diff --git a/Models/ThemeConfig/Json/TagRenderingConfigJson.ts b/Models/ThemeConfig/Json/TagRenderingConfigJson.ts index 19df10751..583294f3d 100644 --- a/Models/ThemeConfig/Json/TagRenderingConfigJson.ts +++ b/Models/ThemeConfig/Json/TagRenderingConfigJson.ts @@ -13,23 +13,21 @@ export interface TagRenderingConfigJson { */ id?: string - /** - * If 'group' is defined on many tagRenderings, these are grouped together when shown. The questions are grouped together as well. - * The first tagRendering of a group will always be a sticky element. - * - * @deprecated - */ - group?: string - /** * A list of labels. These are strings that are used for various purposes, e.g. to filter them away */ labels?: string[] + /** + * A list of css-classes to apply to the entire tagRendering if the answer is known (not applied on the question). + * This is only for advanced users + */ + classes?: string | string[] + /** * A human-readable text explaining what this tagRendering does */ - description?: string | any + description?: string | Record /** * Renders this value. Note that "{key}"-parts are substituted by the corresponding values of the element. @@ -38,7 +36,10 @@ export interface TagRenderingConfigJson { * Note that this is a HTML-interpreted value, so you can add links as e.g. '{website}' or include images such as `This is of type A
` * type: rendered */ - render?: string | any + render?: + | string + | Record + | { special: Record> & { type: string } } /** * Only show this tagrendering (or ask the question) if the selected object also matches the tags specified as `condition`. @@ -81,6 +82,13 @@ export interface TagRenderingConfigJson { * */ condition?: TagConfigJson + /** + * If set, this tag will be evaluated agains the _usersettings/application state_ table. + * Enable 'show debug info' in user settings to see available options. + * Note that values with an underscore depicts _application state_ (including metainfo about the user) whereas values without an underscore depict _user settings_ + */ + metacondition?: TagConfigJson + /** * Allow freeform text input from the user */ @@ -110,7 +118,7 @@ export interface TagRenderingConfigJson { * If not known yet, the user will be presented with `then` as an option * Type: rendered */ - then: string | any + then: string | Record /** * An icon supporting this mapping; typically shown pretty small * Type: icon diff --git a/Models/ThemeConfig/Json/TilesourceConfigJson.ts b/Models/ThemeConfig/Json/TilesourceConfigJson.ts deleted file mode 100644 index ca80ed0c6..000000000 --- a/Models/ThemeConfig/Json/TilesourceConfigJson.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Configuration for a tilesource config - */ -export default interface TilesourceConfigJson { - /** - * Id of this overlay, used in the URL-parameters to set the state - */ - id: string - /** - * The path, where {x}, {y} and {z} will be substituted - */ - source: string - /** - * Wether or not this is an overlay. Default: true - */ - isOverlay?: boolean - - /** - * How this will be shown in the selection menu. - * Make undefined if this may not be toggled - */ - name?: any | string - - /** - * Only visible at this or a higher zoom level - */ - minZoom?: number - - /** - * Only visible at this or a lower zoom level - */ - maxZoom?: number - - /** - * The default state, set to false to hide by default - */ - defaultState: boolean -} diff --git a/Models/ThemeConfig/Json/UnitConfigJson.ts b/Models/ThemeConfig/Json/UnitConfigJson.ts index 88d54009f..fbfd0ef9b 100644 --- a/Models/ThemeConfig/Json/UnitConfigJson.ts +++ b/Models/ThemeConfig/Json/UnitConfigJson.ts @@ -60,7 +60,7 @@ export default interface UnitConfigJson { /** * Every key from this list will be normalized. * - * To render a united value properly, use + * To render the value properly (with a human readable denomination), use `{canonical()}` */ appliesToKey: string[] /** diff --git a/Models/ThemeConfig/LayerConfig.ts b/Models/ThemeConfig/LayerConfig.ts index 24fc7bb14..cd4433fb9 100644 --- a/Models/ThemeConfig/LayerConfig.ts +++ b/Models/ThemeConfig/LayerConfig.ts @@ -26,18 +26,21 @@ import Table from "../../UI/Base/Table" import FilterConfigJson from "./Json/FilterConfigJson" import { And } from "../../Logic/Tags/And" import { Overpass } from "../../Logic/Osm/Overpass" -import Constants from "../Constants" import { FixedUiElement } from "../../UI/Base/FixedUiElement" import Svg from "../../Svg" -import { UIEventSource } from "../../Logic/UIEventSource" +import { ImmutableStore } from "../../Logic/UIEventSource" import { OsmTags } from "../OsmFeature" +import Constants from "../Constants" export default class LayerConfig extends WithContextLoader { public static readonly syncSelectionAllowed = ["no", "local", "theme-only", "global"] as const public readonly id: string public readonly name: Translation public readonly description: Translation - public readonly source: SourceConfig + /** + * Only 'null' for special, privileged layers + */ + public readonly source: SourceConfig | null public readonly calculatedTags: [string, string, boolean][] public readonly doNotDownload: boolean public readonly passAllFeatures: boolean @@ -65,6 +68,9 @@ export default class LayerConfig extends WithContextLoader { public readonly forceLoad: boolean public readonly syncSelection: typeof LayerConfig.syncSelectionAllowed[number] // this is a trick to conver a constant array of strings into a type union of these values + public readonly _needsFullNodeDatabase: boolean + public readonly popupInFloatover + constructor(json: LayerConfigJson, context?: string, official: boolean = true) { context = context + "." + json.id const translationContext = "layers:" + json.id @@ -83,7 +89,9 @@ export default class LayerConfig extends WithContextLoader { throw "Layer " + this.id + " does not define a source section (" + context + ")" } - if (json.source.osmTags === undefined) { + if (json.source === "special" || json.source === "special:library") { + this.source = null + } else if (json.source["osmTags"] === undefined) { throw ( "Layer " + this.id + @@ -100,7 +108,6 @@ export default class LayerConfig extends WithContextLoader { throw `${context}: The id of a layer should match [a-z0-9-_]*: ${json.id}` } - this.maxAgeOfCache = json.source.maxCacheAge ?? 24 * 60 * 60 * 30 if ( json.syncSelection !== undefined && LayerConfig.syncSelectionAllowed.indexOf(json.syncSelection) < 0 @@ -115,13 +122,28 @@ export default class LayerConfig extends WithContextLoader { ) } this.syncSelection = json.syncSelection ?? "no" - const osmTags = TagUtils.Tag(json.source.osmTags, context + "source.osmTags") + if (typeof json.source !== "string") { + this.maxAgeOfCache = json.source["maxCacheAge"] ?? 24 * 60 * 60 * 30 + const osmTags = TagUtils.Tag(json.source["osmTags"], context + "source.osmTags") + if (osmTags.isNegative()) { + throw ( + context + + "The source states tags which give a very wide selection: it only uses negative expressions, which will result in too much and unexpected data. Add at least one required tag. The tags are:\n\t" + + osmTags.asHumanString(false, false, {}) + ) + } - if (Constants.priviliged_layers.indexOf(this.id) < 0 && osmTags.isNegative()) { - throw ( - context + - "The source states tags which give a very wide selection: it only uses negative expressions, which will result in too much and unexpected data. Add at least one required tag. The tags are:\n\t" + - osmTags.asHumanString(false, false, {}) + this.source = new SourceConfig( + { + osmTags: osmTags, + geojsonSource: json.source["geoJson"], + geojsonSourceLevel: json.source["geoJsonZoomLevel"], + overpassScript: json.source["overpassScript"], + isOsmCache: json.source["isOsmCache"], + mercatorCrs: json.source["mercatorCrs"], + idKey: json.source["idKey"], + }, + json.id ) } @@ -133,20 +155,6 @@ export default class LayerConfig extends WithContextLoader { throw context + "Use 'geoJson' instead of 'geojson' (the J is a capital letter)" } - this.source = new SourceConfig( - { - osmTags: osmTags, - geojsonSource: json.source["geoJson"], - geojsonSourceLevel: json.source["geoJsonZoomLevel"], - overpassScript: json.source["overpassScript"], - isOsmCache: json.source["isOsmCache"], - mercatorCrs: json.source["mercatorCrs"], - idKey: json.source["idKey"], - }, - Constants.priviliged_layers.indexOf(this.id) > 0, - json.id - ) - this.allowSplit = json.allowSplit ?? false this.name = Translations.T(json.name, translationContext + ".name") if (json.units !== undefined && !Array.isArray(json.units)) { @@ -209,6 +217,7 @@ export default class LayerConfig extends WithContextLoader { this.doNotDownload = json.doNotDownload ?? false this.passAllFeatures = json.passAllFeatures ?? false this.minzoom = json.minzoom ?? 0 + this._needsFullNodeDatabase = json.fullNodeDatabase ?? false if (json["minZoom"] !== undefined) { throw "At " + context + ": minzoom is written all lowercase" } @@ -316,7 +325,8 @@ export default class LayerConfig extends WithContextLoader { } else if ( !hasCenterRendering && this.lineRendering.length === 0 && - !this.source.geojsonSource?.startsWith( + Constants.priviliged_layers.indexOf(this.id) < 0 && + !this.source?.geojsonSource?.startsWith( "https://api.openstreetmap.org/api/0.6/notes.json" ) ) { @@ -379,7 +389,7 @@ export default class LayerConfig extends WithContextLoader { readOnlyMode: true, }) - this.title = this.tr("title", undefined) + this.title = this.tr("title", undefined, translationContext) this.isShown = TagUtils.TagD(json.isShown, context + ".isShown") this.deletion = null @@ -406,6 +416,8 @@ export default class LayerConfig extends WithContextLoader { ": showIf. Did you mean 'isShown' instead?" ) } + this.popupInFloatover = json.popupInFloatover ?? false + } public defaultIcon(): BaseUIElement | undefined { @@ -416,11 +428,13 @@ export default class LayerConfig extends WithContextLoader { if (mapRendering === undefined) { return undefined } - return mapRendering.GetBaseIcon(this.GetBaseTags()) + return mapRendering.GetBaseIcon(this.GetBaseTags(), { noFullWidth: true }) } - public GetBaseTags(): any { - return TagUtils.changeAsProperties(this.source.osmTags.asChange({ id: "node/-1" })) + public GetBaseTags(): Record { + return TagUtils.changeAsProperties( + this.source?.osmTags?.asChange({ id: "node/-1" }) ?? [{ k: "id", v: "node/-1" }] + ) } public GenerateDocumentation( @@ -470,7 +484,7 @@ export default class LayerConfig extends WithContextLoader { ) } - if (this.source.geojsonSource !== undefined) { + if (this.source?.geojsonSource !== undefined) { extraProps.push( new Combine([ Utils.runningFromConsole @@ -520,8 +534,8 @@ export default class LayerConfig extends WithContextLoader { ) } - let neededTags: TagsFilter[] = [this.source.osmTags] - if (this.source.osmTags["and"] !== undefined) { + let neededTags: TagsFilter[] = Utils.NoNull([this.source?.osmTags]) + if (this.source?.osmTags["and"] !== undefined) { neededTags = this.source.osmTags["and"] } @@ -584,17 +598,15 @@ export default class LayerConfig extends WithContextLoader { .filter((mr) => mr.location.has("point")) .map( (mr) => - mr.GenerateLeafletStyle( - new UIEventSource({ id: "node/-1" }), - false, - { includeBadges: false } - ).html + mr.RenderIcon(new ImmutableStore({ id: "node/-1" }), false, { + includeBadges: false, + }).html ) .find((i) => i !== undefined) } let overpassLink: BaseUIElement = undefined - if (Constants.priviliged_layers.indexOf(this.id) < 0) { + if (this.source !== undefined) { try { overpassLink = new Link( "Execute on overpass", @@ -610,17 +622,26 @@ export default class LayerConfig extends WithContextLoader { filterDocs.push(new Title("Filters", 4)) filterDocs.push(...this.filters.map((filter) => filter.GenerateDocs())) } + + const tagsDescription = [] + if (this.source === null) { + tagsDescription.push( + new Title("Basic tags for this layer", 2), + "Elements must have the all of following tags to be shown on this layer:", + new List(neededTags.map((t) => t.asHumanString(true, false, {}))), + overpassLink + ) + } else { + tagsDescription.push("This is a special layer - data is not sourced from OpenStreetMap") + } + return new Combine([ new Combine([new Title(this.id, 1), iconImg, this.description, "\n"]).SetClass( "flex flex-col" ), new List(extraProps), ...usingLayer, - - new Title("Basic tags for this layer", 2), - "Elements must have the all of following tags to be shown on this layer:", - new List(neededTags.map((t) => t.asHumanString(true, false, {}))), - overpassLink, + ...tagsDescription, new Title("Supported attributes", 2), quickOverview, ...this.tagRenderings.map((tr) => tr.GenerateDocumentation()), diff --git a/Models/ThemeConfig/LayoutConfig.ts b/Models/ThemeConfig/LayoutConfig.ts index 4763169de..be5cda3ec 100644 --- a/Models/ThemeConfig/LayoutConfig.ts +++ b/Models/ThemeConfig/LayoutConfig.ts @@ -3,12 +3,13 @@ import { LayoutConfigJson } from "./Json/LayoutConfigJson" import LayerConfig from "./LayerConfig" import { LayerConfigJson } from "./Json/LayerConfigJson" import Constants from "../Constants" -import TilesourceConfig from "./TilesourceConfig" import { ExtractImages } from "./Conversion/FixImages" import ExtraLinkConfig from "./ExtraLinkConfig" import { Utils } from "../../Utils" import LanguageUtils from "../../Utils/LanguageUtils" +import { RasterLayerProperties } from "../RasterLayerProperties" + /** * Minimal information about a theme **/ @@ -40,11 +41,7 @@ export default class LayoutConfig implements LayoutInformation { public widenFactor: number public defaultBackgroundId?: string public layers: LayerConfig[] - public tileLayerSources: TilesourceConfig[] - public readonly clustering?: { - maxZoom: number - minNeededElements: number - } + public tileLayerSources: (RasterLayerProperties & { defaultState?: true | boolean })[] public readonly hideFromOverview: boolean public lockLocation: boolean | [[number, number], [number, number]] public readonly enableUserBadge: boolean @@ -166,9 +163,7 @@ export default class LayoutConfig implements LayoutInformation { this.widenFactor = json.widenFactor ?? 1.5 this.defaultBackgroundId = json.defaultBackgroundId - this.tileLayerSources = (json.tileLayerSources ?? []).map( - (config, i) => new TilesourceConfig(config, `${this.id}.tileLayerSources[${i}]`) - ) + this.tileLayerSources = json.tileLayerSources ?? [] // At this point, layers should be expanded and validated either by the generateScript or the LegacyJsonConvert this.layers = json.layers.map( (lyrJson) => @@ -189,22 +184,6 @@ export default class LayoutConfig implements LayoutInformation { context + ".extraLink" ) - this.clustering = { - maxZoom: 16, - minNeededElements: 250, - } - if (json.clustering === false) { - this.clustering = { - maxZoom: 0, - minNeededElements: 100000, - } - } else if (json.clustering) { - this.clustering = { - maxZoom: json.clustering.maxZoom ?? 18, - minNeededElements: json.clustering.minNeededElements ?? 250, - } - } - this.hideFromOverview = json.hideFromOverview ?? false this.lockLocation = <[[number, number], [number, number]]>json.lockLocation ?? undefined this.enableUserBadge = json.enableUserBadge ?? true @@ -216,8 +195,8 @@ export default class LayoutConfig implements LayoutInformation { this.enableAddNewPoints = json.enableAddNewPoints ?? true this.enableBackgroundLayerSelection = json.enableBackgroundLayerSelection ?? true this.enableShowAllQuestions = json.enableShowAllQuestions ?? false - this.enableExportButton = json.enableDownload ?? false - this.enablePdfDownload = json.enablePdfDownload ?? false + this.enableExportButton = json.enableDownload ?? true + this.enablePdfDownload = json.enablePdfDownload ?? true this.customCss = json.customCss this.overpassUrl = Constants.defaultOverpassUrls if (json.overpassUrl !== undefined) { @@ -307,11 +286,14 @@ export default class LayoutConfig implements LayoutInformation { return { untranslated, total } } - public getMatchingLayer(tags: any): LayerConfig | undefined { + public getMatchingLayer(tags: Record): LayerConfig | undefined { if (tags === undefined) { return undefined } for (const layer of this.layers) { + if (!layer.source) { + continue + } if (layer.source.osmTags.matchesProperties(tags)) { return layer } diff --git a/Models/ThemeConfig/PointRenderingConfig.ts b/Models/ThemeConfig/PointRenderingConfig.ts index 8183ab032..c3cc1059a 100644 --- a/Models/ThemeConfig/PointRenderingConfig.ts +++ b/Models/ThemeConfig/PointRenderingConfig.ts @@ -1,19 +1,19 @@ import PointRenderingConfigJson from "./Json/PointRenderingConfigJson" import TagRenderingConfig from "./TagRenderingConfig" -import { TagsFilter } from "../../Logic/Tags/TagsFilter" -import { TagUtils } from "../../Logic/Tags/TagUtils" -import { Utils } from "../../Utils" +import {TagsFilter} from "../../Logic/Tags/TagsFilter" +import {TagUtils} from "../../Logic/Tags/TagUtils" +import {Utils} from "../../Utils" import Svg from "../../Svg" import WithContextLoader from "./WithContextLoader" -import { Store, UIEventSource } from "../../Logic/UIEventSource" +import {Store} from "../../Logic/UIEventSource" import BaseUIElement from "../../UI/BaseUIElement" -import { FixedUiElement } from "../../UI/Base/FixedUiElement" +import {FixedUiElement} from "../../UI/Base/FixedUiElement" import Img from "../../UI/Base/Img" import Combine from "../../UI/Base/Combine" -import { VariableUiElement } from "../../UI/Base/VariableUIElement" +import {VariableUiElement} from "../../UI/Base/VariableUIElement" export default class PointRenderingConfig extends WithContextLoader { - private static readonly allowed_location_codes = new Set([ + static readonly allowed_location_codes: ReadonlySet = new Set([ "point", "centroid", "start", @@ -28,9 +28,13 @@ export default class PointRenderingConfig extends WithContextLoader { public readonly iconBadges: { if: TagsFilter; then: TagRenderingConfig }[] public readonly iconSize: TagRenderingConfig public readonly label: TagRenderingConfig + public readonly labelCss: TagRenderingConfig + public readonly labelCssClasses: TagRenderingConfig public readonly rotation: TagRenderingConfig public readonly cssDef: TagRenderingConfig public readonly cssClasses?: TagRenderingConfig + public readonly pitchAlignment?: TagRenderingConfig + public readonly rotationAlignment?: TagRenderingConfig constructor(json: PointRenderingConfigJson, context: string) { super(json, context) @@ -70,6 +74,8 @@ export default class PointRenderingConfig extends WithContextLoader { this.cssDef = this.tr("css", undefined) } this.cssClasses = this.tr("cssClasses", undefined) + this.labelCss = this.tr("labelCss", undefined) + this.labelCssClasses = this.tr("labelCssClasses", undefined) this.iconBadges = (json.iconBadges ?? []).map((overlay, i) => { return { if: TagUtils.Tag(overlay.if), @@ -77,7 +83,7 @@ export default class PointRenderingConfig extends WithContextLoader { } }) - const iconPath = this.icon?.GetRenderValue({ id: "node/-1" })?.txt + const iconPath = this.icon?.GetRenderValue({id: "node/-1"})?.txt if (iconPath !== undefined && iconPath.startsWith(Utils.assets_path)) { const iconKey = iconPath.substr(Utils.assets_path.length) if (Svg.All[iconKey] === undefined) { @@ -87,6 +93,11 @@ export default class PointRenderingConfig extends WithContextLoader { this.iconSize = this.tr("iconSize", "40,40,center") this.label = this.tr("label", undefined) this.rotation = this.tr("rotation", "0") + this.pitchAlignment = this.tr("pitchAlignment", "canvas") + this.rotationAlignment = this.tr( + "rotationAlignment", + json.pitchAlignment === "map" ? "map" : "canvas" + ) } /** @@ -125,7 +136,10 @@ export default class PointRenderingConfig extends WithContextLoader { multiSpec: string, rotation: string, isBadge: boolean, - defaultElement: BaseUIElement = undefined + defaultElement: BaseUIElement = undefined, + options?: { + noFullWidth?: boolean + } ) { if (multiSpec === undefined) { return defaultElement @@ -139,12 +153,22 @@ export default class PointRenderingConfig extends WithContextLoader { if (elements.length === 0) { return defaultElement } else { - return new Combine(elements).SetClass("relative block w-full h-full") + const combine = new Combine(elements).SetClass("relative block") + if (options?.noFullWidth) { + return combine + } + combine.SetClass("w-full h-full") + return combine } } - public GetBaseIcon(tags?: any): BaseUIElement { - tags = tags ?? { id: "node/-1" } + public GetBaseIcon( + tags?: Record, + options?: { + noFullWidth?: boolean + } + ): BaseUIElement { + tags = tags ?? {id: "node/-1"} let defaultPin: BaseUIElement = undefined if (this.label === undefined) { defaultPin = Svg.teardrop_with_hole_green_svg() @@ -161,10 +185,14 @@ export default class PointRenderingConfig extends WithContextLoader { // This layer doesn't want to show an icon right now return undefined } - return PointRenderingConfig.FromHtmlMulti(htmlDefs, rotation, false, defaultPin) + if (htmlDefs.startsWith("<") && htmlDefs.endsWith(">")) { + // This is probably already prepared HTML + return new FixedUiElement(Utils.SubstituteKeys(htmlDefs, tags)) + } + return PointRenderingConfig.FromHtmlMulti(htmlDefs, rotation, false, defaultPin, options) } - public GetSimpleIcon(tags: Store): BaseUIElement { + public GetSimpleIcon(tags: Store>): BaseUIElement { const self = this if (this.icon === undefined) { return undefined @@ -174,8 +202,8 @@ export default class PointRenderingConfig extends WithContextLoader { ) } - public GenerateLeafletStyle( - tags: Store, + public RenderIcon( + tags: Store>, clickable: boolean, options?: { noSize?: false | boolean @@ -183,11 +211,7 @@ export default class PointRenderingConfig extends WithContextLoader { } ): { html: BaseUIElement - iconSize: [number, number] iconAnchor: [number, number] - popupAnchor: [number, number] - iconUrl: string - className: string } { function num(str, deflt = 40) { const n = Number(str) @@ -211,20 +235,21 @@ export default class PointRenderingConfig extends WithContextLoader { let iconH = num(iconSize[1]) const mode = iconSize[2]?.trim()?.toLowerCase() ?? "center" - let anchorW = iconW / 2 - let anchorH = iconH / 2 + // in MapLibre, the offset is relative to the _center_ of the object, with left = [-x, 0] and up = [0,-y] + let anchorW = 0 + let anchorH = 0 if (mode === "left") { - anchorW = 0 + anchorW = -iconW / 2 } if (mode === "right") { - anchorW = iconW + anchorW = iconW / 2 } if (mode === "top") { - anchorH = 0 + anchorH = iconH / 2 } if (mode === "bottom") { - anchorH = iconH + anchorH = -iconH / 2 } const icon = this.GetSimpleIcon(tags) @@ -240,10 +265,11 @@ export default class PointRenderingConfig extends WithContextLoader { iconAndBadges.SetClass("w-full h-full") } - const css = this.cssDef?.GetRenderValue(tags, undefined)?.txt - const cssClasses = this.cssClasses?.GetRenderValue(tags, undefined)?.txt + const css = this.cssDef?.GetRenderValue(tags.data)?.txt + const cssClasses = this.cssClasses?.GetRenderValue(tags.data)?.txt let label = this.GetLabel(tags) + let htmlEl: BaseUIElement if (icon === undefined && label === undefined) { htmlEl = undefined @@ -264,15 +290,11 @@ export default class PointRenderingConfig extends WithContextLoader { } return { html: htmlEl, - iconSize: [iconW, iconH], iconAnchor: [anchorW, anchorH], - popupAnchor: [0, 3 - anchorH], - iconUrl: undefined, - className: clickable ? "leaflet-div-icon" : "leaflet-div-icon unclickable", } } - private GetBadges(tags: Store): BaseUIElement { + private GetBadges(tags: Store>): BaseUIElement { if (this.iconBadges.length === 0) { return undefined } @@ -288,6 +310,12 @@ export default class PointRenderingConfig extends WithContextLoader { badge.then.GetRenderValue(tags)?.txt, tags ) + if (htmlDefs.startsWith("<") && htmlDefs.endsWith(">")) { + // This is probably an HTML-element + return new FixedUiElement(Utils.SubstituteKeys(htmlDefs, tags)) + .SetStyle("width: 1.5rem") + .SetClass("block") + } const badgeElement = PointRenderingConfig.FromHtmlMulti( htmlDefs, "0", @@ -304,18 +332,24 @@ export default class PointRenderingConfig extends WithContextLoader { ).SetClass("absolute bottom-0 right-1/3 h-1/2 w-0") } - private GetLabel(tags: Store): BaseUIElement { + private GetLabel(tags: Store>): BaseUIElement { if (this.label === undefined) { return undefined } + const cssLabel = this.labelCss?.GetRenderValue(tags.data)?.txt + const cssClassesLabel = this.labelCssClasses?.GetRenderValue(tags.data)?.txt const self = this return new VariableUiElement( tags.map((tags) => { const label = self.label ?.GetRenderValue(tags) ?.Subs(tags) - ?.SetClass("block text-center") - return new Combine([label]).SetClass("flex flex-col items-center mt-1") + ?.SetClass("block center absolute text-center ") + ?.SetClass(cssClassesLabel) + if (cssLabel) { + label.SetStyle(cssLabel) + } + return new Combine([label]).SetClass("flex flex-col items-center") }) ) } diff --git a/Models/ThemeConfig/SourceConfig.ts b/Models/ThemeConfig/SourceConfig.ts index 7d285cdd7..6afd68f08 100644 --- a/Models/ThemeConfig/SourceConfig.ts +++ b/Models/ThemeConfig/SourceConfig.ts @@ -3,7 +3,6 @@ import { RegexTag } from "../../Logic/Tags/RegexTag" export default class SourceConfig { public osmTags?: TagsFilter - public readonly overpassScript?: string public geojsonSource?: string public geojsonZoomLevel?: number public isOsmCacheLayer: boolean @@ -20,7 +19,6 @@ export default class SourceConfig { geojsonSourceLevel?: number idKey?: string }, - isSpecialLayer: boolean, context?: string ) { let defined = 0 @@ -51,7 +49,7 @@ export default class SourceConfig { throw `Source defines a geojson-zoomLevel, but does not specify {x} nor {y} (or equivalent), this is probably a bug (in context ${context})` } } - if (params.osmTags !== undefined && !isSpecialLayer) { + if (params.osmTags !== undefined) { const optimized = params.osmTags.optimize() if (optimized === false) { throw ( @@ -72,7 +70,6 @@ export default class SourceConfig { } } this.osmTags = params.osmTags ?? new RegexTag("id", /.*/) - this.overpassScript = params.overpassScript this.geojsonSource = params.geojsonSource this.geojsonZoomLevel = params.geojsonSourceLevel this.isOsmCacheLayer = params.isOsmCache ?? false diff --git a/Models/ThemeConfig/TagRenderingConfig.ts b/Models/ThemeConfig/TagRenderingConfig.ts index 1bd4149da..cf88c2ed6 100644 --- a/Models/ThemeConfig/TagRenderingConfig.ts +++ b/Models/ThemeConfig/TagRenderingConfig.ts @@ -1,23 +1,20 @@ -import { Translation, TypedTranslation } from "../../UI/i18n/Translation" -import { TagsFilter } from "../../Logic/Tags/TagsFilter" +import {Translation, TypedTranslation} from "../../UI/i18n/Translation" +import {TagsFilter} from "../../Logic/Tags/TagsFilter" import Translations from "../../UI/i18n/Translations" -import { TagUtils, UploadableTag } from "../../Logic/Tags/TagUtils" -import { And } from "../../Logic/Tags/And" -import ValidatedTextField from "../../UI/Input/ValidatedTextField" -import { Utils } from "../../Utils" -import { Tag } from "../../Logic/Tags/Tag" +import {TagUtils, UploadableTag} from "../../Logic/Tags/TagUtils" +import {And} from "../../Logic/Tags/And" +import {Utils} from "../../Utils" +import {Tag} from "../../Logic/Tags/Tag" import BaseUIElement from "../../UI/BaseUIElement" import Combine from "../../UI/Base/Combine" import Title from "../../UI/Base/Title" import Link from "../../UI/Base/Link" import List from "../../UI/Base/List" -import { - MappingConfigJson, - QuestionableTagRenderingConfigJson, -} from "./Json/QuestionableTagRenderingConfigJson" -import { FixedUiElement } from "../../UI/Base/FixedUiElement" -import { Paragraph } from "../../UI/Base/Paragraph" +import {MappingConfigJson, QuestionableTagRenderingConfigJson,} from "./Json/QuestionableTagRenderingConfigJson" +import {FixedUiElement} from "../../UI/Base/FixedUiElement" +import {Paragraph} from "../../UI/Base/Paragraph" import Svg from "../../Svg" +import Validators, {ValidatorType} from "../../UI/InputElement/Validators"; export interface Mapping { readonly if: UploadableTag @@ -44,11 +41,14 @@ export interface Mapping { */ export default class TagRenderingConfig { public readonly id: string - public readonly group: string public readonly render?: TypedTranslation public readonly question?: TypedTranslation public readonly questionhint?: TypedTranslation public readonly condition?: TagsFilter + /** + * Evaluated against the current 'usersettings'-state + */ + public readonly metacondition?: TagsFilter public readonly description?: Translation public readonly configuration_warnings: string[] = [] @@ -67,20 +67,12 @@ export default class TagRenderingConfig { public readonly mappings?: Mapping[] public readonly labels: string[] + public readonly classes: string[] constructor(json: string | QuestionableTagRenderingConfigJson, context?: string) { if (json === undefined) { throw "Initing a TagRenderingConfig with undefined in " + context } - if (json === "questions") { - // Very special value - this.render = null - this.question = null - this.condition = null - this.id = "questions" - this.group = "" - return - } if (typeof json === "number") { json = "" + json @@ -116,13 +108,21 @@ export default class TagRenderingConfig { ) } - this.group = json.group ?? "" this.labels = json.labels ?? [] - this.render = Translations.T(json.render, translationKey + ".render") + if (typeof json.classes === "string") { + this.classes = json.classes.split(" ") + } else { + this.classes = json.classes ?? [] + } + this.render = Translations.T(json.render, translationKey + ".render") this.question = Translations.T(json.question, translationKey + ".question") this.questionhint = Translations.T(json.questionHint, translationKey + ".questionHint") this.description = Translations.T(json.description, translationKey + ".description") - this.condition = TagUtils.Tag(json.condition ?? { and: [] }, `${context}.condition`) + this.condition = TagUtils.Tag(json.condition ?? {and: []}, `${context}.condition`) + this.metacondition = TagUtils.Tag( + json.metacondition ?? {and: []}, + `${context}.metacondition` + ) if (json.freeform) { if ( json.freeform.addExtraTags !== undefined && @@ -132,17 +132,6 @@ export default class TagRenderingConfig { } const type = json.freeform.type ?? "string" - if (ValidatedTextField.AvailableTypes().indexOf(type) < 0) { - throw ( - "At " + - context + - ".freeform.type is an unknown type: " + - type + - "; try one of " + - ValidatedTextField.AvailableTypes().join(", ") - ) - } - let placeholder: Translation = Translations.T(json.freeform.placeholder) if (placeholder === undefined) { const typeDescription = Translations.t.validation[type]?.description @@ -182,13 +171,7 @@ export default class TagRenderingConfig { } } - if ( - this.freeform.type !== undefined && - ValidatedTextField.AvailableTypes().indexOf(this.freeform.type) < 0 - ) { - const knownKeys = ValidatedTextField.AvailableTypes().join(", ") - throw `Freeform.key ${this.freeform.key} is an invalid type. Known keys are ${knownKeys}` - } + // freeform.type is validated in Validation.ts so that we don't need ValidatedTextFields here if (this.freeform.addExtraTags) { const usedKeys = new And(this.freeform.addExtraTags).usedKeys() if (usedKeys.indexOf(this.freeform.key) >= 0) { @@ -224,19 +207,6 @@ export default class TagRenderingConfig { throw `${context}: A question is defined, but no mappings nor freeform (key) are. The question is ${this.question.txt} at ${context}` } - if (this.id === "questions" && this.render !== undefined) { - for (const ln in this.render.translations) { - const txt: string = this.render.translations[ln] - if (txt.indexOf("{questions}") >= 0) { - continue - } - throw `${context}: The rendering for language ${ln} does not contain {questions}. This is a bug, as this rendering should include exactly this to trigger those questions to be shown!` - } - if (this.freeform?.key !== undefined && this.freeform?.key !== "questions") { - throw `${context}: If the ID is questions to trigger a question box, the only valid freeform value is 'questions' as well. Set freeform to questions or remove the freeform all together` - } - } - if (this.freeform) { if (this.render === undefined) { throw `${context}: Detected a freeform key without rendering... Key: ${this.freeform.key} in ${context}` @@ -405,10 +375,11 @@ export default class TagRenderingConfig { let iconClass = commonSize if (mapping.icon !== undefined) { if (typeof mapping.icon === "string" && mapping.icon !== "") { - if ( - Svg.All[mapping.icon] !== undefined || - Svg.All[mapping.icon + ".svg"] !== undefined - ) { + let stripped = mapping.icon + if (stripped.endsWith(".svg")) { + stripped = stripped.substring(0, stripped.length - 4) + } + if (Svg.All[stripped + ".svg"] !== undefined) { icon = "./assets/svg/" + mapping.icon if (!icon.endsWith(".svg")) { icon += ".svg" @@ -534,15 +505,11 @@ export default class TagRenderingConfig { }) } } - return applicableMappings } - public GetRenderValue( - tags: any, - defltValue: any = undefined - ): TypedTranslation | undefined { - return this.GetRenderValueWithImage(tags, defltValue)?.then + public GetRenderValue(tags: Record): TypedTranslation | undefined { + return this.GetRenderValueWithImage(tags)?.then } /** @@ -551,8 +518,7 @@ export default class TagRenderingConfig { * @constructor */ public GetRenderValueWithImage( - tags: any, - defltValue: any = undefined + tags: Record ): { then: TypedTranslation; icon?: string } | undefined { if (this.condition !== undefined) { if (!this.condition.matchesProperties(tags)) { @@ -572,14 +538,13 @@ export default class TagRenderingConfig { } if ( - this.id === "questions" || this.freeform?.key === undefined || tags[this.freeform.key] !== undefined ) { - return { then: this.render } + return {then: this.render} } - return { then: defltValue } + return undefined } /** @@ -650,6 +615,105 @@ export default class TagRenderingConfig { } } + /** + * Given a value for the freeform key and an overview of the selected mappings, construct the correct tagsFilter to apply + * + * @param freeformValue The freeform value which will be applied as 'freeform.key'. Ignored if 'freeform.key' is not set + * + * @param singleSelectedMapping (Only used if multiAnswer == false): the single mapping to apply. Use (mappings.length) for the freeform + * @param multiSelectedMapping (Only used if multiAnswer == true): all the mappings that must be applied. Set multiSelectedMapping[mappings.length] to use the freeform as well + * @param currentProperties: The current properties of the object for which the question should be answered + */ + public constructChangeSpecification( + freeformValue: string | undefined, + singleSelectedMapping: number, + multiSelectedMapping: boolean[] | undefined, + currentProperties: Record + ): UploadableTag { + freeformValue = freeformValue?.trim() + const validator = Validators.get(this.freeform?.type) + if (validator && freeformValue) { + freeformValue = validator.reformat(freeformValue, () => currentProperties["_country"]) + } + if (freeformValue === "") { + freeformValue = undefined + } + if ( + freeformValue === undefined && + singleSelectedMapping === undefined && + multiSelectedMapping === undefined + ) { + return undefined + } + + if (this.mappings === undefined && freeformValue === undefined) { + return undefined + } + if ( + this.freeform !== undefined && + (this.mappings === undefined || + this.mappings.length == 0 || + (singleSelectedMapping === this.mappings.length && !this.multiAnswer)) + ) { + // Either no mappings, or this is a radio-button selected freeform value + return new And([ + new Tag(this.freeform.key, freeformValue), + ...(this.freeform.addExtraTags ?? []), + ]) + } + + if (this.multiAnswer) { + let selectedMappings: UploadableTag[] = this.mappings + .filter((_, i) => multiSelectedMapping[i]) + .map((m) => new And([m.if, ...(m.addExtraTags ?? [])])) + + let unselectedMappings: UploadableTag[] = this.mappings + .filter((_, i) => !multiSelectedMapping[i]) + .map((m) => m.ifnot) + + if (multiSelectedMapping.at(-1) && this.freeform) { + // The freeform value was selected as well + selectedMappings.push( + new And([ + new Tag(this.freeform.key, freeformValue), + ...(this.freeform.addExtraTags ?? []), + ]) + ) + } + return TagUtils.FlattenMultiAnswer([...selectedMappings, ...unselectedMappings]) + } else { + // Is at least one mapping shown in the answer? + const someMappingIsShown = this.mappings.some(m => { + if (typeof m.hideInAnswer === "boolean") { + return !m.hideInAnswer + } + const isHidden = m.hideInAnswer.matchesProperties(currentProperties) + return !isHidden + }) + // If all mappings are hidden for the current tags, we can safely assume that we should use the freeform key + const useFreeform = freeformValue !== undefined && (singleSelectedMapping === this.mappings.length || !someMappingIsShown) + if (useFreeform) { + return new And([ + new Tag(this.freeform.key, freeformValue), + ...(this.freeform.addExtraTags ?? []), + ]) + } else if (singleSelectedMapping !== undefined) { + return new And([ + this.mappings[singleSelectedMapping].if, + ...(this.mappings[singleSelectedMapping].addExtraTags ?? []), + ]) + } else { + console.warn("TagRenderingConfig.ConstructSpecification has a weird fallback for", { + freeformValue, + singleSelectedMapping, + multiSelectedMapping, + currentProperties + }) + return undefined + } + } + } + GenerateDocumentation(): BaseUIElement { let withRender: (BaseUIElement | string)[] = [] if (this.freeform?.key !== undefined) { @@ -689,7 +753,7 @@ export default class TagRenderingConfig { if (m.ifnot !== undefined) { msgs.push( "Unselecting this answer will add " + - m.ifnot.asHumanString(true, false, {}) + m.ifnot.asHumanString(true, false, {}) ) } return msgs @@ -706,13 +770,6 @@ export default class TagRenderingConfig { ]) } - let group: BaseUIElement = undefined - if (this.group !== undefined && this.group !== "") { - group = new Combine([ - "This tagrendering is part of group ", - new FixedUiElement(this.group).SetClass("code"), - ]) - } let labels: BaseUIElement = undefined if (this.labels?.length > 0) { labels = new Combine([ @@ -726,16 +783,15 @@ export default class TagRenderingConfig { this.description, this.question !== undefined ? new Combine([ - "The question is ", - new FixedUiElement(this.question.txt).SetClass("font-bold bold"), - ]) + "The question is ", + new FixedUiElement(this.question.txt).SetClass("font-bold bold"), + ]) : new FixedUiElement( - "This tagrendering has no question and is thus read-only" - ).SetClass("italic"), + "This tagrendering has no question and is thus read-only" + ).SetClass("italic"), new Combine(withRender), mappings, condition, - group, labels, ]).SetClass("flex flex-col") } diff --git a/Models/ThemeConfig/TilesourceConfig.ts b/Models/ThemeConfig/TilesourceConfig.ts deleted file mode 100644 index 4cfca68be..000000000 --- a/Models/ThemeConfig/TilesourceConfig.ts +++ /dev/null @@ -1,43 +0,0 @@ -import TilesourceConfigJson from "./Json/TilesourceConfigJson" -import Translations from "../../UI/i18n/Translations" -import { Translation } from "../../UI/i18n/Translation" - -export default class TilesourceConfig { - public readonly source: string - public readonly id: string - public readonly isOverlay: boolean - public readonly name: Translation - public readonly minzoom: number - public readonly maxzoom: number - public readonly defaultState: boolean - - constructor(config: TilesourceConfigJson, ctx: string = "") { - this.id = config.id - this.source = config.source - this.isOverlay = config.isOverlay ?? false - this.name = Translations.T(config.name) - this.minzoom = config.minZoom ?? 0 - this.maxzoom = config.maxZoom ?? 999 - this.defaultState = config.defaultState ?? true - if (this.id === undefined) { - throw "An id is obligated" - } - if (this.minzoom > this.maxzoom) { - throw ( - "Invalid tilesourceConfig: minzoom should be smaller then maxzoom (at " + ctx + ")" - ) - } - if (this.minzoom < 0) { - throw "minzoom should be > 0 (at " + ctx + ")" - } - if (this.maxzoom < 0) { - throw "maxzoom should be > 0 (at " + ctx + ")" - } - if (this.source.indexOf("{zoom}") >= 0) { - throw "Invalid source url: use {z} instead of {zoom} (at " + ctx + ".source)" - } - if (!this.defaultState && config.name === undefined) { - throw "Disabling an overlay without a name is not possible" - } - } -} diff --git a/Models/ThemeConfig/WithContextLoader.ts b/Models/ThemeConfig/WithContextLoader.ts index ad481a57f..8d480fb80 100644 --- a/Models/ThemeConfig/WithContextLoader.ts +++ b/Models/ThemeConfig/WithContextLoader.ts @@ -15,13 +15,13 @@ export default class WithContextLoader { * * The found value is interpreted as a tagrendering and fetched/parsed * */ - public tr(key: string, deflt) { + public tr(key: string, deflt?: string, translationContext?: string) { const v = this._json[key] if (v === undefined || v === null) { if (deflt === undefined) { return undefined } - return new TagRenderingConfig(deflt, `${this._context}.${key}.default value`) + return new TagRenderingConfig(deflt, `${translationContext ?? this._context}.${key}.default value`) } if (typeof v === "string") { const shared = SharedTagRenderings.SharedTagRendering.get(v) @@ -29,7 +29,7 @@ export default class WithContextLoader { return shared } } - return new TagRenderingConfig(v, `${this._context}.${key}`) + return new TagRenderingConfig(v, `${translationContext ?? this._context}.${key}`) } /** diff --git a/Models/ThemeViewState.ts b/Models/ThemeViewState.ts new file mode 100644 index 000000000..ffdcdaad6 --- /dev/null +++ b/Models/ThemeViewState.ts @@ -0,0 +1,556 @@ +import LayoutConfig from "./ThemeConfig/LayoutConfig" +import {SpecialVisualizationState} from "../UI/SpecialVisualization" +import {Changes} from "../Logic/Osm/Changes" +import {ImmutableStore, Store, UIEventSource} from "../Logic/UIEventSource" +import {FeatureSource, IndexedFeatureSource, WritableFeatureSource,} from "../Logic/FeatureSource/FeatureSource" +import {OsmConnection} from "../Logic/Osm/OsmConnection" +import {ExportableMap, MapProperties} from "./MapProperties" +import LayerState from "../Logic/State/LayerState" +import {Feature, Point, Polygon} from "geojson" +import FullNodeDatabaseSource from "../Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource" +import {Map as MlMap} from "maplibre-gl" +import InitialMapPositioning from "../Logic/Actors/InitialMapPositioning" +import {MapLibreAdaptor} from "../UI/Map/MapLibreAdaptor" +import {GeoLocationState} from "../Logic/State/GeoLocationState" +import FeatureSwitchState from "../Logic/State/FeatureSwitchState" +import {QueryParameters} from "../Logic/Web/QueryParameters" +import UserRelatedState from "../Logic/State/UserRelatedState" +import LayerConfig from "./ThemeConfig/LayerConfig" +import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler" +import {AvailableRasterLayers, RasterLayerPolygon, RasterLayerUtils} from "./RasterLayers" +import LayoutSource from "../Logic/FeatureSource/Sources/LayoutSource" +import StaticFeatureSource from "../Logic/FeatureSource/Sources/StaticFeatureSource" +import FeaturePropertiesStore from "../Logic/FeatureSource/Actors/FeaturePropertiesStore" +import PerLayerFeatureSourceSplitter from "../Logic/FeatureSource/PerLayerFeatureSourceSplitter" +import FilteringFeatureSource from "../Logic/FeatureSource/Sources/FilteringFeatureSource" +import ShowDataLayer from "../UI/Map/ShowDataLayer" +import TitleHandler from "../Logic/Actors/TitleHandler" +import ChangeToElementsActor from "../Logic/Actors/ChangeToElementsActor" +import PendingChangesUploader from "../Logic/Actors/PendingChangesUploader" +import SelectedElementTagsUpdater from "../Logic/Actors/SelectedElementTagsUpdater" +import {BBox} from "../Logic/BBox" +import Constants from "./Constants" +import Hotkeys from "../UI/Base/Hotkeys" +import Translations from "../UI/i18n/Translations" +import {GeoIndexedStoreForLayer} from "../Logic/FeatureSource/Actors/GeoIndexedStore" +import {LastClickFeatureSource} from "../Logic/FeatureSource/Sources/LastClickFeatureSource" +import {MenuState} from "./MenuState" +import MetaTagging from "../Logic/MetaTagging" +import ChangeGeometryApplicator from "../Logic/FeatureSource/Sources/ChangeGeometryApplicator" +import {NewGeometryFromChangesFeatureSource} from "../Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource" +import OsmObjectDownloader from "../Logic/Osm/OsmObjectDownloader" +import ShowOverlayRasterLayer from "../UI/Map/ShowOverlayRasterLayer" +import {Utils} from "../Utils" +import {EliCategory} from "./RasterLayerProperties" +import BackgroundLayerResetter from "../Logic/Actors/BackgroundLayerResetter" +import SaveFeatureSourceToLocalStorage from "../Logic/FeatureSource/Actors/SaveFeatureSourceToLocalStorage" +import BBoxFeatureSource from "../Logic/FeatureSource/Sources/TouchesBboxFeatureSource" +import ThemeViewStateHashActor from "../Logic/Web/ThemeViewStateHashActor"; + +/** + * + * The themeviewState contains all the state needed for the themeViewGUI. + * + * This is pretty much the 'brain' or the HQ of MapComplete + * + * It ties up all the needed elements and starts some actors. + */ +export default class ThemeViewState implements SpecialVisualizationState { + readonly layout: LayoutConfig + readonly map: UIEventSource + readonly changes: Changes + readonly featureSwitches: FeatureSwitchState + readonly featureSwitchIsTesting: Store + readonly featureSwitchUserbadge: Store + + readonly featureProperties: FeaturePropertiesStore + + readonly osmConnection: OsmConnection + readonly selectedElement: UIEventSource + readonly mapProperties: MapProperties & ExportableMap + readonly osmObjectDownloader: OsmObjectDownloader + + readonly dataIsLoading: Store + readonly guistate: MenuState + readonly fullNodeDatabase?: FullNodeDatabaseSource // TODO + + readonly historicalUserLocations: WritableFeatureSource> + readonly indexedFeatures: IndexedFeatureSource & LayoutSource + readonly currentView: FeatureSource> + readonly featuresInView: FeatureSource + readonly newFeatures: WritableFeatureSource + readonly layerState: LayerState + readonly perLayer: ReadonlyMap + readonly availableLayers: Store + readonly selectedLayer: UIEventSource + readonly userRelatedState: UserRelatedState + readonly geolocation: GeoLocationHandler + + readonly lastClickObject: WritableFeatureSource + readonly overlayLayerStates: ReadonlyMap< + string, + { readonly isDisplayed: UIEventSource } + > + /** + * All 'level'-tags that are available with the current features + */ + readonly floors: Store + + constructor(layout: LayoutConfig) { + this.layout = layout + this.guistate = new MenuState(layout.id) + this.map = new UIEventSource(undefined) + const initial = new InitialMapPositioning(layout) + this.mapProperties = new MapLibreAdaptor(this.map, initial) + const geolocationState = new GeoLocationState() + + this.featureSwitches = new FeatureSwitchState(layout) + this.featureSwitchIsTesting = this.featureSwitches.featureSwitchIsTesting + this.featureSwitchUserbadge = this.featureSwitches.featureSwitchUserbadge + + this.osmConnection = new OsmConnection({ + dryRun: this.featureSwitches.featureSwitchIsTesting, + fakeUser: this.featureSwitches.featureSwitchFakeUser.data, + oauth_token: QueryParameters.GetQueryParameter( + "oauth_token", + undefined, + "Used to complete the login" + ), + osmConfiguration: <"osm" | "osm-test">this.featureSwitches.featureSwitchApiURL.data, + }) + this.userRelatedState = new UserRelatedState( + this.osmConnection, + layout?.language, + layout, + this.featureSwitches + ) + this.selectedElement = new UIEventSource(undefined, "Selected element") + this.selectedLayer = new UIEventSource(undefined, "Selected layer") + this.geolocation = new GeoLocationHandler( + geolocationState, + this.selectedElement, + this.mapProperties, + this.userRelatedState.gpsLocationHistoryRetentionTime + ) + + this.availableLayers = AvailableRasterLayers.layersAvailableAt(this.mapProperties.location) + + const self = this + this.layerState = new LayerState(this.osmConnection, layout.layers, layout.id) + + { + const overlayLayerStates = new Map }>() + for (const rasterInfo of this.layout.tileLayerSources) { + const isDisplayed = QueryParameters.GetBooleanQueryParameter( + "overlay-" + rasterInfo.id, + rasterInfo.defaultState ?? true, + "Wether or not overlayer layer " + rasterInfo.id + " is shown" + ) + const state = {isDisplayed} + overlayLayerStates.set(rasterInfo.id, state) + new ShowOverlayRasterLayer(rasterInfo, this.map, this.mapProperties, state) + } + this.overlayLayerStates = overlayLayerStates + } + + { + /* Setup the layout source + * A bit tricky, as this is heavily intertwined with the 'changes'-element, which generate a stream of new and changed features too + */ + + + if (this.layout.layers.some(l => l._needsFullNodeDatabase)) { + this.fullNodeDatabase = new FullNodeDatabaseSource() + } + + const layoutSource = new LayoutSource( + layout.layers, + this.featureSwitches, + this.mapProperties, + this.osmConnection.Backend(), + (id) => self.layerState.filteredLayers.get(id).isDisplayed, + this.fullNodeDatabase + ) + this.indexedFeatures = layoutSource + const empty = [] + let currentViewIndex = 0 + this.currentView = new StaticFeatureSource( + this.mapProperties.bounds.map((bbox) => { + if (!bbox) { + return empty + } + currentViewIndex++ + return [bbox.asGeoJson({ + zoom: this.mapProperties.zoom.data, + ...this.mapProperties.location.data, + id: "current_view" + } + )]; + } + ) + ) + this.featuresInView = new BBoxFeatureSource(layoutSource, this.mapProperties.bounds) + this.dataIsLoading = layoutSource.isLoading + + const indexedElements = this.indexedFeatures + this.featureProperties = new FeaturePropertiesStore(indexedElements) + this.changes = new Changes( + { + dryRun: this.featureSwitches.featureSwitchIsTesting, + allElements: indexedElements, + featurePropertiesStore: this.featureProperties, + osmConnection: this.osmConnection, + historicalUserLocations: this.geolocation.historicalUserLocations, + }, + layout?.isLeftRightSensitive() ?? false + ) + this.historicalUserLocations = this.geolocation.historicalUserLocations + this.newFeatures = new NewGeometryFromChangesFeatureSource( + this.changes, + indexedElements, + this.osmConnection.Backend() + ) + layoutSource.addSource(this.newFeatures) + + const perLayer = new PerLayerFeatureSourceSplitter( + Array.from(this.layerState.filteredLayers.values()).filter( + (l) => l.layerDef?.source !== null + ), + new ChangeGeometryApplicator(this.indexedFeatures, this.changes), + { + constructStore: (features, layer) => + new GeoIndexedStoreForLayer(features, layer), + handleLeftovers: (features) => { + console.warn( + "Got ", + features.length, + "leftover features, such as", + features[0].properties + ) + }, + } + ) + this.perLayer = perLayer.perLayer + } + this.perLayer.forEach((fs) => { + new SaveFeatureSourceToLocalStorage( + this.osmConnection.Backend(), + fs.layer.layerDef.id, + 15, + fs, + this.featureProperties, + fs.layer.layerDef.maxAgeOfCache + ) + }) + + this.floors = this.featuresInView.features.stabilized(500).map((features) => { + if (!features) { + return [] + } + const floors = new Set() + for (const feature of features) { + const level = feature.properties["level"] + if (level) { + const levels = level.split(";") + for (const l of levels) { + floors.add(l) + } + } else { + floors.add("0") // '0' is the default and is thus _always_ present + } + } + const sorted = Array.from(floors) + // Sort alphabetically first, to deal with floor "A", "B" and "C" + sorted.sort() + sorted.sort((a, b) => { + // We use the laxer 'parseInt' to deal with floor '1A' + const na = parseInt(a) + const nb = parseInt(b) + if (isNaN(na) || isNaN(nb)) { + return 0 + } + return na - nb + }) + sorted.reverse(/* new list, no side-effects */) + return sorted + }) + + const lastClick = (this.lastClickObject = new LastClickFeatureSource( + this.mapProperties.lastClickLocation, + this.layout + )) + + this.osmObjectDownloader = new OsmObjectDownloader( + this.osmConnection.Backend(), + this.changes + ) + + this.showNormalDataOn(this.map) + this.initActors() + this.addLastClick(lastClick) + this.drawSpecialLayers() + this.initHotkeys() + this.miscSetup() + if (!Utils.runningFromConsole) { + console.log("State setup completed", this) + } + } + + public showNormalDataOn(map: Store) { + this.perLayer.forEach((fs) => { + const doShowLayer = this.mapProperties.zoom.map( + (z) => + (fs.layer.isDisplayed?.data ?? true) && z >= (fs.layer.layerDef?.minzoom ?? 0), + [fs.layer.isDisplayed] + ) + + if ( + !doShowLayer.data && + (this.featureSwitches.featureSwitchFilter.data === false || !fs.layer.layerDef.name) + ) { + /* This layer is hidden and there is no way to enable it (filterview is disabled or this layer doesn't show up in the filter view as the name is not defined) + * + * This means that we don't have to filter it, nor do we have to display it + * */ + return + } + const filtered = new FilteringFeatureSource( + fs.layer, + fs, + (id) => this.featureProperties.getStore(id), + this.layerState.globalFilters + ) + + new ShowDataLayer(map, { + layer: fs.layer.layerDef, + features: filtered, + doShowLayer, + selectedElement: this.selectedElement, + selectedLayer: this.selectedLayer, + fetchStore: (id) => this.featureProperties.getStore(id), + }) + }) + } + + /** + * Various small methods that need to be called + */ + private miscSetup() { + this.userRelatedState.markLayoutAsVisited(this.layout) + + this.selectedElement.addCallbackAndRunD((feature) => { + // As soon as we have a selected element, we clear the selected element + // This is to work around maplibre, which'll _first_ register the click on the map and only _then_ on the feature + // The only exception is if the last element is the 'add_new'-button, as we don't want it to disappear + if (feature.properties.id === "last_click") { + return + } + this.lastClickObject.features.setData([]) + }) + + if (this.layout.customCss !== undefined && window.location.pathname.indexOf("theme") >= 0) { + Utils.LoadCustomCss(this.layout.customCss) + } + } + + private initHotkeys() { + Hotkeys.RegisterHotkey( + {nomod: "Escape", onUp: true}, + Translations.t.hotkeyDocumentation.closeSidebar, + () => { + this.selectedElement.setData(undefined) + this.guistate.closeAll() + } + ) + + Hotkeys.RegisterHotkey( + { + nomod: "b", + }, + Translations.t.hotkeyDocumentation.openLayersPanel, + () => { + if (this.featureSwitches.featureSwitchFilter.data) { + this.guistate.openFilterView() + } + } + ) + + Hotkeys.RegisterHotkey( + {shift: "O"}, + Translations.t.hotkeyDocumentation.selectMapnik, + () => { + this.mapProperties.rasterLayer.setData(AvailableRasterLayers.osmCarto) + } + ) + const setLayerCategory = (category: EliCategory) => { + const available = this.availableLayers.data + const current = this.mapProperties.rasterLayer + const best = RasterLayerUtils.SelectBestLayerAccordingTo( + available, + category, + current.data + ) + console.log("Best layer for category", category, "is", best.properties.id) + current.setData(best) + } + + Hotkeys.RegisterHotkey( + {nomod: "O"}, + Translations.t.hotkeyDocumentation.selectOsmbasedmap, + () => setLayerCategory("osmbasedmap") + ) + + Hotkeys.RegisterHotkey({nomod: "M"}, Translations.t.hotkeyDocumentation.selectMap, () => + setLayerCategory("map") + ) + + Hotkeys.RegisterHotkey( + {nomod: "P"}, + Translations.t.hotkeyDocumentation.selectAerial, + () => setLayerCategory("photo") + ) + } + + private addLastClick(last_click: LastClickFeatureSource) { + // The last_click gets a _very_ special treatment as it interacts with various parts + + const last_click_layer = this.layerState.filteredLayers.get("last_click") + this.featureProperties.trackFeatureSource(last_click) + this.indexedFeatures.addSource(last_click) + + last_click.features.addCallbackAndRunD((features) => { + if (this.selectedLayer.data?.id === "last_click") { + // The last-click location moved, but we have selected the last click of the previous location + // So, we update _after_ clearing the selection to make sure no stray data is sticking around + this.selectedElement.setData(undefined) + this.selectedElement.setData(features[0]) + } + }) + + new ShowDataLayer(this.map, { + features: new FilteringFeatureSource(last_click_layer, last_click), + doShowLayer: new ImmutableStore(true), + layer: last_click_layer.layerDef, + selectedElement: this.selectedElement, + selectedLayer: this.selectedLayer, + onClick: (feature: Feature) => { + if (this.mapProperties.zoom.data < Constants.minZoomLevelToAddNewPoint) { + this.map.data.flyTo({ + zoom: Constants.minZoomLevelToAddNewPoint, + center: this.mapProperties.lastClickLocation.data, + }) + return + } + // We first clear the selection to make sure no weird state is around + this.selectedLayer.setData(undefined) + this.selectedElement.setData(undefined) + + this.selectedElement.setData(feature) + this.selectedLayer.setData(last_click_layer.layerDef) + }, + }) + } + + /** + * Add the special layers to the map + */ + private drawSpecialLayers() { + type AddedByDefaultTypes = typeof Constants.added_by_default[number] + const empty = [] + /** + * A listing which maps the layerId onto the featureSource + */ + const specialLayers: Record< + Exclude | "current_view", + FeatureSource + > = { + home_location: this.userRelatedState.homeLocation, + gps_location: this.geolocation.currentUserLocation, + gps_location_history: this.geolocation.historicalUserLocations, + gps_track: this.geolocation.historicalUserLocationsTrack, + selected_element: new StaticFeatureSource( + this.selectedElement.map((f) => (f === undefined ? empty : [f])) + ), + range: new StaticFeatureSource( + this.mapProperties.maxbounds.map((bbox) => + bbox === undefined ? empty : [bbox.asGeoJson({id: "range"})] + ) + ), + current_view: this.currentView + } + if (this.layout?.lockLocation) { + const bbox = new BBox(this.layout.lockLocation) + this.mapProperties.maxbounds.setData(bbox) + ShowDataLayer.showRange( + this.map, + new StaticFeatureSource([bbox.asGeoJson({})]), + this.featureSwitches.featureSwitchIsTesting + ) + } + const currentViewLayer = this.layout.layers.find(l => l.id === "current_view") + if (currentViewLayer?.tagRenderings?.length > 0) { + const params = MetaTagging.createExtraFuncParams(this) + this.featureProperties.trackFeatureSource(specialLayers.current_view) + specialLayers.current_view.features.addCallbackAndRunD(features => { + MetaTagging.addMetatags(features, params, currentViewLayer, this.layout, this.osmObjectDownloader, this.featureProperties) + }) + } + + this.layerState.filteredLayers + .get("range") + ?.isDisplayed?.syncWith(this.featureSwitches.featureSwitchIsTesting, true) + + this.layerState.filteredLayers.forEach((flayer) => { + const id = flayer.layerDef.id + const features: FeatureSource = specialLayers[id] + if (features === undefined) { + return + } + + this.featureProperties.trackFeatureSource(features) + // this.indexedFeatures.addSource(features) + new ShowDataLayer(this.map, { + features, + doShowLayer: flayer.isDisplayed, + layer: flayer.layerDef, + selectedElement: this.selectedElement, + selectedLayer: this.selectedLayer, + }) + }) + } + + /** + * Setup various services for which no reference are needed + */ + private initActors() { + { + // Unselect the selected element if it is panned out of view + this.mapProperties.bounds.stabilized(250).addCallbackD((bounds) => { + const selected = this.selectedElement.data + if (selected === undefined) { + return + } + const bbox = BBox.get(selected) + if (!bbox.overlapsWith(bounds)) { + this.selectedElement.setData(undefined) + } + }) + } + { + this.selectedElement.addCallback(selected => { + if (selected === undefined) { + // We did _unselect_ an item - we always remove the lastclick-object + this.lastClickObject.features.setData([]) + this.selectedLayer.setData(undefined) + } + }) + } + new ThemeViewStateHashActor(this) + new MetaTagging(this) + new TitleHandler(this.selectedElement, this.selectedLayer, this.featureProperties, this) + new ChangeToElementsActor(this.changes, this.featureProperties) + new PendingChangesUploader(this.changes, this.selectedElement) + new SelectedElementTagsUpdater(this) + new BackgroundLayerResetter(this.mapProperties.rasterLayer, this.availableLayers) + } +} diff --git a/Models/TileRange.ts b/Models/TileRange.ts index 2454ed471..6b70c438e 100644 --- a/Models/TileRange.ts +++ b/Models/TileRange.ts @@ -1,3 +1,5 @@ +import { BBox } from "../Logic/BBox" + export interface TileRange { xstart: number ystart: number @@ -82,9 +84,29 @@ export class Tiles { * Return x, y of the tile containing (lat, lon) on the given zoom level */ static embedded_tile(lat: number, lon: number, z: number): { x: number; y: number; z: number } { - return { x: Tiles.lon2tile(lon, z), y: Tiles.lat2tile(lat, z), z: z } + return { x: Tiles.lon2tile(lon, z), y: Tiles.lat2tile(lat, z), z } } + static tileRangeFrom(bbox: BBox, zoomlevel: number) { + return Tiles.TileRangeBetween( + zoomlevel, + bbox.getNorth(), + bbox.getWest(), + bbox.getSouth(), + bbox.getEast() + ) + } + + /** + * Construct a tilerange which (at least) contains the given coordinates. + * This means that the actual iterated area might be a bit bigger then the the passed in coordinates + * @param zoomlevel + * @param lat0 + * @param lon0 + * @param lat1 + * @param lon1 + * @constructor + */ static TileRangeBetween( zoomlevel: number, lat0: number, diff --git a/Models/Unit.ts b/Models/Unit.ts index 74862557f..8b0f9adee 100644 --- a/Models/Unit.ts +++ b/Models/Unit.ts @@ -122,6 +122,10 @@ export class Unit { `${ctx}.units[${i}]` ) ) + + if(json.defaultInput && !applicable.some(denom => denom.canonical.trim() === json.defaultInput)){ + throw `${ctx}: no denomination has the specified default denomination. The default denomination is '${json.defaultInput}', but the available denominations are ${applicable.map(denom => denom.canonical).join(", ")}` + } return new Unit(appliesTo, applicable, json.eraseInvalidValues ?? false) } @@ -199,7 +203,7 @@ export class Unit { ) { continue } - let countries: string | string[] = country() + let countries: string | string[] = country() ?? [] if (typeof countries === "string") { countries = countries.split(",") } diff --git a/State.ts b/State.ts deleted file mode 100644 index 2572dc84a..000000000 --- a/State.ts +++ /dev/null @@ -1,16 +0,0 @@ -import LayoutConfig from "./Models/ThemeConfig/LayoutConfig" -import FeaturePipelineState from "./Logic/State/FeaturePipelineState" - -/** - * Contains the global state: a bunch of UI-event sources - */ - -export default class State extends FeaturePipelineState { - /* The singleton of the global state - */ - public static state: FeaturePipelineState - - constructor(layoutToUse: LayoutConfig) { - super(layoutToUse) - } -} diff --git a/StylesheetTestGui.ts b/StylesheetTestGui.ts new file mode 100644 index 000000000..2ebe1dfbb --- /dev/null +++ b/StylesheetTestGui.ts @@ -0,0 +1,4 @@ +import SvelteUIElement from "./UI/Base/SvelteUIElement"; +import StylesheetTestGui from "./UI/StylesheetTestGui.svelte"; + +new SvelteUIElement(StylesheetTestGui, {}).AttachTo("main") diff --git a/UI/AllTagsPanel.svelte b/UI/AllTagsPanel.svelte deleted file mode 100644 index 4eab95c50..000000000 --- a/UI/AllTagsPanel.svelte +++ /dev/null @@ -1,54 +0,0 @@ - - -
- -
- - diff --git a/UI/AllThemesGui.ts b/UI/AllThemesGui.ts index a56d18de0..722eec27e 100644 --- a/UI/AllThemesGui.ts +++ b/UI/AllThemesGui.ts @@ -4,44 +4,53 @@ import Combine from "./Base/Combine" import MoreScreen from "./BigComponents/MoreScreen" import Translations from "./i18n/Translations" import Constants from "../Models/Constants" -import { Utils } from "../Utils" -import LanguagePicker1 from "./LanguagePicker" +import LanguagePicker from "./LanguagePicker" import IndexText from "./BigComponents/IndexText" -import FeaturedMessage from "./BigComponents/FeaturedMessage" -import { ImportViewerLinks } from "./BigComponents/UserInformation" import { LoginToggle } from "./Popup/LoginButton" +import { ImmutableStore } from "../Logic/UIEventSource" +import { OsmConnection } from "../Logic/Osm/OsmConnection" +import {QueryParameters} from "../Logic/Web/QueryParameters"; +import {OsmConnectionFeatureSwitches} from "../Logic/State/FeatureSwitchState"; export default class AllThemesGui { setup() { try { - const state = new UserRelatedState(undefined) + const featureSwitches = new OsmConnectionFeatureSwitches() + const osmConnection = new OsmConnection({ + fakeUser: featureSwitches.featureSwitchFakeUser.data, + oauth_token: QueryParameters.GetQueryParameter( + "oauth_token", + undefined, + "Used to complete the login" + ), + osmConfiguration: <"osm" | "osm-test">featureSwitches.featureSwitchApiURL.data, + }) + const state = new UserRelatedState(osmConnection) const intro = new Combine([ - new LanguagePicker1(Translations.t.index.title.SupportedLanguages(), "").SetClass( + new LanguagePicker(Translations.t.index.title.SupportedLanguages(), state.language).SetClass( "flex absolute top-2 right-3" ), new IndexText(), ]) new Combine([ intro, - new FeaturedMessage().SetClass("mb-4 block"), new MoreScreen(state, true), - new LoginToggle(undefined, Translations.t.index.logIn, state), - new ImportViewerLinks(state.osmConnection), - Translations.t.general.aboutMapcomplete - .Subs({ osmcha_link: Utils.OsmChaLinkFor(7) }) - .SetClass("link-underline"), - new FixedUiElement("v" + Constants.vNumber), + new LoginToggle(undefined, Translations.t.index.logIn, { + osmConnection, + featureSwitchUserbadge: new ImmutableStore(true), + }).SetClass("flex justify-center w-full"), + Translations.t.general.aboutMapComplete.intro.SetClass("link-underline"), + new FixedUiElement("v" + Constants.vNumber).SetClass("block"), ]) .SetClass("block m-5 lg:w-3/4 lg:ml-40") - .SetStyle("pointer-events: all;") - .AttachTo("top-left") + .AttachTo("main") } catch (e) { console.error(">>>> CRITICAL", e) new FixedUiElement( "Seems like no layers are compiled - check the output of `npm run generate:layeroverview`. Is this visible online? Contact pietervdvn immediately!" ) .SetClass("alert") - .AttachTo("top-left") + .AttachTo("main") } } } diff --git a/UI/AutomatonGui.ts b/UI/AutomatonGui.ts deleted file mode 100644 index 1a8b446a8..000000000 --- a/UI/AutomatonGui.ts +++ /dev/null @@ -1,476 +0,0 @@ -import BaseUIElement from "./BaseUIElement" -import Combine from "./Base/Combine" -import Svg from "../Svg" -import Title from "./Base/Title" -import Toggle from "./Input/Toggle" -import { SubtleButton } from "./Base/SubtleButton" -import LayoutConfig from "../Models/ThemeConfig/LayoutConfig" -import ValidatedTextField from "./Input/ValidatedTextField" -import { Utils } from "../Utils" -import { UIEventSource } from "../Logic/UIEventSource" -import { VariableUiElement } from "./Base/VariableUIElement" -import { FixedUiElement } from "./Base/FixedUiElement" -import { Tiles } from "../Models/TileRange" -import { LocalStorageSource } from "../Logic/Web/LocalStorageSource" -import { DropDown } from "./Input/DropDown" -import { AllKnownLayouts } from "../Customizations/AllKnownLayouts" -import MinimapImplementation from "./Base/MinimapImplementation" -import { OsmConnection } from "../Logic/Osm/OsmConnection" -import { BBox } from "../Logic/BBox" -import MapState from "../Logic/State/MapState" -import FeaturePipeline from "../Logic/FeatureSource/FeaturePipeline" -import LayerConfig from "../Models/ThemeConfig/LayerConfig" -import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig" -import FeatureSource from "../Logic/FeatureSource/FeatureSource" -import List from "./Base/List" -import { QueryParameters } from "../Logic/Web/QueryParameters" -import { SubstitutedTranslation } from "./SubstitutedTranslation" -import { AutoAction } from "./Popup/AutoApplyButton" -import DynamicGeoJsonTileSource from "../Logic/FeatureSource/TiledFeatureSource/DynamicGeoJsonTileSource" -import themeOverview from "../assets/generated/theme_overview.json" - -class AutomationPanel extends Combine { - private static readonly openChangeset = new UIEventSource(undefined) - - constructor( - layoutToUse: LayoutConfig, - indices: number[], - extraCommentText: UIEventSource, - tagRenderingToAutomate: { layer: LayerConfig; tagRendering: TagRenderingConfig } - ) { - const layerId = tagRenderingToAutomate.layer.id - const trId = tagRenderingToAutomate.tagRendering.id - const tileState = LocalStorageSource.GetParsed( - "automation-tile_state-" + layerId + "-" + trId, - {} - ) - const logMessages = new UIEventSource([]) - if (indices === undefined) { - throw "No tiles loaded - can not automate" - } - const openChangeset = AutomationPanel.openChangeset - - openChangeset.addCallbackAndRun((cs) => - console.trace("Sync current open changeset to:", cs) - ) - - const nextTileToHandle = tileState.map((handledTiles) => { - for (const index of indices) { - if (handledTiles[index] !== undefined) { - // Already handled - continue - } - return index - } - return undefined - }) - nextTileToHandle.addCallback((t) => console.warn("Next tile to handle is", t)) - - const neededTimes = new UIEventSource([]) - const automaton = new VariableUiElement( - nextTileToHandle.map((tileIndex) => { - if (tileIndex === undefined) { - return new FixedUiElement("All done!").SetClass("thanks") - } - console.warn("Triggered map on nextTileToHandle", tileIndex) - const start = new Date() - return AutomationPanel.TileHandler( - layoutToUse, - tileIndex, - layerId, - tagRenderingToAutomate.tagRendering, - extraCommentText, - (result, logMessage) => { - const end = new Date() - const timeNeeded = (end.getTime() - start.getTime()) / 1000 - neededTimes.data.push(timeNeeded) - neededTimes.ping() - tileState.data[tileIndex] = result - tileState.ping() - if (logMessage !== undefined) { - logMessages.data.push(logMessage) - logMessages.ping() - } - } - ) - }) - ) - - const statistics = new VariableUiElement( - tileState.map((states) => { - let total = 0 - const perResult = new Map() - for (const key in states) { - total++ - const result = states[key] - perResult.set(result, (perResult.get(result) ?? 0) + 1) - } - - let sum = 0 - neededTimes.data.forEach((v) => { - sum = sum + v - }) - let timePerTile = sum / neededTimes.data.length - - return new Combine([ - "Handled " + total + "/" + indices.length + " tiles: ", - new List( - Array.from(perResult.keys()).map((key) => key + ": " + perResult.get(key)) - ), - "Handling one tile needs " + - Math.floor(timePerTile * 100) / 100 + - "s on average. Estimated time left: " + - Utils.toHumanTime((indices.length - total) * timePerTile), - ]).SetClass("flex flex-col") - }) - ) - - super([ - statistics, - automaton, - new SubtleButton(undefined, "Clear fixed").onClick(() => { - const st = tileState.data - for (const tileIndex in st) { - if (st[tileIndex] === "fixed") { - delete st[tileIndex] - } - } - - tileState.ping() - }), - new VariableUiElement(logMessages.map((logMessages) => new List(logMessages))), - ]) - this.SetClass("flex flex-col") - } - - private static TileHandler( - layoutToUse: LayoutConfig, - tileIndex: number, - targetLayer: string, - targetAction: TagRenderingConfig, - extraCommentText: UIEventSource, - whenDone: (result: string, logMessage?: string) => void - ): BaseUIElement { - const state = new MapState(layoutToUse, { attemptLogin: false }) - extraCommentText.syncWith(state.changes.extraComment) - const [z, x, y] = Tiles.tile_from_index(tileIndex) - state.locationControl.setData({ - zoom: z, - lon: x, - lat: y, - }) - state.currentBounds.setData(BBox.fromTileIndex(tileIndex)) - - let targetTiles: UIEventSource = new UIEventSource([]) - const pipeline = new FeaturePipeline((tile) => { - const layerId = tile.layer.layerDef.id - if (layerId === targetLayer) { - targetTiles.data.push(tile) - targetTiles.ping() - } - }, state) - - state.locationControl.ping() - state.currentBounds.ping() - const stateToShow = new UIEventSource("") - - pipeline.runningQuery.map( - async (isRunning) => { - if (targetTiles.data.length === 0) { - stateToShow.setData("No data loaded yet...") - return - } - if (isRunning) { - stateToShow.setData( - "Waiting for all layers to be loaded... Has " + - targetTiles.data.length + - " tiles already" - ) - return - } - if (targetTiles.data.length === 0) { - stateToShow.setData("No features found to apply the action") - whenDone("empty") - return true - } - stateToShow.setData("Gathering applicable elements") - - let handled = 0 - let inspected = 0 - let log = [] - for (const targetTile of targetTiles.data) { - for (const ffs of targetTile.features.data) { - inspected++ - if (inspected % 10 === 0) { - stateToShow.setData( - "Inspected " + - inspected + - " features, updated " + - handled + - " features" - ) - } - const feature = ffs.feature - const renderingTr = targetAction.GetRenderValue(feature.properties) - const rendering = renderingTr.txt - log.push( - "" + - feature.properties.id + - ": " + - new SubstitutedTranslation( - renderingTr, - new UIEventSource(feature.properties), - undefined - ).ConstructElement().textContent - ) - const actions = Utils.NoNull( - SubstitutedTranslation.ExtractSpecialComponents(rendering).map( - (obj) => obj.special - ) - ) - for (const action of actions) { - const auto = action.func - if (auto.supportsAutoAction !== true) { - continue - } - - await auto.applyActionOn( - { - layoutToUse: state.layoutToUse, - changes: state.changes, - }, - state.allElements.getEventSourceById(feature.properties.id), - action.args - ) - handled++ - } - } - } - stateToShow.setData( - "Done! Inspected " + inspected + " features, updated " + handled + " features" - ) - - if (inspected === 0) { - whenDone("empty") - return true - } - - if (handled === 0) { - whenDone("no-action", "Inspected " + inspected + " elements: " + log.join("; ")) - } else { - state.osmConnection.AttemptLogin() - state.changes.flushChanges("handled tile automatically, time to flush!") - whenDone( - "fixed", - "Updated " + - handled + - " elements, inspected " + - inspected + - ": " + - log.join("; ") - ) - } - return true - }, - [targetTiles] - ) - - return new Combine([ - new Title("Performing action for tile " + tileIndex, 1), - new VariableUiElement(stateToShow), - ]).SetClass("flex flex-col") - } -} - -class AutomatonGui { - constructor() { - const osmConnection = new OsmConnection({ - singlePage: false, - oauth_token: QueryParameters.GetQueryParameter("oauth_token", "OAuth token"), - }) - - new Combine([ - new Combine([ - Svg.robot_svg().SetClass("w-24 h-24 p-4 rounded-full subtle-background"), - new Combine([ - new Title("MapComplete Automaton", 1), - "This page helps to automate certain tasks for a theme. Expert use only.", - ]).SetClass("flex flex-col m-4"), - ]).SetClass("flex"), - new Toggle( - AutomatonGui.GenerateMainPanel(), - new SubtleButton(Svg.osm_logo_svg(), "Login to get started").onClick(() => - osmConnection.AttemptLogin() - ), - osmConnection.isLoggedIn - ), - ]) - .SetClass("block p-4") - .AttachTo("main") - } - - private static GenerateMainPanel(): BaseUIElement { - const themeSelect = new DropDown( - "Select a theme", - Array.from(themeOverview).map((l) => ({ value: l.id, shown: l.id })) - ) - - LocalStorageSource.Get("automation-theme-id", "missing_streets").syncWith( - themeSelect.GetValue() - ) - - const tilepath = ValidatedTextField.ForType("url").ConstructInputElement({ - placeholder: "Specifiy the path of the overview", - inputStyle: "width: 100%", - }) - tilepath.SetClass("w-full") - LocalStorageSource.Get("automation-tile_path").syncWith(tilepath.GetValue(), true) - - let tilesToRunOver = tilepath.GetValue().bind((path) => { - if (path === undefined) { - return undefined - } - return UIEventSource.FromPromiseWithErr(Utils.downloadJsonCached(path, 1000 * 60 * 60)) - }) - - const targetZoom = 14 - - const tilesPerIndex = tilesToRunOver.map((tiles) => { - if (tiles === undefined || tiles["error"] !== undefined) { - return undefined - } - let indexes: number[] = [] - const tilesS = tiles["success"] - DynamicGeoJsonTileSource.RegisterWhitelist(tilepath.GetValue().data, tilesS) - const z = Number(tilesS["zoom"]) - for (const key in tilesS) { - if (key === "zoom") { - continue - } - const x = Number(key) - const ys = tilesS[key] - indexes.push(...ys.map((y) => Tiles.tile_index(z, x, y))) - } - - console.log("Got ", indexes.length, "indexes") - let rezoomed = new Set() - for (const index of indexes) { - let [z, x, y] = Tiles.tile_from_index(index) - while (z > targetZoom) { - z-- - x = Math.floor(x / 2) - y = Math.floor(y / 2) - } - rezoomed.add(Tiles.tile_index(z, x, y)) - } - - return Array.from(rezoomed) - }) - - const extraComment = ValidatedTextField.ForType("text").ConstructInputElement() - LocalStorageSource.Get("automaton-extra-comment").syncWith(extraComment.GetValue()) - - return new Combine([ - themeSelect, - "Specify the path to a tile overview. This is a hosted .json of the format {x : [y0, y1, y2], x1: [y0, ...]} where x is a string and y are numbers", - tilepath, - "Add an extra comment:", - extraComment, - new VariableUiElement( - extraComment - .GetValue() - .map((c) => "Your comment is " + (c?.length ?? 0) + "/200 characters long") - ).SetClass("subtle"), - new VariableUiElement( - tilesToRunOver.map((t) => { - if (t === undefined) { - return "No path given or still loading..." - } - if (t["error"] !== undefined) { - return new FixedUiElement("Invalid URL or data: " + t["error"]).SetClass( - "alert" - ) - } - - return new FixedUiElement( - "Loaded " + tilesPerIndex.data.length + " tiles to automated over" - ).SetClass("thanks") - }) - ), - new VariableUiElement( - themeSelect - .GetValue() - .map((id) => AllKnownLayouts.allKnownLayouts.get(id)) - .map( - (layoutToUse) => { - if (layoutToUse === undefined) { - return new FixedUiElement("Select a valid layout") - } - if ( - tilesPerIndex.data === undefined || - tilesPerIndex.data.length === 0 - ) { - return "No tiles given" - } - - const automatableTagRenderings: { - layer: LayerConfig - tagRendering: TagRenderingConfig - }[] = [] - for (const layer of layoutToUse.layers) { - for (const tagRendering of layer.tagRenderings) { - if (tagRendering.group === "auto") { - automatableTagRenderings.push({ - layer, - tagRendering: tagRendering, - }) - } - } - } - console.log("Automatable tag renderings:", automatableTagRenderings) - if (automatableTagRenderings.length === 0) { - return new FixedUiElement( - 'This theme does not have any tagRendering with "group": "auto" set' - ).SetClass("alert") - } - const pickAuto = new DropDown("Pick the action to automate", [ - { - value: undefined, - shown: "Pick an option", - }, - ...automatableTagRenderings.map((config) => ({ - shown: config.layer.id + " - " + config.tagRendering.id, - value: config, - })), - ]) - - return new Combine([ - pickAuto, - new VariableUiElement( - pickAuto - .GetValue() - .map((auto) => - auto === undefined - ? undefined - : new AutomationPanel( - layoutToUse, - tilesPerIndex.data, - extraComment.GetValue(), - auto - ) - ) - ), - ]) - }, - [tilesPerIndex] - ) - ).SetClass("flex flex-col"), - ]).SetClass("flex flex-col") - } -} - -MinimapImplementation.initialize() - -new AutomatonGui() diff --git a/UI/Base/AsyncLazy.ts b/UI/Base/AsyncLazy.ts index d09c9769f..71c6ab34e 100644 --- a/UI/Base/AsyncLazy.ts +++ b/UI/Base/AsyncLazy.ts @@ -1,6 +1,6 @@ import BaseUIElement from "../BaseUIElement" import { VariableUiElement } from "./VariableUIElement" -import { Stores, UIEventSource } from "../../Logic/UIEventSource" +import { Stores } from "../../Logic/UIEventSource" import Loading from "./Loading" export default class AsyncLazy extends BaseUIElement { diff --git a/UI/Base/BackButton.svelte b/UI/Base/BackButton.svelte new file mode 100644 index 000000000..e39baa243 --- /dev/null +++ b/UI/Base/BackButton.svelte @@ -0,0 +1,17 @@ + + + dispatch("click")} options={{extraClasses:clss+ " flex items-center"}}> + + + diff --git a/UI/Base/Checkbox.svelte b/UI/Base/Checkbox.svelte new file mode 100644 index 000000000..93fec9483 --- /dev/null +++ b/UI/Base/Checkbox.svelte @@ -0,0 +1,13 @@ + + + diff --git a/UI/Base/DivContainer.ts b/UI/Base/DivContainer.ts index bc6c9e68e..f36b041d6 100644 --- a/UI/Base/DivContainer.ts +++ b/UI/Base/DivContainer.ts @@ -1,4 +1,3 @@ -import { UIElement } from "../UIElement" import BaseUIElement from "../BaseUIElement" /** diff --git a/UI/Base/DragInvitation.svelte b/UI/Base/DragInvitation.svelte new file mode 100644 index 000000000..93b1265c4 --- /dev/null +++ b/UI/Base/DragInvitation.svelte @@ -0,0 +1,86 @@ + + + +
+
+ +
+
+ + diff --git a/UI/Base/Dropdown.svelte b/UI/Base/Dropdown.svelte new file mode 100644 index 000000000..2e711d954 --- /dev/null +++ b/UI/Base/Dropdown.svelte @@ -0,0 +1,15 @@ + + + diff --git a/UI/Base/FloatOver.svelte b/UI/Base/FloatOver.svelte new file mode 100644 index 000000000..e7c4a0ca5 --- /dev/null +++ b/UI/Base/FloatOver.svelte @@ -0,0 +1,33 @@ + + +
+
+
+ +
+ + +
dispatch("close")}> + +
+
+
+
+ + + diff --git a/UI/Base/FromHtml.svelte b/UI/Base/FromHtml.svelte new file mode 100644 index 000000000..0f5837629 --- /dev/null +++ b/UI/Base/FromHtml.svelte @@ -0,0 +1,20 @@ + + +{#if src !== undefined} + +{/if} + diff --git a/UI/Base/Hotkeys.ts b/UI/Base/Hotkeys.ts index 243417fdb..6b4f07365 100644 --- a/UI/Base/Hotkeys.ts +++ b/UI/Base/Hotkeys.ts @@ -99,14 +99,23 @@ export default class Hotkeys { } static generateDocumentation(): BaseUIElement { - const byKey: [string, string | Translation][] = Hotkeys._docs.data + let byKey: [string, string | Translation][] = Hotkeys._docs.data .map(({ key, documentation }) => { const modifiers = Object.keys(key).filter((k) => k !== "nomod" && k !== "onUp") - const keycode: string = key["ctrl"] ?? key["shift"] ?? key["alt"] ?? key["nomod"] + let keycode: string = key["ctrl"] ?? key["shift"] ?? key["alt"] ?? key["nomod"] + if (keycode.length == 1) { + keycode = keycode.toUpperCase() + } modifiers.push(keycode) return <[string, string | Translation]>[modifiers.join("+"), documentation] }) .sort() + byKey = Utils.NoNull(byKey) + for (let i = byKey.length - 1; i > 0; i--) { + if (byKey[i - 1][0] === byKey[i][0]) { + byKey.splice(i, 1) + } + } const t = Translations.t.hotkeyDocumentation return new Combine([ new Title(t.title, 1), @@ -114,7 +123,7 @@ export default class Hotkeys { new Table( [t.key, t.action], byKey.map(([key, doc]) => { - return [new FixedUiElement(key).SetClass("code"), doc] + return [new FixedUiElement(key).SetClass("literal-code"), doc] }) ), ]) diff --git a/UI/Base/If.svelte b/UI/Base/If.svelte new file mode 100644 index 000000000..5255b8046 --- /dev/null +++ b/UI/Base/If.svelte @@ -0,0 +1,23 @@ + + +{#if _c} + + {:else} + +{/if} diff --git a/UI/Base/IfHidden.svelte b/UI/Base/IfHidden.svelte new file mode 100644 index 000000000..7f38dd20e --- /dev/null +++ b/UI/Base/IfHidden.svelte @@ -0,0 +1,33 @@ + + +{#if hasBeenShownPositive} + + + +{/if} + +{#if hasBeenShownNegative} + + + +{/if} diff --git a/UI/Base/IfNot.svelte b/UI/Base/IfNot.svelte new file mode 100644 index 000000000..baab7c190 --- /dev/null +++ b/UI/Base/IfNot.svelte @@ -0,0 +1,18 @@ + + +{#if _c} + +{/if} diff --git a/UI/Base/Link.ts b/UI/Base/Link.ts index 76c025dc6..25f107a47 100644 --- a/UI/Base/Link.ts +++ b/UI/Base/Link.ts @@ -1,6 +1,6 @@ import Translations from "../i18n/Translations" import BaseUIElement from "../BaseUIElement" -import { Store, UIEventSource } from "../../Logic/UIEventSource" +import { Store } from "../../Logic/UIEventSource" export default class Link extends BaseUIElement { private readonly _href: string | Store diff --git a/UI/Base/Loading.svelte b/UI/Base/Loading.svelte new file mode 100644 index 000000000..f98d9fe3f --- /dev/null +++ b/UI/Base/Loading.svelte @@ -0,0 +1,13 @@ + + +
+
+ +
+
+ +
+
diff --git a/UI/Base/LoginButton.svelte b/UI/Base/LoginButton.svelte new file mode 100644 index 000000000..2c710c2cf --- /dev/null +++ b/UI/Base/LoginButton.svelte @@ -0,0 +1,17 @@ + + + diff --git a/UI/Base/LoginToggle.svelte b/UI/Base/LoginToggle.svelte new file mode 100644 index 000000000..3f3ab19e5 --- /dev/null +++ b/UI/Base/LoginToggle.svelte @@ -0,0 +1,47 @@ + + +{#if $badge} + {#if !ignoreLoading && $loadingStatus === "loading"} + + + + {:else if $loadingStatus === "error"} +
+ + +
+ + {:else if $loadingStatus === "logged-in"} + + {:else if $loadingStatus === "not-attempted"} + + + + {/if} +{/if} diff --git a/UI/Base/MapControlButton.svelte b/UI/Base/MapControlButton.svelte new file mode 100644 index 000000000..7705b910e --- /dev/null +++ b/UI/Base/MapControlButton.svelte @@ -0,0 +1,14 @@ + + + + diff --git a/UI/Base/Minimap.ts b/UI/Base/Minimap.ts deleted file mode 100644 index 13ac4b5f7..000000000 --- a/UI/Base/Minimap.ts +++ /dev/null @@ -1,47 +0,0 @@ -import BaseUIElement from "../BaseUIElement" -import Loc from "../../Models/Loc" -import BaseLayer from "../../Models/BaseLayer" -import { UIEventSource } from "../../Logic/UIEventSource" -import { BBox } from "../../Logic/BBox" - -export interface MinimapOptions { - background?: UIEventSource - location?: UIEventSource - bounds?: UIEventSource - allowMoving?: boolean - leafletOptions?: any - attribution?: BaseUIElement | boolean - onFullyLoaded?: (leaflet: L.Map) => void - leafletMap?: UIEventSource - lastClickLocation?: UIEventSource<{ lat: number; lon: number }> - addLayerControl?: boolean | false -} - -export interface MinimapObj { - readonly leafletMap: UIEventSource - readonly location: UIEventSource - readonly bounds: UIEventSource - - installBounds(factor: number | BBox, showRange?: boolean): void - - TakeScreenshot(format): Promise - TakeScreenshot(format: "image"): Promise - TakeScreenshot(format: "blob"): Promise - TakeScreenshot(format?: "image" | "blob"): Promise -} - -export default class Minimap { - /** - * A stub implementation. The actual implementation is injected later on, but only in the browser. - * importing leaflet crashes node-ts, which is pretty annoying considering the fact that a lot of scripts use it - */ - - private constructor() {} - - /** - * Construct a minimap - */ - public static createMiniMap: (options?: MinimapOptions) => BaseUIElement & MinimapObj = (_) => { - throw "CreateMinimap hasn't been initialized yet. Please call MinimapImplementation.initialize()" - } -} diff --git a/UI/Base/MinimapImplementation.ts b/UI/Base/MinimapImplementation.ts deleted file mode 100644 index 271bd7253..000000000 --- a/UI/Base/MinimapImplementation.ts +++ /dev/null @@ -1,424 +0,0 @@ -import { Utils } from "../../Utils" -import BaseUIElement from "../BaseUIElement" -import { UIEventSource } from "../../Logic/UIEventSource" -import Loc from "../../Models/Loc" -import BaseLayer from "../../Models/BaseLayer" -import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers" -import * as L from "leaflet" -import { LeafletMouseEvent, Map } from "leaflet" -import Minimap, { MinimapObj, MinimapOptions } from "./Minimap" -import { BBox } from "../../Logic/BBox" -import "leaflet-polylineoffset" -import { SimpleMapScreenshoter } from "leaflet-simple-map-screenshoter" -import BackgroundMapSwitch from "../BigComponents/BackgroundMapSwitch" -import AvailableBaseLayersImplementation from "../../Logic/Actors/AvailableBaseLayersImplementation" -import ShowDataLayer from "../ShowDataLayer/ShowDataLayer" -import ShowDataLayerImplementation from "../ShowDataLayer/ShowDataLayerImplementation" -import FilteredLayer from "../../Models/FilteredLayer" -import ScrollableFullScreen from "./ScrollableFullScreen" -import Constants from "../../Models/Constants" -import StrayClickHandler from "../../Logic/Actors/StrayClickHandler" - -/** - * The stray-click-hanlders adds a marker to the map if no feature was clicked. - * Shows the given uiToShow-element in the messagebox - */ -class StrayClickHandlerImplementation { - private _lastMarker - - constructor( - state: { - LastClickLocation: UIEventSource<{ lat: number; lon: number }> - selectedElement: UIEventSource - filteredLayers: UIEventSource - leafletMap: UIEventSource - }, - uiToShow: ScrollableFullScreen, - iconToShow: BaseUIElement - ) { - const self = this - const leafletMap = state.leafletMap - state.filteredLayers.data.forEach((filteredLayer) => { - filteredLayer.isDisplayed.addCallback((isEnabled) => { - if (isEnabled && self._lastMarker && leafletMap.data !== undefined) { - // When a layer is activated, we remove the 'last click location' in order to force the user to reclick - // This reclick might be at a location where a feature now appeared... - state.leafletMap.data.removeLayer(self._lastMarker) - } - }) - }) - - state.LastClickLocation.addCallback(function (lastClick) { - if (self._lastMarker !== undefined) { - state.leafletMap.data?.removeLayer(self._lastMarker) - } - - if (lastClick === undefined) { - return - } - - state.selectedElement.setData(undefined) - const clickCoor: [number, number] = [lastClick.lat, lastClick.lon] - self._lastMarker = L.marker(clickCoor, { - icon: L.divIcon({ - html: iconToShow.ConstructElement(), - iconSize: [50, 50], - iconAnchor: [25, 50], - popupAnchor: [0, -45], - }), - }) - - self._lastMarker.addTo(leafletMap.data) - - self._lastMarker.on("click", () => { - if (leafletMap.data.getZoom() < Constants.userJourney.minZoomLevelToAddNewPoints) { - leafletMap.data.flyTo( - clickCoor, - Constants.userJourney.minZoomLevelToAddNewPoints - ) - return - } - - uiToShow.Activate() - }) - }) - - state.selectedElement.addCallback(() => { - if (self._lastMarker !== undefined) { - leafletMap.data.removeLayer(self._lastMarker) - this._lastMarker = undefined - } - }) - } -} - -export default class MinimapImplementation extends BaseUIElement implements MinimapObj { - private static _nextId = 0 - public readonly leafletMap: UIEventSource - public readonly location: UIEventSource - public readonly bounds: UIEventSource | undefined - private readonly _id: string - private readonly _background: UIEventSource - private _isInited = false - private _allowMoving: boolean - private readonly _leafletoptions: any - private readonly _onFullyLoaded: (leaflet: L.Map) => void - private readonly _attribution: BaseUIElement | boolean - private readonly _addLayerControl: boolean - private readonly _options: MinimapOptions - - private constructor(options?: MinimapOptions) { - super() - options = options ?? {} - this._id = "minimap" + MinimapImplementation._nextId - MinimapImplementation._nextId++ - this.leafletMap = options.leafletMap ?? new UIEventSource(undefined) - this._background = - options?.background ?? new UIEventSource(AvailableBaseLayers.osmCarto) - this.location = options?.location ?? new UIEventSource({ lat: 0, lon: 0, zoom: 1 }) - this.bounds = options?.bounds - this._allowMoving = options.allowMoving ?? true - this._leafletoptions = options.leafletOptions ?? {} - this._onFullyLoaded = options.onFullyLoaded - this._attribution = options.attribution - this._addLayerControl = options.addLayerControl ?? false - this._options = options - this.SetClass("relative") - } - - public static initialize() { - AvailableBaseLayers.implement(new AvailableBaseLayersImplementation()) - Minimap.createMiniMap = (options) => new MinimapImplementation(options) - ShowDataLayer.actualContstructor = (options) => new ShowDataLayerImplementation(options) - StrayClickHandler.construct = ( - state: { - LastClickLocation: UIEventSource<{ lat: number; lon: number }> - selectedElement: UIEventSource - filteredLayers: UIEventSource - leafletMap: UIEventSource - }, - uiToShow: ScrollableFullScreen, - iconToShow: BaseUIElement - ) => { - return new StrayClickHandlerImplementation(state, uiToShow, iconToShow) - } - } - - public installBounds(factor: number | BBox, showRange?: boolean) { - this.leafletMap.addCallbackD((leaflet) => { - let bounds: { getEast(); getNorth(); getWest(); getSouth() } - if (typeof factor === "number") { - const lbounds = leaflet.getBounds().pad(factor) - leaflet.setMaxBounds(lbounds) - bounds = lbounds - } else { - // @ts-ignore - leaflet.setMaxBounds(factor.toLeaflet()) - bounds = factor - } - - if (showRange) { - const data = { - type: "FeatureCollection", - features: [ - { - type: "Feature", - geometry: { - type: "LineString", - coordinates: [ - [bounds.getEast(), bounds.getNorth()], - [bounds.getWest(), bounds.getNorth()], - [bounds.getWest(), bounds.getSouth()], - - [bounds.getEast(), bounds.getSouth()], - [bounds.getEast(), bounds.getNorth()], - ], - }, - }, - ], - } - // @ts-ignore - L.geoJSON(data, { - style: { - color: "#f44", - weight: 4, - opacity: 0.7, - }, - }).addTo(leaflet) - } - }) - } - - Destroy() { - super.Destroy() - console.warn("Decomissioning minimap", this._id) - const mp = this.leafletMap.data - this.leafletMap.setData(null) - mp.off() - mp.remove() - } - - /** - * Takes a screenshot of the current map - * @param format: image: give a base64 encoded png image; - * @constructor - */ - public async TakeScreenshot(): Promise - public async TakeScreenshot(format: "image"): Promise - public async TakeScreenshot(format: "blob"): Promise - public async TakeScreenshot(format: "image" | "blob"): Promise - public async TakeScreenshot(format: "image" | "blob" = "image"): Promise { - console.log("Taking a screenshot...") - const screenshotter = new SimpleMapScreenshoter() - screenshotter.addTo(this.leafletMap.data) - const result = await screenshotter.takeScreen(format ?? "image") - if (format === "image" && typeof result === "string") { - return result - } - if (format === "blob" && result instanceof Blob) { - return result - } - throw "Something went wrong while creating the screenshot: " + result - } - - protected InnerConstructElement(): HTMLElement { - const div = document.createElement("div") - div.id = this._id - div.style.height = "100%" - div.style.width = "100%" - div.style.minWidth = "40px" - div.style.minHeight = "40px" - div.style.position = "relative" - const wrapper = document.createElement("div") - wrapper.appendChild(div) - const self = this - // @ts-ignore - const resizeObserver = new ResizeObserver((_) => { - if (wrapper.clientHeight === 0 || wrapper.clientWidth === 0) { - return - } - if ( - wrapper.offsetParent === null || - window.getComputedStyle(wrapper).display === "none" - ) { - // Not visible - return - } - try { - self.InitMap() - } catch (e) { - console.debug("Could not construct a minimap:", e) - } - - try { - self.leafletMap?.data?.invalidateSize() - } catch (e) { - console.debug("Could not invalidate size of a minimap:", e) - } - }) - - resizeObserver.observe(div) - - if (this._addLayerControl) { - const switcher = new BackgroundMapSwitch( - { - locationControl: this.location, - backgroundLayer: this._background, - }, - this._background - ).SetClass("top-0 right-0 z-above-map absolute") - wrapper.appendChild(switcher.ConstructElement()) - } - - return wrapper - } - - private InitMap() { - if (this._constructedHtmlElement === undefined) { - // This element isn't initialized yet - return - } - - if (document.getElementById(this._id) === null) { - // not yet attached, we probably got some other event - return - } - - if (this._isInited) { - return - } - this._isInited = true - const location = this.location - const self = this - let currentLayer = this._background.data.layer() - let latLon = <[number, number]>[location.data?.lat ?? 0, location.data?.lon ?? 0] - if (isNaN(latLon[0]) || isNaN(latLon[1])) { - latLon = [0, 0] - } - const options = { - center: latLon, - zoom: location.data?.zoom ?? 2, - layers: [currentLayer], - zoomControl: false, - attributionControl: this._attribution !== undefined, - dragging: this._allowMoving, - scrollWheelZoom: this._allowMoving, - doubleClickZoom: this._allowMoving, - keyboard: this._allowMoving, - touchZoom: this._allowMoving, - // Disabling this breaks the geojson layer - don't ask me why! zoomAnimation: this._allowMoving, - fadeAnimation: this._allowMoving, - maxZoom: 21, - } - - Utils.Merge(this._leafletoptions, options) - /* - * Somehow, the element gets '_leaflet_id' set on chrome. - * When attempting to init this leaflet map, it'll throw an exception and the map won't show up. - * Simply removing '_leaflet_id' fixes the issue. - * See https://github.com/pietervdvn/MapComplete/issues/726 - * */ - delete document.getElementById(this._id)["_leaflet_id"] - - const map = L.map(this._id, options) - if (self._onFullyLoaded !== undefined) { - currentLayer.on("load", () => { - console.log("Fully loaded all tiles!") - self._onFullyLoaded(map) - }) - } - - // Users are not allowed to zoom to the 'copies' on the left and the right, stuff goes wrong then - // We give a bit of leeway for people on the edges - // Also see: https://www.reddit.com/r/openstreetmap/comments/ih4zzc/mapcomplete_a_new_easytouse_editor/g31ubyv/ - - map.setMaxBounds([ - [-100, -200], - [100, 200], - ]) - - if (this._attribution !== undefined) { - if (this._attribution === true) { - map.attributionControl.setPrefix(false) - } else { - map.attributionControl.setPrefix("") - } - } - - this._background.addCallbackAndRun((layer) => { - const newLayer = layer.layer() - if (currentLayer !== undefined) { - map.removeLayer(currentLayer) - } - currentLayer = newLayer - if (self._onFullyLoaded !== undefined) { - currentLayer.on("load", () => { - console.log("Fully loaded all tiles!") - self._onFullyLoaded(map) - }) - } - map.addLayer(newLayer) - if (self._attribution !== true && self._attribution !== false) { - self._attribution?.AttachTo("leaflet-attribution") - } - }) - - let isRecursing = false - map.on("moveend", function () { - if (isRecursing) { - return - } - if ( - map.getZoom() === location.data.zoom && - map.getCenter().lat === location.data.lat && - map.getCenter().lng === location.data.lon - ) { - return - } - location.data.zoom = map.getZoom() - location.data.lat = map.getCenter().lat - location.data.lon = map.getCenter().lng - isRecursing = true - location.ping() - - if (self.bounds !== undefined) { - self.bounds.setData(BBox.fromLeafletBounds(map.getBounds())) - } - - isRecursing = false // This is ugly, I know - }) - - location.addCallback((loc) => { - const mapLoc = map.getCenter() - const dlat = Math.abs(loc.lat - mapLoc[0]) - const dlon = Math.abs(loc.lon - mapLoc[1]) - - if (dlat < 0.000001 && dlon < 0.000001 && map.getZoom() === loc.zoom) { - return - } - map.setView([loc.lat, loc.lon], loc.zoom) - }) - - if (self.bounds !== undefined) { - self.bounds.setData(BBox.fromLeafletBounds(map.getBounds())) - } - - if (this._options.lastClickLocation) { - const lastClickLocation = this._options.lastClickLocation - map.addEventListener("click", function (e: LeafletMouseEvent) { - if (e.originalEvent["dismissed"]) { - return - } - lastClickLocation?.setData({ lat: e.latlng.lat, lon: e.latlng.lng }) - }) - - map.on("contextmenu", function (e) { - // @ts-ignore - lastClickLocation?.setData({ lat: e.latlng.lat, lon: e.latlng.lng }) - map.setZoom(map.getZoom() + 1) - }) - } - - this.leafletMap.setData(map) - } -} diff --git a/UI/Base/ModalRight.svelte b/UI/Base/ModalRight.svelte new file mode 100644 index 000000000..6decdfd67 --- /dev/null +++ b/UI/Base/ModalRight.svelte @@ -0,0 +1,20 @@ + + +
+
+ +
dispatch("close")}> + +
+
+ +
+
diff --git a/UI/Base/NextButton.svelte b/UI/Base/NextButton.svelte new file mode 100644 index 000000000..1068559a3 --- /dev/null +++ b/UI/Base/NextButton.svelte @@ -0,0 +1,21 @@ + + + dispatch("click")} options={{extraClasses: clss+" flex items-center"}}> + +
+ + +
+
diff --git a/UI/Base/ScrollableFullScreen.ts b/UI/Base/ScrollableFullScreen.ts deleted file mode 100644 index 6a9261d94..000000000 --- a/UI/Base/ScrollableFullScreen.ts +++ /dev/null @@ -1,169 +0,0 @@ -import Svg from "../../Svg" -import Combine from "./Combine" -import { FixedUiElement } from "./FixedUiElement" -import { UIEventSource } from "../../Logic/UIEventSource" -import Hash from "../../Logic/Web/Hash" -import BaseUIElement from "../BaseUIElement" -import Title from "./Title" -import Hotkeys from "./Hotkeys" -import Translations from "../i18n/Translations" - -/** - * - * The scrollableFullScreen is a bit of a peculiar component: - * - It shows a title and some contents, constructed from the respective functions passed into the constructor - * - When the element is 'activated', one clone of title+contents is attached to the fullscreen - * - The element itself will - upon rendering - also show the title and contents (allthough it'll be a different clone) - * - * - */ -export default class ScrollableFullScreen { - private static readonly empty = ScrollableFullScreen.initEmpty() - private static _currentlyOpen: ScrollableFullScreen - public isShown: UIEventSource - private hashToShow: string - private _fullscreencomponent: BaseUIElement - private _resetScrollSignal: UIEventSource = new UIEventSource(undefined) - private _setHash: boolean - - constructor( - title: (options: { mode: string }) => BaseUIElement, - content: (options: { - mode: string - resetScrollSignal: UIEventSource - }) => BaseUIElement, - hashToShow: string, - isShown: UIEventSource = new UIEventSource(false), - options?: { - setHash?: boolean - } - ) { - this.hashToShow = hashToShow - this.isShown = isShown - this._setHash = options?.setHash ?? true - - if ((hashToShow === undefined || hashToShow === "") && this._setHash) { - throw "HashToShow should be defined as it is vital for the 'back' key functionality" - } - - const mobileOptions = { - mode: "mobile", - resetScrollSignal: this._resetScrollSignal, - } - - this._fullscreencomponent = this.BuildComponent( - title(mobileOptions), - content(mobileOptions).SetClass("pb-20") - ) - - const self = this - if (this._setHash) { - Hash.hash.addCallback((h) => { - if (h === undefined) { - isShown.setData(false) - } - }) - } - - isShown.addCallbackD((isShown) => { - if (isShown) { - // We first must set the hash, then activate the panel - // If the order is wrong, this will cause the panel to disactivate again - ScrollableFullScreen._currentlyOpen = self - self.Activate() - } else { - if (self.hashToShow !== undefined) { - Hash.hash.setData(undefined) - } - // Some cleanup... - ScrollableFullScreen.collapse() - } - }) - if (isShown.data) { - ScrollableFullScreen._currentlyOpen = self - this.Activate() - } - } - - private static initEmpty(): FixedUiElement { - Hotkeys.RegisterHotkey( - { nomod: "Escape", onUp: true }, - Translations.t.hotkeyDocumentation.closeSidebar, - ScrollableFullScreen.collapse - ) - - return new FixedUiElement("") - } - public static collapse() { - const fs = document.getElementById("fullscreen") - if (fs !== null) { - ScrollableFullScreen.empty.AttachTo("fullscreen") - fs.classList.add("hidden") - } - - const opened = ScrollableFullScreen._currentlyOpen - if (opened !== undefined) { - opened?.isShown?.setData(false) - } - } - - Destroy() { - this._fullscreencomponent.Destroy() - } - - /** - * Actually show this in the 'fullscreen'-div - * @constructor - */ - public Activate(): void { - if (this.hashToShow && this.hashToShow !== "" && this._setHash) { - Hash.hash.setData(this.hashToShow) - } - this.isShown.setData(true) - this._fullscreencomponent.AttachTo("fullscreen") - const fs = document.getElementById("fullscreen") - ScrollableFullScreen._currentlyOpen = this - fs?.classList?.remove("hidden") - } - - private BuildComponent(title: BaseUIElement, content: BaseUIElement): BaseUIElement { - const returnToTheMap = new Combine([ - Svg.back_svg().SetClass("block md:hidden w-12 h-12 p-2 svg-foreground"), - Svg.close_svg().SetClass("hidden md:block w-12 h-12 p-3 svg-foreground"), - ]).SetClass("rounded-full p-0 flex-shrink-0 self-center") - - returnToTheMap.onClick(() => { - this.isShown.setData(false) - Hash.hash.setData(undefined) - }) - - title = new Title(title, 2) - title.SetClass( - "text-l sm:text-xl md:text-2xl w-full p-0 max-h-20vh overflow-y-auto self-center" - ) - - const contentWrapper = new Combine([content]).SetClass( - "block p-2 md:pt-4 w-full h-full overflow-y-auto" - ) - - this._resetScrollSignal.addCallback((_) => { - contentWrapper.ScrollToTop() - }) - - return new Combine([ - new Combine([ - new Combine([returnToTheMap, title]).SetClass( - "border-b-1 border-black shadow bg-white flex flex-shrink-0 pt-1 pb-1 md:pt-0 md:pb-0" - ), - contentWrapper, - // We add an ornament which takes around 5em. This is in order to make sure the Web UI doesn't hide - ]).SetClass("flex flex-col h-full relative bg-white"), - ]).SetClass( - "fixed top-0 left-0 right-0 h-screen w-screen md:w-auto md:relative z-above-controls md:rounded-xl overflow-hidden" - ) - } - - static ActivateCurrent() { - ScrollableFullScreen._currentlyOpen?.Activate() - } -} diff --git a/UI/Base/ShareButton.svelte b/UI/Base/ShareButton.svelte new file mode 100644 index 000000000..16286d11c --- /dev/null +++ b/UI/Base/ShareButton.svelte @@ -0,0 +1,33 @@ + + + + diff --git a/UI/Base/SubtleButton.svelte b/UI/Base/SubtleButton.svelte index edd897372..464bba17e 100644 --- a/UI/Base/SubtleButton.svelte +++ b/UI/Base/SubtleButton.svelte @@ -1,82 +1,31 @@ - dispatch("click", e)} > {#if imageUrl !== undefined} {#if typeof imageUrl === "string"} - - {:else} -