Merge master

This commit is contained in:
Pieter Vander Vennet 2025-04-27 00:34:30 +02:00
commit b61f930fea
39 changed files with 525 additions and 22753 deletions

23
.forgejo/setup/action.yml Normal file
View file

@ -0,0 +1,23 @@
name: 'Setup'
description: 'Checkout code, set up Nodejs, run `npm ci`'
runs:
using: 'composite'
steps:
- uses: actions/checkout@v4
- name: Setup up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: package-lock.json
- name: pwd
run: pwd && ls
shell: bash
- name: install deps
run: npm ci
shell: bash

View file

@ -0,0 +1,23 @@
name: 'Upload_hetzner'
description: 'Uploads a directory to hetzner. Will zip first, for performance'
inputs:
src:
description: 'The source directory'
required: true
dst:
description: "The destination directory. The source directory will be placed _inside_"
required: true
runs:
using: 'composite'
steps:
- name: Upload
shell: bash
run: |
F=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16)
zip $F.zip ${{ inputs.src }}/*
scp $F.zip hetzner:${{ inputs.dst }}/
ssh hetzner "cd ${{ inputs.dst }} unzip $F.zip && rm $F.zip"

View file

@ -4,21 +4,10 @@ on:
- cron: "0 2 * * *"
jobs:
daily_data_maintenance:
create_community_index:
runs-on: [ ubuntu-latest, hetzner-access ]
steps:
- uses: https://source.mapcomplete.org/actions/checkout@v4
- name: Set up Node.js
uses: https://source.mapcomplete.org/actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: package-lock.json
- name: install deps
run: npm ci
shell: bash
- uses: ./.forgejo/setup
- name: create community index files
shell: bash
@ -31,6 +20,11 @@ jobs:
scp community-index.zip hetzner:data/
ssh hetzner "cd data && rm -rf community-index/ && unzip community-index.zip && rm community-index.zip"
update_statistics:
runs-on: [ ubuntu-latest, hetzner-access ]
steps:
- uses: https://source.mapcomplete.org/actions/checkout@v4
- uses: ./.forgejo/snippets/setup
- name: Update statistics
shell: bash

View file

@ -10,17 +10,7 @@ jobs:
runs-on: [ubuntu-latest, hetzner-access]
steps:
- uses: https://source.mapcomplete.org/actions/checkout@v4
- name: Set up Node.js
uses: https://source.mapcomplete.org/actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: package-lock.json
- name: install deps
run: npm ci
shell: bash
- uses: ./.forgejo/setup
- name: create generated dir
run: mkdir -p ./assets/generated

View file

@ -8,17 +8,7 @@ jobs:
runs-on: [ ubuntu-latest, hetzner-access ]
steps:
- uses: https://source.mapcomplete.org/actions/checkout@v4
- name: Set up Node.js
uses: https://source.mapcomplete.org/actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: package-lock.json
- name: install deps
run: npm ci
shell: bash
- uses: ./.forgejo/setup
- name: create generated dir
run: mkdir ./assets/generated

View file

@ -0,0 +1,21 @@
on:
workflow_dispatch:
schedule:
- cron: "0 2 1 * *"
jobs:
update_nsi_logos:
runs-on: [ ubuntu-latest, hetzner-access ]
steps:
- uses: https://source.mapcomplete.org/actions/checkout@v4
- uses: ./.forgejo/setup
- name: Download the NSI-logos
shell: bash
run: npm run download:nsi-logos
- uses: ./.forgejo/upload_hetzner
with:
src: "./public/assets/data/nsi"
dst: "nsi"

View file

@ -9,17 +9,11 @@ jobs:
runs-on: [ lain ]
steps:
- uses: https://source.mapcomplete.org/actions/checkout@v4
- name: Set up Node.js
uses: https://source.mapcomplete.org/actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: package-lock.json
- uses: ./.forgejo/setup
- name: Init all dependencies and layers
shell: bash
run: npm ci && npm run init
run: npm run init
- name: Create export script
shell: bash

View file

@ -80,6 +80,7 @@
- lighthouse
- love_hotel
- map
- mobility_hub
- mountain_rescue
- nature_reserve
- observation_tower
@ -213,6 +214,7 @@
- food_courts
- governments
- hackerspace
- mobility_hub
- nature_reserve
- observation_tower
- outdoor_seating

View file

@ -27,7 +27,6 @@ This table gives a summary of ids, names and other metainformation. [See the onl
| TW_NLSC_WMS_LANDSECT | Taiwan Land-Section Data | other | | © National Land Surveying and Mapping Center, Taiwan OGDL 1.0 |
| TW_NLSC_WMS_Village | Taiwan Village Boundaries | other | | © National Land Surveying and Mapping Center, Taiwan OGDL 1.0 |
| AL_DPGJC_ASIG_SistemiAdresave | Address System Albania (ASIG) | map | | |
| openlabs-geoportal-tirana | Municipality of Tirana (Open Labs GeoPortal) | map | | Data provided by the Muncipality of Tirana hosted by Open Labs |
| bev-inspire-orthofoto | BEV INSPIRE Orthofoto | photo | | Bundesamt für Eich- und Vermessungswesen |
| basemap.at | basemap.at | map | | basemap.at |
| basemap.at-orthofoto | basemap.at Orthofoto | photo | ⭐ | basemap.at |
@ -705,7 +704,8 @@ This table gives a summary of ids, names and other metainformation. [See the onl
| Kansas_NG911_2018 | Kansas NG911 Orthoimagery (2018) | historicphoto | | Kansas 911 Coordinating Council |
| Kansas_NG911_2021 | Kansas NG911 Orthoimagery (2021) | photo | ⭐ | Kansas 911 Coordinating Council |
| KYAPED_Phase_1 | KyFromAbove Aerial Imagery (2012-2014) | historicphoto | | KyFromAbove |
| KYAPED_Phase_2 | KyFromAbove Aerial Imagery (2018-2022) | photo | | KyFromAbove |
| KYAPED_Phase_2 | KyFromAbove Aerial Imagery (2018-2022) | historicphoto | | KyFromAbove |
| KYAPED_Phase_3 | KyFromAbove Aerial Imagery (2022-2024) | photo | ⭐ | KyFromAbove |
| MassGIS-LIDAR-Shaded-Relief | MassGIS LIDAR Shaded Relief | elevation | | MassGIS |
| MassGIS-LIDAR-Slope | MassGIS LIDAR Slope | elevation | | MassGIS |
| MassGIS_2021_Aerial | MassGIS 2021 Aerial Imagery | photo | | MassGIS |
@ -811,9 +811,9 @@ This table gives a summary of ids, names and other metainformation. [See the onl
| RIGIS_Aerial_Photo_23s | Rhode Island Aerial Photo (Spring 2023) | historicphoto | | RIGIS |
| RIGIS_Aerial_Photo_24s | Rhode Island Aerial Photo (Spring 2024) | photo | | RIGIS |
| TNMap_Orthoimagery_Latest | TNMap Orthoimagery Latest | photo | | Tennessee Imagery Program |
| brazos_county_2019_wms | TX: Brazos County Imagery 2019 | photo | ⭐ | Strategic Mapping Program (StratMap). Brazos County Imagery, 2019-01-29 |
| brazos_county_2019_wms | StratMap Brazos County Imagery (2019) | photo | ⭐ | Strategic Mapping Program (StratMap). Brazos County Imagery, 2019-01-29 |
| capcog_2022 | CAPCOG Imagery (2022) | photo | | Strategic Mapping Program (StratMap). CAPCOG Imagery, 2022-01-22 |
| caparea_2019_wms | TX: CapArea Imagery 2019 | historicphoto | | Strategic Mapping Program (StratMap). CapArea Imagery, 2019-01-29 |
| caparea_2019_wms | StratMap CapArea Imagery (2019) | historicphoto | | Strategic Mapping Program (StratMap). CapArea Imagery, 2019-01-29 |
| amarillo_2016_wms | TX: City of Amarillo Imagery 2015 | photo | | Strategic Mapping Program (StratMap). City of Amarillo Imagery, 2015-03-13 |
| el_paso_2015_wms | TX: City of El Paso Imagery 2015 | photo | | Strategic Mapping Program (StratMap). City of El Paso Imagery, 2015-10-25 |
| georgetown_2016_wms | TX: City of Georgetown Imagery 2015 | photo | | Texas Natural Resources Information System (TNRIS). City of Georgetown Imagery, 2015-03-06 |

126
Docs/Layers/mobility_hub.md Normal file
View file

@ -0,0 +1,126 @@
[//]: # (WARNING: this file is automatically generated. Please find the sources at the bottom and edit those sources)
# mobility_hub
Mobility hubs are places where different kinds of transit meet, making it easy to switch between them. These places are usually part of a larger network or system.
- This layer is shown at zoomlevel **8** and higher
## Table of contents
1. [Themes using this layer](#themes-using-this-layer)
2. [Presets](#presets)
3. [Basic tags for this layer](#basic-tags-for-this-layer)
4. [Supported attributes](#supported-attributes)
5. [Featureview elements and TagRenderings](#featureview-elements-and-tagrenderings)
- [images](#images)
- [name](#name)
- [network](#network)
- [website](#website)
- [physical_marker](#physical_marker)
- [leftover-questions](#leftover-questions)
- [move-button](#move-button)
- [lod](#lod)
## Themes using this layer
- [personal](https://mapcomplete.org/personal)
- [transit](https://mapcomplete.org/transit)
## Presets
The following options to create new points are included:
- **a mobility hub** which has the following tags:<a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dmobility_hub' target='_blank'>mobility_hub</a> & <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dinformation' target='_blank'>information</a>
## Basic tags for this layer
Elements must match the expression **<a href='https://wiki.openstreetmap.org/wiki/Key:amenity' target='_blank'>amenity</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dmobility_hub' target='_blank'>mobility_hub</a>**
[Execute on overpass](http://overpass-turbo.eu/?Q=%5Bout%3Ajson%5D%5Btimeout%3A90%5D%3B%28%20%20%20%20nwr%5B%22amenity%22%3D%22mobility_hub%22%5D%28%7B%7Bbbox%7D%7D%29%3B%0A%29%3Bout%20body%3B%3E%3Bout%20skel%20qt%3B)
## Supported attributes
**Warning:**: this quick overview is incomplete
| attribute | type | values which are supported by this layer |
-----|-----|----- |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/name#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/name/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [name](https://wiki.openstreetmap.org/wiki/Key:name) | [string](../SpecialInputElements.md#string) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/network#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/network/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [network](https://wiki.openstreetmap.org/wiki/Key:network) | [string](../SpecialInputElements.md#string) | [Groningen-Drenthe](https://wiki.openstreetmap.org/wiki/Tag:network%3DGroningen-Drenthe) [Hoppin](https://wiki.openstreetmap.org/wiki/Tag:network%3DHoppin) [Jelbi](https://wiki.openstreetmap.org/wiki/Tag:network%3DJelbi) |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/website#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/website/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) | |
| <a target="_blank" href='https://taginfo.openstreetmap.org/keys/tourism#values'><img src='https://mapcomplete.org/assets/svg/search.svg' height='18px'></a> <a target="_blank" href='https://taghistory.raifer.tech/?#***/tourism/'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a> [tourism](https://wiki.openstreetmap.org/wiki/Key:tourism) | Multiple choice | [information](https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dinformation) [information](https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dinformation) [information](https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dinformation) |
## Featureview elements and TagRenderings
| id | question | labels | freeform key |
-----|-----|-----|----- |
| [images](#images) <br/> _(Original in [questions](./BuiltinQuestions.md#images))_ | _{image_carousel()}{image_upload()}_ | | _Multiple choice only_ |
| [name](#name) | What is the name of this mobility hub?<br/>_This mobility hub is called {name}_ | | *[name](https://wiki.osm.org/wiki/Key:name)* ([string](../SpecialInputElements.md#string)) |
| [network](#network) | To which network does this mobility hub belong to?<br/>_This mobility hub belongs to the network {network}_<br/>3 options | | *[network](https://wiki.osm.org/wiki/Key:network)* ([string](../SpecialInputElements.md#string)) |
| [website](#website) <br/> _(Original in [questions](./BuiltinQuestions.md#website))_ | What is the website of ?<br/>_<a href='{website}' rel='nofollow noopener noreferrer' target='_blank'>{website}</a>_<br/>1 options | contact | *[website](https://wiki.osm.org/wiki/Key:website)* ([url](../SpecialInputElements.md#url)) |
| [physical_marker](#physical_marker) | What kind of physical marker is used to mark this mobility hub?<br/>3 options | | _Multiple choice only_ |
| [leftover-questions](#leftover-questions) | _{questions( ,hidden)}_ | ignore-docs, added_by_default | _Multiple choice only_ |
| [move-button](#move-button) | _{move_button()}_ | | _Multiple choice only_ |
| [lod](#lod) <br/> _(Original in [questions](./BuiltinQuestions.md#lod))_ | _{linked_data_from_website()}_ | added_by_default | _Multiple choice only_ |
### images
This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` and shows the button to upload new images
_This tagrendering has no question and is thus read-only_
*{image_carousel()}{image_upload()}*
### name
The question is `What is the name of this mobility hub?`
*This mobility hub is called {name}* is shown if `name` is set
### network
The question is `To which network does this mobility hub belong to?`
*This mobility hub belongs to the network {network}* is shown if `network` is set
- <img width='38px' height='38px' src='https://dev.mapcomplete.org/./assets/layers/mobility_hub/hub-gd.svg'> *This mobility hub belongs to the Groningen-Drenthe network* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:network' target='_blank'>network</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:network%3DGroningen-Drenthe' target='_blank'>Groningen-Drenthe</a>
- <img width='38px' height='38px' src='https://dev.mapcomplete.org/./assets/layers/mobility_hub/logo-hoppin.svg'> *This mobility hub belongs to the Hoppin network* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:network' target='_blank'>network</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:network%3DHoppin' target='_blank'>Hoppin</a>
- *This mobility hub belongs to the Jelbi network* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:network' target='_blank'>network</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:network%3DJelbi' target='_blank'>Jelbi</a>
### website
The question is `What is the website of {title()}?`
*<a href='{website}' rel='nofollow noopener noreferrer' target='_blank'>{website}</a>* is shown if `website` is set
- <img width='38px' height='38px' src='https://dev.mapcomplete.org/./assets/layers/icons/website.svg'> *<a href='{contact:website}' rel='nofollow noopener noreferrer' target='_blank'>{contact:website}</a>* is shown if with contact:website~.+. _This option cannot be chosen as answer_
This tagrendering has labels
`contact`
### physical_marker
The question is `What kind of physical marker is used to mark this mobility hub?`
- *This mobility hub is marked by a board, containing information about the hub* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dinformation' target='_blank'>information</a> & <a href='https://wiki.openstreetmap.org/wiki/Key:information' target='_blank'>information</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:information%3Dboard' target='_blank'>board</a>
- *This mobility hub is marked by a sign with an electronic display* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dinformation' target='_blank'>information</a> & <a href='https://wiki.openstreetmap.org/wiki/Key:information' target='_blank'>information</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:information%3Dterminal' target='_blank'>terminal</a>
- *This mobility hub is marked by a simple sign showing only basic information like the logo or name* is shown if with <a href='https://wiki.openstreetmap.org/wiki/Key:tourism' target='_blank'>tourism</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:tourism%3Dinformation' target='_blank'>information</a> & <a href='https://wiki.openstreetmap.org/wiki/Key:information' target='_blank'>information</a>=<a href='https://wiki.openstreetmap.org/wiki/Tag:information%3Dsign' target='_blank'>sign</a>
### leftover-questions
_This tagrendering has no question and is thus read-only_
*{questions( ,hidden)}*
This tagrendering has labels
`ignore-docs`
`added_by_default`
### move-button
_This tagrendering has no question and is thus read-only_
*{move_button()}*
### lod
_This tagrendering has no question and is thus read-only_
*{linked_data_from_website()}*
This tagrendering has labels
`added_by_default`
This document is autogenerated from [assets/layers/mobility_hub/mobility_hub.json](https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/assets/layers/mobility_hub/mobility_hub.json)

View file

@ -1086,7 +1086,7 @@ The special element which shows the questions which are unkown. Added by default
### statistics
Show general statistics about the elements currently in view. Intended to use on the `current_view`-layer
Show general statistics about all the elements currently in view. Intended to use on the `current_view`-layer. They will be split per layer
#### Example usage of statistics

View file

@ -10,6 +10,136 @@
"contact_email": "info@mapcomplete.org"
},
"tags": [
{
"key": "amenity",
"value": "mobility_hub",
"description": "Features with this tag are displayed by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "id",
"description": "id~.+ is displayed as \"You just created this element! Thanks for sharing this info with the world and helping people worldwide.\" by layers Mobility Hubs, Transit Stops, Bus lines, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#just_created",
"icon_url": "./assets/svg/party.svg"
},
{
"key": "image",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Mobility Hubs, Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#images",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "panoramax",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Mobility Hubs, Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#images",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "mapillary",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Mobility Hubs, Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#images",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "wikidata",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Mobility Hubs, Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#images",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "wikipedia",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Mobility Hubs, Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#images",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "name",
"description": "Values of `name` are shown with \"This mobility hub is called {name}\" and can be updated. The question is \"What is the name of this mobility hub?\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#name",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "network",
"description": "Values of `network` are shown with \"This mobility hub belongs to the network {network}\" and can be updated. The question is \"To which network does this mobility hub belong to?\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#network",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "network",
"value": "Groningen-Drenthe",
"description": "network=Groningen-Drenthe is displayed as \"This mobility hub belongs to the Groningen-Drenthe network\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#network",
"icon_url": "./assets/layers/mobility_hub/hub-gd.svg"
},
{
"key": "network",
"value": "Hoppin",
"description": "network=Hoppin is displayed as \"This mobility hub belongs to the Hoppin network\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#network",
"icon_url": "./assets/layers/mobility_hub/logo-hoppin.svg"
},
{
"key": "network",
"value": "Jelbi",
"description": "network=Jelbi is displayed as \"This mobility hub belongs to the Jelbi network\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#network",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "website",
"description": "Values of `website` are shown with \"<a href='{website}' rel='nofollow noopener noreferrer' target='_blank'>{website}</a>\" and can be updated. The question is \"What is the website of {title()}?\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#website",
"icon_url": "./assets/layers/icons/website.svg"
},
{
"key": "contact:website",
"description": "contact:website~.+ is displayed as \"<a href='{contact:website}' rel='nofollow noopener noreferrer' target='_blank'>{contact:website}</a>\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#website",
"icon_url": "./assets/layers/icons/website.svg"
},
{
"key": "tourism",
"value": "information",
"description": "tourism=information & information=board is displayed as \"This mobility hub is marked by a board, containing information about the hub\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#physical_marker",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "information",
"value": "board",
"description": "tourism=information & information=board is displayed as \"This mobility hub is marked by a board, containing information about the hub\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#physical_marker",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "tourism",
"value": "information",
"description": "tourism=information & information=terminal is displayed as \"This mobility hub is marked by a sign with an electronic display\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#physical_marker",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "information",
"value": "terminal",
"description": "tourism=information & information=terminal is displayed as \"This mobility hub is marked by a sign with an electronic display\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#physical_marker",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "tourism",
"value": "information",
"description": "tourism=information & information=sign is displayed as \"This mobility hub is marked by a simple sign showing only basic information like the logo or name\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#physical_marker",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "information",
"value": "sign",
"description": "tourism=information & information=sign is displayed as \"This mobility hub is marked by a simple sign showing only basic information like the logo or name\" by layer Mobility Hubs",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/mobility_hub.md#physical_marker",
"icon_url": "./assets/layers/mobility_hub/hub.svg"
},
{
"key": "highway",
"value": "bus_stop",
@ -17,12 +147,6 @@
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/transit_stops.md",
"icon_url": "./assets/layers/transit_stops/bus_stop.svg"
},
{
"key": "id",
"description": "id~.+ is displayed as \"You just created this element! Thanks for sharing this info with the world and helping people worldwide.\" by layers Transit Stops, Bus lines, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/transit_stops.md#just_created",
"icon_url": "./assets/svg/party.svg"
},
{
"key": "name",
"description": "Values of `name` are shown with \"This stop is called <b>{name}</b>\" and can be updated. The question is \"What is the name of this stop?\" by layer Transit Stops",
@ -42,36 +166,6 @@
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/transit_stops.md#stop_name",
"icon_url": "./assets/layers/transit_stops/bus_stop.svg"
},
{
"key": "image",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/transit_stops.md#images",
"icon_url": "./assets/layers/transit_stops/bus_stop.svg"
},
{
"key": "panoramax",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/transit_stops.md#images",
"icon_url": "./assets/layers/transit_stops/bus_stop.svg"
},
{
"key": "mapillary",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/transit_stops.md#images",
"icon_url": "./assets/layers/transit_stops/bus_stop.svg"
},
{
"key": "wikidata",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/transit_stops.md#images",
"icon_url": "./assets/layers/transit_stops/bus_stop.svg"
},
{
"key": "wikipedia",
"description": "Images are displayed based on the keys image, image:0, image:1,..., panoramax, panoramax:0, panoramx:1, ... , wikidata, wikipedia, wikimedia_commons and mapillary Furthermore, this layer shows images based on the keys panoramax, image, wikidata, wikipedia, wikimedia_commons and mapillary by layers Transit Stops, Bike parking, Parking, Shelter",
"doc_url": "https://source.mapcomplete.org/MapComplete/MapComplete/src/branch/develop/Docs/Layers/transit_stops.md#images",
"icon_url": "./assets/layers/transit_stops/bus_stop.svg"
},
{
"key": "shelter",
"value": "yes",

View file

@ -91,6 +91,7 @@ This theme contains the following layers:
- [maproulette_challenge](../Layers/maproulette_challenge.md)
- [maxspeed](../Layers/maxspeed.md)
- [memorial](../Layers/memorial.md)
- [mobility_hub](../Layers/mobility_hub.md)
- [mountain_rescue](../Layers/mountain_rescue.md)
- [nature_reserve](../Layers/nature_reserve.md)
- [note](../Layers/note.md)

View file

@ -8,6 +8,7 @@ The theme introduction reads:
This theme contains the following layers:
- [mobility_hub](../Layers/mobility_hub.md)
- [transit_stops](../Layers/transit_stops.md)
- [transit_routes](../Layers/transit_routes.md)
- [bike_parking](../Layers/bike_parking.md)

View file

@ -419,7 +419,7 @@ The default value is _false_
The mode the application starts in, e.g. 'map', 'dashboard' or 'statistics'
This documentation is defined in the source code at [generateDocs.ts](ervdvn/git2/MapComplete/scripts/generateDocs.ts#L449)
This documentation is defined in the source code at [generateDocs.ts](ervdvn/git2/MapComplete/scripts/generateDocs.ts#L451)
The default value is _map_

View file

@ -14563,4 +14563,4 @@
"render": "wind turbine"
}
}
}
}

View file

@ -11558,4 +11558,4 @@
"render": "windturbine"
}
}
}
}

22589
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -37,6 +37,8 @@
"summary_server": "https://cache.mapcomplete.org/",
"geoip_server": "https://ipinfo.mapcomplete.org/",
"error_server": "https://report.mapcomplete.org/report",
"#nsi_logos_server": "The location where a running instance of MapComplete will fetch the NSI-logos. This is by default the host itself, but not in e.g. the android app",
"nsi_logos_server": "https://mapcomplete.org/assets/data/nsi/",
"api_keys": {
"#": "Various API-keys for various services. Feel free to reuse those in another MapComplete-hosted version",
"#fork": "Not bound to a domain; can be reused",
@ -110,7 +112,7 @@
"generate": "npm run generate:licenses && npm run generate:images && npm run generate:charging-stations && npm run generate:translations && npm run reset:layeroverview && npm run generate:service-worker",
"generate:charging-stations": "cd ./assets/layers/charging_station && vite-node csvToJson.ts && cd -",
"clean:tests": "find . -type f -name \"*.doctest.ts\" | xargs -r rm",
"clean": "rm -rf .cache/ && (find *.html | grep -v \"^\\(404\\|index\\|land\\|privacy\\|test\\|studio\\|theme\\|style_test\\|statistics\\|status\\|leaderboard\\|inspector\\).html\" | xargs -r rm) && (ls | grep \"^index_[a-zA-Z_-]\\+\\.ts$\" | xargs -r rm)",
"clean": "echo '{\n \"#\": \"Settings in this file override the `config`-section of `package.json`\"\n}' > config.json && rm -rf .cache/ && (find *.html | grep -v \"^\\(404\\|index\\|land\\|privacy\\|test\\|studio\\|theme\\|style_test\\|statistics\\|status\\|leaderboard\\|inspector\\).html\" | xargs -r rm) && (ls | grep \"^index_[a-zA-Z_-]\\+\\.ts$\" | xargs -r rm)",
"generate:dependency-graph": "node_modules/.bin/depcruise --exclude \"^node_modules\" --output-type dot Logic/State/MapState.ts > dependencies.dot && dot dependencies.dot -T svg -o dependencies.svg && rm dependencies.dot",
"scrapeWebsites": "vite-node scripts/importscripts/compareWebsiteData.ts -- ~/Downloads/ShopsWithWebsiteNodes.csv ~/data/scraped_websites/",
"### 0": "VELOPARK",
@ -227,7 +229,7 @@
"marked": "^12.0.2",
"monaco-editor": "^0.46.0",
"mvt-to-geojson": "^0.0.6",
"name-suggestion-index": "^6.0.20250302",
"name-suggestion-index": "^6.0.20250413",
"npm": "^11.1.0",
"opening_hours": "^3.6.0",
"osm-auth": "^2.6.0",

View file

@ -126,7 +126,7 @@ class DownloadEli extends Script {
fs.writeFileSync(targetGlobal, JSON.stringify(contentsGlobal, null, " "), {
encoding: "utf8",
})
console.log("Written", keptGlobalLayers.length + ", entries to the global ELI")
console.log("Written", keptGlobalLayers.length + ", entries to the global ELI ("+targetGlobal+")")
}
}

View file

@ -211,7 +211,7 @@ class NsiLogos extends Script {
const config: LayerConfigJson = {
id: "nsi_" + type,
description: {
en: "Exposes part of the NSI to reuse in other themes, e.g. for rendering",
en: "Exposes part of the NSI to reuse in other themes, e.g. for rendering. Automatically generated and never directly loaded in a theme",
},
source: "special:library",
pointRendering: null,

View file

@ -8,7 +8,18 @@ then
npm run generate:layeroverview
npm run generate:layouts
fi
vite-node scripts/nsiLogos.ts -- patch
echo '''
{
"nsi_logos_server": "https://mapcomplete.org/assets/data/nsi/logos/"
}
''' > config.json
cat config.json | jq
if [ $? -ne 0 ]
then
echo "config.json file is invalid, exiting now"
tput bel
exit 0
fi
npm run build
echo '''
import type { CapacitorConfig } from "@capacitor/cli";
@ -22,6 +33,7 @@ const config: CapacitorConfig = {
export default config;
''' > capacitor.config.ts
# copy distribution files
rm -rf dist-full
mkdir dist-full
@ -51,6 +63,11 @@ cp -r dist/assets/svg dist-full/assets/
cp -r dist/assets/templates dist-full/assets/
cp -r dist/assets/generated/themes/ dist-full/assets/generated/
cp -r dist/assets/themes dist-full/assets/
cp dist/assets/*.js.map dist-full/assets/
rm -rf dist-full/assets/data/nsi
rm /home/pietervdvn/git/MapComplete/dist-full/assets/layers/nsi_brand/nsi_brand.json
rm /home/pietervdvn/git/MapComplete/dist-full/assets/layers/nsi_operator/nsi_operator.json
# mkdir dist-full/assets/generated
nvm use
@ -59,7 +76,8 @@ nvm use
npx capacitor-assets generate
npx cap sync
cd android
npm run clean
echo "All done! Don't forget to click 'gradle sync files' in Android Studio"
tput bel
tput bel

View file

@ -13,7 +13,6 @@ import StaticFeatureSource, {
} from "../FeatureSource/Sources/StaticFeatureSource"
import { MapProperties } from "../../Models/MapProperties"
import { Orientation } from "../../Sensors/Orientation"
;("use strict")
/**
* The geolocation-handler takes a map-location and a geolocation state.

View file

@ -330,6 +330,9 @@ ${nds}${tags} </way>
}
private isPolygon(): boolean {
if (this.coordinates.length === 0) {
return false
}
// Compare lat and lon seperately, as the coordinate array might not be a reference to the same object
if (
this.coordinates[0][0] !== this.coordinates[this.coordinates.length - 1][0] ||

View file

@ -5,7 +5,6 @@ import { BBox } from "../BBox"
import osmtogeojson from "osmtogeojson"
import { FeatureCollection, Geometry } from "geojson"
import { OsmTags } from "../../Models/OsmFeature"
;("use strict")
/**
* Interfaces overpass to get all the latest data

View file

@ -8,6 +8,7 @@ import { TypedTranslation } from "../../UI/i18n/Translation"
import { RegexTag } from "../Tags/RegexTag"
import { TagConfigJson } from "../../Models/ThemeConfig/Json/TagConfigJson"
import { TagUtils } from "../Tags/TagUtils"
import Constants from "../../Models/Constants"
/**
* Main name suggestion index file
@ -69,8 +70,10 @@ export default class NameSuggestionIndex {
private loco: LocationConflation // Some additional boundaries
private _supportedTypes: string[]
private _serverLocation: string
constructor(
private constructor(
serverLocation: string,
nsiFile: Readonly<NSIFile>,
nsiWdFile: Readonly<
Record<
@ -82,6 +85,7 @@ export default class NameSuggestionIndex {
>,
features: Readonly<FeatureCollection>
) {
this._serverLocation = serverLocation
this.nsiFile = nsiFile
this.nsiWdFile = nsiWdFile
this.loco = new LocationConflation(features)
@ -101,6 +105,7 @@ export default class NameSuggestionIndex {
].map((url) => Utils.downloadJsonCached(url, 1000 * 60 * 60 * 24 * 30))
)
NameSuggestionIndex.inited = new NameSuggestionIndex(
Constants.nsiLogosEndpoint,
<any>nsi,
<any>nsiWd["wikidata"],
<any>features
@ -129,12 +134,13 @@ export default class NameSuggestionIndex {
* @param countries
* @private
*/
private static async fetchFrequenciesFor(type: string, countries: string[]) {
private async fetchFrequenciesFor(type: string, countries: string[]) {
const server = this._serverLocation
let stats = await Promise.all(
countries.map((c) => {
try {
return Utils.downloadJsonCached<Record<string, number>>(
`./assets/data/nsi/stats/${type}.${c.toUpperCase()}.json`,
`${server}/stats/${type}.${c.toUpperCase()}.json`,
24 * 60 * 60 * 1000
)
} catch (e) {
@ -194,7 +200,7 @@ export default class NameSuggestionIndex {
const mappings: (Mapping & { frequency: number })[] = []
const frequencies =
country !== undefined
? await NameSuggestionIndex.fetchFrequenciesFor(type, country)
? await this.fetchFrequenciesFor(type, country)
: {}
for (const key in tags) {
if (key.startsWith("_")) {
@ -398,11 +404,12 @@ export default class NameSuggestionIndex {
}
public getIconUrl(nsiItem: NSIItem): string | undefined {
if (!nsiItem.ext) {
const baseUrl = this._serverLocation
if (!nsiItem.ext || baseUrl === null) {
// No extension -> there is no logo
return undefined
}
return "./assets/data/nsi/logos/" + nsiItem.id + "." + nsiItem.ext
return baseUrl +"/logos/"+ nsiItem.id + "." + nsiItem.ext
}
private static readonly brandPrefix = ["name", "alt_name", "operator", "brand"] as const

View file

@ -139,6 +139,7 @@ export default class Constants {
public static osmAuthConfig: AuthConfig = Constants.config.oauth_credentials
public static nominatimEndpoint: string = Constants.config.nominatimEndpoint
public static photonEndpoint: string = Constants.config.photonEndpoint
public static nsiLogosEndpoint: string = Constants.config.nsi_logos_server ?? null
public static weblate: string = "https://translate.mapcomplete.org/"
public static linkedDataProxy: string = Constants.config["jsonld-proxy"]

View file

@ -1,48 +0,0 @@
import { VariableUiElement } from "../Base/VariableUIElement"
import Title from "../Base/Title"
import TagRenderingChart from "./TagRenderingChart"
import Combine from "../Base/Combine"
import Locale from "../i18n/Locale"
import { FeatureSourceForLayer } from "../../Logic/FeatureSource/FeatureSource"
import BaseUIElement from "../BaseUIElement"
export default class StatisticsForLayerPanel extends VariableUiElement {
constructor(elementsInview: FeatureSourceForLayer) {
const layer = elementsInview.layer.layerDef
super(
elementsInview.features.stabilized(1000).map(
(features) => {
const els: BaseUIElement[] = []
const featuresForLayer = features
if (featuresForLayer.length === 0) {
return
}
els.push(new Title(layer.name, 1).SetClass("mt-8"))
const layerStats = []
for (const tagRendering of layer?.tagRenderings ?? []) {
const chart = new TagRenderingChart(featuresForLayer, tagRendering, {
chartclasses: "w-full",
chartstyle: "height: 60rem",
includeTitle: false,
})
const title = new Title(
tagRendering.question?.Clone() ?? tagRendering.id,
4
).SetClass("mt-8")
if (!chart.HasClass("hidden")) {
layerStats.push(
new Combine([title, chart]).SetClass(
"flex flex-col w-full lg:w-1/3"
)
)
}
}
els.push(new Combine(layerStats).SetClass("flex flex-wrap"))
return new Combine(els)
},
[Locale.language]
)
)
}
}

View file

@ -247,7 +247,7 @@ export default class TagRenderingChart extends Combine {
}
const config = <ChartConfiguration>{
type: options.chartType ?? (barchartMode ? "bar" : "doughnut"),
type: options.chartType ?? (barchartMode ? "bar" : "pie"),
data: {
labels,
datasets: [

View file

@ -10,6 +10,9 @@
import Tr from "../Base/Tr.svelte"
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
import Translations from "../i18n/Translations"
import TagRenderingChart from "../BigComponents/TagRenderingChart"
import ToSvelte from "../Base/ToSvelte.svelte"
import type { TagRenderingConfigJson } from "../../Models/ThemeConfig/Json/TagRenderingConfigJson"
export let onlyShowUsername: string[]
export let features: Feature[]
@ -25,10 +28,13 @@
key: string
value?: string
oldValue?: string
step: OsmObject
}[]
> = allHistories.mapD((histories) => HistoryUtils.fullHistoryDiff(histories, usernames))
const trs = shared_questions.tagRenderings.map((tr) => new TagRenderingConfig(tr))
const trs = shared_questions.tagRenderings.map(
(tr) => new TagRenderingConfig(<TagRenderingConfigJson>tr)
)
function detectQuestion(key: string): TagRenderingConfig {
return trs.find((tr) => tr.freeform?.key === key)
@ -40,17 +46,19 @@
tr: TagRenderingConfig
count: number
values: { value: string; count: number }[]
features: Feature[]
}[]
> = allDiffs.mapD((allDiffs) => {
const keyCounts = new Map<string, Map<string, number>>()
const keyCounts = new Map<string, Map<string, OsmObject[]>>()
for (const diff of allDiffs) {
const k = diff.key
if (!keyCounts.has(k)) {
keyCounts.set(k, new Map<string, number>())
keyCounts.set(k, new Map<string, OsmObject[]>())
}
const valueCounts = keyCounts.get(k)
const v = diff.value ?? ""
valueCounts.set(v, 1 + (valueCounts.get(v) ?? 0))
const oldFeaturesList = valueCounts.get(v) ?? []
valueCounts.set(v, [...oldFeaturesList, diff.step])
}
const perKey: {
@ -58,19 +66,29 @@
tr: TagRenderingConfig
count: number
values: { value: string; count: number }[]
features: Feature[]
}[] = []
keyCounts.forEach((values, key) => {
const keyTotal: { value: string; count: number }[] = []
keyCounts.forEach((values: Map<string, OsmObject[]>, key: string) => {
const keyTotal: { value: string; features: Feature[] }[] = []
values.forEach((count, value) => {
keyTotal.push({ value, count })
keyTotal.push({ value, features: count.map((step) => step.asGeoJson()) })
})
let countForKey = 0
for (const { count } of keyTotal) {
countForKey += count
let countForKey: Feature[] = []
for (const { features } of keyTotal) {
countForKey.push(...features)
}
keyTotal.sort((a, b) => b.count - a.count)
keyTotal.sort((a, b) => b.features.length - a.features.length)
const tr = detectQuestion(key)
perKey.push({ count: countForKey, tr, key, values: keyTotal })
perKey.push({
count: countForKey.length,
tr,
key,
values: keyTotal.map(({ value, features }) => ({
value,
count: features.length,
})),
features: countForKey,
})
})
perKey.sort((a, b) => b.count - a.count)
@ -105,6 +123,19 @@
</li>
{/each}
</ul>
{#if diff.tr}
<div class="h-48 w-48">
<ToSvelte
construct={new TagRenderingChart(diff.features, diff.tr, {
groupToOtherCutoff: 0,
chartType: "pie",
sort: true,
})}
/>
</div>
{:else}
Could not create a graph
{/if}
</AccordionSingle>
{/each}
{/if}

View file

@ -44,22 +44,37 @@ export class HistoryUtils {
.filter((ch) => ch.oldValue !== ch.value)
}
public static fullHistoryDiff(histories: OsmObject[][], onlyShowUsername?: Set<string>) {
const allDiffs: { key: string; oldValue?: string; value?: string }[] = [].concat(
...histories.map((history) => {
const filtered = history.filter(
(step) =>
!onlyShowUsername ||
onlyShowUsername?.has(step.tags["_last_edit:contributor"])
)
const diffs: {
public static fullHistoryDiff(
histories: OsmObject[][],
onlyShowUsername?: Set<string>
): {
key: string
value?: string
oldValue?: string
step: OsmObject
}[] {
const allDiffs: {
key: string
value?: string
oldValue?: string
step: OsmObject
}[] = []
for (const history of histories) {
const filtered = history.filter(
(step) =>
!onlyShowUsername || onlyShowUsername?.has(step.tags["_last_edit:contributor"])
)
for (const step of filtered) {
const diff: {
key: string
value?: string
oldValue?: string
}[][] = filtered.map((step) => HistoryUtils.tagHistoryDiff(step, history))
return [].concat(...diffs)
})
)
step: OsmObject
}[] = HistoryUtils.tagHistoryDiff(step, history)
allDiffs.push(...diff)
}
}
return allDiffs
}
}

View file

@ -70,6 +70,7 @@
searchIsRunning.set(false)
}
})
let state = {
mapProperties: maplibremap,
searchState: {
@ -164,6 +165,18 @@
let showPreviouslyVisited = new UIEventSource(true)
const t = Translations.t.inspector
function search(suggestion?: GeocodeResult) {
suggestion ??= searchSuggestions?.data?.[0]
console.log("Seaching", suggestion)
if (!suggestion) {
return
}
map.data.flyTo({
zoom: 14,
center: [suggestion.lon, suggestion.lat],
})
}
</script>
<div class="flex h-screen w-full flex-col">
@ -251,12 +264,13 @@
<MaplibreMap {map} mapProperties={maplibremap} autorecovery={true} />
<div class="absolute right-0 top-0 w-1/4 p-4">
<Searchbar
on:search={() => search()}
isFocused={searchIsFocussed}
value={searchvalue}
on:focus={() => state.searchState.showSearchDrawer.set(true)}
/>
{#if $searchSuggestions?.length > 0 || $searchIsFocussed}
<GeocodeResults {state} />
<GeocodeResults {state} on:select={(event) => search(event.detail)} />
{/if}
</div>
</div>

View file

@ -13,6 +13,7 @@
import FeaturePropertiesStore from "../../Logic/FeatureSource/Actors/FeaturePropertiesStore"
import SearchState from "../../Logic/State/SearchState"
import ArrowUp from "@babeard/svelte-heroicons/mini/ArrowUp"
import { createEventDispatcher } from "svelte"
export let entry: GeocodeResult
export let state: {
@ -40,8 +41,9 @@
let mapRotation = state.mapProperties.rotation
let inView = state.mapProperties.bounds.mapD((bounds) => bounds.contains([entry.lon, entry.lat]))
let dispatch = createEventDispatcher<{ select: GeocodeResult }>()
function select() {
state.searchState.applyGeocodeResult(entry)
dispatch("select", entry)
}
</script>

View file

@ -55,7 +55,12 @@
{#if $allowFilters}
<FilterResults {state} />
{/if}
<GeocodeResults {state}>
<GeocodeResults
{state}
on:select={(select) => {
state.searchState.applyGeocodeResult(select.detail)
}}
>
<svelte:fragment slot="if-no-results">
{#if $recentlySeen?.length > 0}
<SidebarUnit>

View file

@ -403,7 +403,7 @@ export default class SpecialVisualizations {
},
{
funcName: "statistics",
docs: "Show general statistics about the elements currently in view. Intended to use on the `current_view`-layer",
docs: "Show general statistics about all the elements currently in view. Intended to use on the `current_view`-layer. They will be split per layer",
args: [],
constr: (state) => new SvelteUIElement(AllFeaturesStatistics, { state }),

View file

@ -1,11 +1,11 @@
{
"contributors": [
{
"commits": 9515,
"commits": 9531,
"contributor": "Pieter Vander Vennet"
},
{
"commits": 546,
"commits": 557,
"contributor": "Robin van der Linde"
},
{

View file

@ -682,9 +682,9 @@
"vi"
],
"VU": [
"fr",
"en",
"bi"
"bi",
"fr"
],
"WS": [
"en",

View file

@ -11133,6 +11133,10 @@
"if": "value=memorial",
"then": "memorial - Layer showing memorial plaques, based upon a unofficial theme. Can be expanded to have multiple types of memorials later on"
},
{
"if": "value=mobility_hub",
"then": "mobility_hub - Mobility hubs are places where different kinds of transit meet, making it easy to switch between them. These places are usually part of a larger network or system."
},
{
"if": "value=mountain_rescue",
"then": "mountain_rescue - A building where first aid responders store material and might be on watch"

View file

@ -1012,6 +1012,10 @@
"if": "value=memorial",
"then": "<b>memorial</b> (builtin) - Layer showing memorial plaques, based upon a unofficial theme. Can be expanded to have multiple types of memorials later on"
},
{
"if": "value=mobility_hub",
"then": "<b>mobility_hub</b> (builtin) - Mobility hubs are places where different kinds of transit meet, making it easy to switch between them. These places are usually part of a larger network or system."
},
{
"if": "value=mountain_rescue",
"then": "<b>mountain_rescue</b> (builtin) - A building where first aid responders store material and might be on watch"
@ -13777,6 +13781,10 @@
"if": "value=memorial",
"then": "memorial - Layer showing memorial plaques, based upon a unofficial theme. Can be expanded to have multiple types of memorials later on"
},
{
"if": "value=mobility_hub",
"then": "mobility_hub - Mobility hubs are places where different kinds of transit meet, making it easy to switch between them. These places are usually part of a larger network or system."
},
{
"if": "value=mountain_rescue",
"then": "mountain_rescue - A building where first aid responders store material and might be on watch"
@ -35578,6 +35586,10 @@
"if": "value=memorial",
"then": "memorial - Layer showing memorial plaques, based upon a unofficial theme. Can be expanded to have multiple types of memorials later on"
},
{
"if": "value=mobility_hub",
"then": "mobility_hub - Mobility hubs are places where different kinds of transit meet, making it easy to switch between them. These places are usually part of a larger network or system."
},
{
"if": "value=mountain_rescue",
"then": "mountain_rescue - A building where first aid responders store material and might be on watch"