Merge develop

This commit is contained in:
Pieter Vander Vennet 2024-09-17 02:55:01 +02:00
commit fec3608ca4
57 changed files with 1160 additions and 594 deletions

View file

@ -2,6 +2,22 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [0.46.9](https://github.com/USERNAME/REPOSITORY_NAME/compare/v0.46.8...v0.46.9) (2024-09-14)
### Bug Fixes
* fix [#2142](https://github.com/pietervdvn/MapComplete/issues/2142) ([f2fca2d](https://github.com/USERNAME/REPOSITORY_NAME/commitsf2fca2dad8576a18629591e886e511912c1d99e9))
* nobrand= is actually applied when using the Name suggestion index ([c3bb0cb](https://github.com/USERNAME/REPOSITORY_NAME/commitsc3bb0cb83787c299ee4a92e8df6046aa448d77c8))
* scroll horizontal images into view ([0397863](https://github.com/USERNAME/REPOSITORY_NAME/commits03978631ebd1e61abd13dd7a53bdb400c3d0f059))
* some fixes to make studio useable again, probably fixes [#2139](https://github.com/pietervdvn/MapComplete/issues/2139) ([6672fc8](https://github.com/USERNAME/REPOSITORY_NAME/commits6672fc87b4326db65289dfa31599ec0583d6c0f4))
### Theme improvements
* **disaster_respone:** add a police station layer, add this and more layers to disaster_response theme ([418a4a7](https://github.com/USERNAME/REPOSITORY_NAME/commits418a4a71af5824487e4aa6754701e5d14371beae))
* **disaster_response:** add defibrillators and logical zoom levels ([65fceb9](https://github.com/USERNAME/REPOSITORY_NAME/commits65fceb9434294051c8f565d89f42443c6afe3fb8))
### [0.46.8](https://github.com/USERNAME/REPOSITORY_NAME/compare/v0.46.7...v0.46.8) (2024-09-13)

View file

@ -21,7 +21,27 @@
"pl": "Miejsca kamperowe",
"zh_Hans": "露营地"
},
"minzoom": 7,
"description": {
"en": "camper sites",
"it": "Aree camper",
"ru": "площадки для кемпинга",
"ja": "キャンプサイト",
"fr": "campings",
"zh_Hant": "露營地",
"nl": "camperplaatsen",
"pt_BR": "Locais de acampamento",
"de": "Wohnmobilstellplätze",
"hu": "Lakóautós megállóhelyek",
"id": "Tempat camping",
"ca": "llocs d'acampada",
"es": "Sitios de acampada",
"da": "autocamperpladser",
"pa_PK": "کیمب‌سائیٹاں",
"cs": "kempovací místa",
"eu": "Kanpatzeko tokiak",
"pl": "miejsca dla kamperów",
"zh_Hans": "露营地"
},
"source": {
"osmTags": {
"and": [
@ -30,6 +50,7 @@
]
}
},
"minzoom": 7,
"title": {
"render": {
"en": "Camper site {name}",
@ -77,27 +98,89 @@
}
]
},
"description": {
"en": "camper sites",
"it": "Aree camper",
"ru": "площадки для кемпинга",
"ja": "キャンプサイト",
"fr": "campings",
"zh_Hant": "露營地",
"nl": "camperplaatsen",
"pt_BR": "Locais de acampamento",
"de": "Wohnmobilstellplätze",
"hu": "Lakóautós megállóhelyek",
"id": "Tempat camping",
"ca": "llocs d'acampada",
"es": "Sitios de acampada",
"da": "autocamperpladser",
"pa_PK": "کیمب‌سائیٹاں",
"cs": "kempovací místa",
"eu": "Kanpatzeko tokiak",
"pl": "miejsca dla kamperów",
"zh_Hans": "露营地"
},
"pointRendering": [
{
"marker": [
{
"icon": "circle",
"color": "white"
},
{
"icon": {
"render": "./assets/themes/campersite/caravan.svg",
"mappings": [
{
"if": {
"and": [
"fee=no"
]
},
"then": "./assets/themes/campersite/caravan_green.svg"
}
]
}
}
],
"iconSize": "40,40",
"location": [
"point",
"centroid"
],
"anchor": "center"
}
],
"lineRendering": [
{
"color": "#00f",
"width": "8"
}
],
"presets": [
{
"tags": [
"tourism=caravan_site"
],
"title": {
"en": "a camper site",
"ru": "площадка для кемпинга",
"ja": "キャンプサイト",
"zh_Hant": "露營地",
"it": "una luogo di campeggio",
"fr": "une aire de camping",
"pt_BR": "uma local de acampamento",
"de": "ein Wohnmobilstellplatz",
"nl": "een camperplaats",
"hu": "lakóautós megállóhely",
"ca": "un lloc d'acampada",
"es": "Un camping",
"da": "en autocamperplads",
"pa_PK": "اِک کیمپ‌سائیٹ",
"cs": "kempovací místa",
"eu": "Kanpin bat",
"pl": "miejsce dla kampera",
"pt": "uma local de acampamento",
"zh_Hans": "露营地"
},
"description": {
"en": "Add a new official camper site. These are designated places to stay overnight with your camper. They might look like a real camping or just look like a parking. They might not be signposted at all, but just be defined in a municipal decision. A regular parking intended for campers where it is not expected to spend the night, is -not- a camper site ",
"ru": "Добавьте новую официальную площадку для кемпинга. Это специально отведённые места для ночлега с автофургоном. Они могут выглядеть как настоящий кемпинг или просто выглядеть как парковка. Они не могут быть обозначены вообще, а просто быть определены в муниципальном решении. Обычная парковка, предназначенная для отдыхающих, где не ожидается, что они проведут ночь это -НЕ- площадка для кемпинга ",
"ja": "新しい公式キャンプサイトを追加します。お客様のキャンピングカーで一泊する指定の場所です。本物のキャンプのように見えるかもしれないし、単なる駐車場のように見えるかもしれない。それらは全く署名されていないかもしれませんが、自治体の決定で定義されているだけです。夜を過ごすことが予想されないキャンパー向けの通常の駐車場は、キャンプサイトではない ",
"it": "Aggiungi una nuova area di sosta ufficiale per camper. Si tratta di aree destinate alla sosta notturna dei camper. Potrebbe trattarsi di luoghi di campeggio o semplici parcheggi. Potrebbero anche non essere segnalati sul posto, ma semplicemente indicati in una delibera comunale. Un parcheggio destinato ai camper in cui non è però consentito trascorrere la notte -non- va considerato un'area di sosta per camper. ",
"fr": "Ajouter une nouvelle aire officielle pour campings-cars, destinée à y passer la nuit avec un camping-car. Elle ne nécessite pas dinfrastructures particulières et peut être simplement désignée sous arrêté municipal, un simple parking pour camping-cars non destiné au stationnement de nuit ne rentre pas dans cette catégorie ",
"de": "Fügen Sie einen neuen offiziellen Wohnmobilstellplatz hinzu. Dies sind ausgewiesene Plätze, an denen Sie in Ihrem Wohnmobil übernachten können. Sie können wie ein richtiger Campingplatz oder nur wie ein Parkplatz aussehen. Möglicherweise sind sie gar nicht ausgeschildert, sondern nur in einem Gemeindebeschluss festgelegt. Ein normaler Parkplatz für Wohnmobile, auf dem übernachten nicht zulässig ist, zählt nicht als Wohnmobilstellplatz. ",
"nl": "Voeg een nieuwe officiële camperplaats toe. Dit zijn speciaal aangeduide plaatsen waar het toegestaan is om te overnachten met een camper. Ze kunnen er uitzien als een parking, of soms eerder als een camping. Soms staan ze niet ter plaatse aangeduid, maar heeft de gemeente wel degelijk beslist dat dit een camperplaats is. Een parking voor campers waar je niet mag overnachten is géén camperplaats. ",
"zh_Hant": "新增正式露營地點,通常是設計給過夜的露營者的地點。看起來像是真的露營地或是一般的停車場,而且也許沒有任何指標,但在城鎮被定議地點。如果一般給露營者的停車場並不是用來過夜,則不是露營地點 ",
"hu": "Új hivatalos lakóautóhely hozzáadása. Ez arra vannak kijelölve, hogy lakóautóval ott éjszakázzunk. Lehet, hogy úgy néz ki, mint egy igazi kemping, de az is lehet, hogy csak olyan, mint egy parkoló. Előfordulhat, hogy egyáltalán nem jelzik őket, hanem csak egy önkormányzati határozatban vannak kijelölve. A lakóautósoknak szánt olyan hagyományos parkolók, ahol nem várhatóan nem fognak éjszakázni, -nem minősül- lakóautóhelynek. ",
"es": "Añade un nuevo sitio de acampada oficial. Son lugares designados para pasar la noche con tu caravana. Pueden parecerse a un camping real o simplemente a un aparcamiento. Puede que no estén señalizados en absoluto, sino que simplemente estén definidos en una decisión municipal. Un aparcamiento normal destinado a los campistas en el que no se espera que se pase la noche, no es un camping. ",
"ca": "Afig un nou lloc d'acampada oficial. Són llocs designats per a passar la nit amb la teua caravana. Poden semblar-se a un càmping real o simplement a un aparcament. Pot ser que no estiguen senyalitzats en absolut, sinó que simplement estiguen definits per una decisió municipal. Un aparcament normal destinat als acampadors en el qual no s'espera que es passe la nit, no és un càmping. ",
"da": "Tilføj en ny officiel campingplads. Disse er udpegede steder at overnatte med din autocamper. De kan ligne en rigtig campingplads eller bare ligne en parkeringsplads. De er måske slet ikke skiltet, men er blot defineret i en kommunal beslutning. En almindelig parkering beregnet til campister, hvor det ikke forventes at overnatte, er -ikke- en autocamperplads ",
"cs": "Přidejte nové oficiální kempovací místo. Jedná se o místa, určená pro přenocování s karavanem. Mohou vypadat jako skutečný kemp nebo jen jako parkoviště. Takováto místa nemusí být označena, ale stačí, pokud jsou pouze definována v rozhodnutí obce. Běžné parkoviště určené pro táborníky, kde se nepovažuje za kempovací místo. ",
"eu": "Kanpaleku ofizialeko beste leku bat gehitu du. Gaua zure karabanarekin igarotzeko lekuak dira. Benetako kanpin baten edo, besterik gabe, aparkaleku baten itxura izan dezakete. Baliteke ez egotea inola ere seinaleztatuta, baizik eta udal erabaki batean definitzea. Kanpinlarientzako aparkaleku arrunt bat ez da kanpin bat, gaua bertan pasatzea espero ez bada ere. ",
"pl": "Dodaj nowe oficjalne miejsce dla kamperów. Są to wyznaczone miejsca, w których można przenocować w swoim kamperze. Mogą wyglądać jak prawdziwy kemping lub po prostu wyglądać jak parking. Mogą one w ogóle nie być oznakowane, a jedynie określone w decyzji gminy. Zwykły parking przeznaczony dla kamperów, na którym nie przewiduje się nocowania, nie jest miejscem dla kamperów ",
"zh_Hans": "添加一个新的官方露营车场地。这些是专门设置的供露营车过夜的地点。它们可能看起来像真正的露营地,也可能只是看起来像一个停车场。它们可能没有任何标识,仅在市政决策中定义。普通的停车场,尽管可能供露营车使用,但不期望在其中过夜的,不算作露营车场地 "
}
}
],
"tagRenderings": [
"images",
{
@ -848,88 +931,5 @@
"questions",
"reviews"
],
"presets": [
{
"tags": [
"tourism=caravan_site"
],
"title": {
"en": "a camper site",
"ru": "площадка для кемпинга",
"ja": "キャンプサイト",
"zh_Hant": "露營地",
"it": "una luogo di campeggio",
"fr": "une aire de camping",
"pt_BR": "uma local de acampamento",
"de": "ein Wohnmobilstellplatz",
"nl": "een camperplaats",
"hu": "lakóautós megállóhely",
"ca": "un lloc d'acampada",
"es": "Un camping",
"da": "en autocamperplads",
"pa_PK": "اِک کیمپ‌سائیٹ",
"cs": "kempovací místa",
"eu": "Kanpin bat",
"pl": "miejsce dla kampera",
"pt": "uma local de acampamento",
"zh_Hans": "露营地"
},
"description": {
"en": "Add a new official camper site. These are designated places to stay overnight with your camper. They might look like a real camping or just look like a parking. They might not be signposted at all, but just be defined in a municipal decision. A regular parking intended for campers where it is not expected to spend the night, is -not- a camper site ",
"ru": "Добавьте новую официальную площадку для кемпинга. Это специально отведённые места для ночлега с автофургоном. Они могут выглядеть как настоящий кемпинг или просто выглядеть как парковка. Они не могут быть обозначены вообще, а просто быть определены в муниципальном решении. Обычная парковка, предназначенная для отдыхающих, где не ожидается, что они проведут ночь это -НЕ- площадка для кемпинга ",
"ja": "新しい公式キャンプサイトを追加します。お客様のキャンピングカーで一泊する指定の場所です。本物のキャンプのように見えるかもしれないし、単なる駐車場のように見えるかもしれない。それらは全く署名されていないかもしれませんが、自治体の決定で定義されているだけです。夜を過ごすことが予想されないキャンパー向けの通常の駐車場は、キャンプサイトではない ",
"it": "Aggiungi una nuova area di sosta ufficiale per camper. Si tratta di aree destinate alla sosta notturna dei camper. Potrebbe trattarsi di luoghi di campeggio o semplici parcheggi. Potrebbero anche non essere segnalati sul posto, ma semplicemente indicati in una delibera comunale. Un parcheggio destinato ai camper in cui non è però consentito trascorrere la notte -non- va considerato un'area di sosta per camper. ",
"fr": "Ajouter une nouvelle aire officielle pour campings-cars, destinée à y passer la nuit avec un camping-car. Elle ne nécessite pas dinfrastructures particulières et peut être simplement désignée sous arrêté municipal, un simple parking pour camping-cars non destiné au stationnement de nuit ne rentre pas dans cette catégorie ",
"de": "Fügen Sie einen neuen offiziellen Wohnmobilstellplatz hinzu. Dies sind ausgewiesene Plätze, an denen Sie in Ihrem Wohnmobil übernachten können. Sie können wie ein richtiger Campingplatz oder nur wie ein Parkplatz aussehen. Möglicherweise sind sie gar nicht ausgeschildert, sondern nur in einem Gemeindebeschluss festgelegt. Ein normaler Parkplatz für Wohnmobile, auf dem übernachten nicht zulässig ist, zählt nicht als Wohnmobilstellplatz. ",
"nl": "Voeg een nieuwe officiële camperplaats toe. Dit zijn speciaal aangeduide plaatsen waar het toegestaan is om te overnachten met een camper. Ze kunnen er uitzien als een parking, of soms eerder als een camping. Soms staan ze niet ter plaatse aangeduid, maar heeft de gemeente wel degelijk beslist dat dit een camperplaats is. Een parking voor campers waar je niet mag overnachten is géén camperplaats. ",
"zh_Hant": "新增正式露營地點,通常是設計給過夜的露營者的地點。看起來像是真的露營地或是一般的停車場,而且也許沒有任何指標,但在城鎮被定議地點。如果一般給露營者的停車場並不是用來過夜,則不是露營地點 ",
"hu": "Új hivatalos lakóautóhely hozzáadása. Ez arra vannak kijelölve, hogy lakóautóval ott éjszakázzunk. Lehet, hogy úgy néz ki, mint egy igazi kemping, de az is lehet, hogy csak olyan, mint egy parkoló. Előfordulhat, hogy egyáltalán nem jelzik őket, hanem csak egy önkormányzati határozatban vannak kijelölve. A lakóautósoknak szánt olyan hagyományos parkolók, ahol nem várhatóan nem fognak éjszakázni, -nem minősül- lakóautóhelynek. ",
"es": "Añade un nuevo sitio de acampada oficial. Son lugares designados para pasar la noche con tu caravana. Pueden parecerse a un camping real o simplemente a un aparcamiento. Puede que no estén señalizados en absoluto, sino que simplemente estén definidos en una decisión municipal. Un aparcamiento normal destinado a los campistas en el que no se espera que se pase la noche, no es un camping. ",
"ca": "Afig un nou lloc d'acampada oficial. Són llocs designats per a passar la nit amb la teua caravana. Poden semblar-se a un càmping real o simplement a un aparcament. Pot ser que no estiguen senyalitzats en absolut, sinó que simplement estiguen definits per una decisió municipal. Un aparcament normal destinat als acampadors en el qual no s'espera que es passe la nit, no és un càmping. ",
"da": "Tilføj en ny officiel campingplads. Disse er udpegede steder at overnatte med din autocamper. De kan ligne en rigtig campingplads eller bare ligne en parkeringsplads. De er måske slet ikke skiltet, men er blot defineret i en kommunal beslutning. En almindelig parkering beregnet til campister, hvor det ikke forventes at overnatte, er -ikke- en autocamperplads ",
"cs": "Přidejte nové oficiální kempovací místo. Jedná se o místa, určená pro přenocování s karavanem. Mohou vypadat jako skutečný kemp nebo jen jako parkoviště. Takováto místa nemusí být označena, ale stačí, pokud jsou pouze definována v rozhodnutí obce. Běžné parkoviště určené pro táborníky, kde se nepovažuje za kempovací místo. ",
"eu": "Kanpaleku ofizialeko beste leku bat gehitu du. Gaua zure karabanarekin igarotzeko lekuak dira. Benetako kanpin baten edo, besterik gabe, aparkaleku baten itxura izan dezakete. Baliteke ez egotea inola ere seinaleztatuta, baizik eta udal erabaki batean definitzea. Kanpinlarientzako aparkaleku arrunt bat ez da kanpin bat, gaua bertan pasatzea espero ez bada ere. ",
"pl": "Dodaj nowe oficjalne miejsce dla kamperów. Są to wyznaczone miejsca, w których można przenocować w swoim kamperze. Mogą wyglądać jak prawdziwy kemping lub po prostu wyglądać jak parking. Mogą one w ogóle nie być oznakowane, a jedynie określone w decyzji gminy. Zwykły parking przeznaczony dla kamperów, na którym nie przewiduje się nocowania, nie jest miejscem dla kamperów ",
"zh_Hans": "添加一个新的官方露营车场地。这些是专门设置的供露营车过夜的地点。它们可能看起来像真正的露营地,也可能只是看起来像一个停车场。它们可能没有任何标识,仅在市政决策中定义。普通的停车场,尽管可能供露营车使用,但不期望在其中过夜的,不算作露营车场地 "
}
}
],
"pointRendering": [
{
"marker": [
{
"icon": "circle",
"color": "white"
},
{
"icon": {
"render": "./assets/themes/campersite/caravan.svg",
"mappings": [
{
"if": {
"and": [
"fee=no"
]
},
"then": "./assets/themes/campersite/caravan_green.svg"
}
]
}
}
],
"iconSize": "40,40",
"location": [
"point",
"centroid"
],
"anchor": "center"
}
],
"lineRendering": [
{
"color": "#00f",
"width": "8"
}
],
"allowMove": true
}

View file

@ -5,7 +5,13 @@
"nl": "Oplaadpunten",
"de": "Ladestationen"
},
"minzoom": 10,
"description": {
"en": "A charging station",
"nl": "Oplaadpunten",
"ca": "Una estació de càrrega",
"de": "Eine Ladestation",
"fr": "Une station de recharge"
},
"source": {
"osmTags": {
"and": [
@ -20,6 +26,7 @@
]
}
},
"minzoom": 10,
"title": {
"render": {
"en": "Charging station",
@ -65,14 +72,109 @@
}
]
},
"description": {
"en": "A charging station",
"nl": "Oplaadpunten",
"ca": "Una estació de càrrega",
"de": "Eine Ladestation",
"fr": "Une station de recharge"
},
"#": "no-question-hint-check",
"pointRendering": [
{
"location": [
"point",
"centroid"
],
"marker": [
{
"icon": "pin",
"color": "#fff"
},
{
"icon": {
"render": "./assets/themes/charging_stations/plug.svg",
"mappings": [
{
"if": "bicycle=yes",
"then": "./assets/themes/charging_stations/bicycle.svg"
},
{
"if": {
"or": [
"car=yes",
"motorcar=yes"
]
},
"then": "./assets/themes/charging_stations/car.svg"
}
]
}
}
],
"iconBadges": [
{
"if": {
"or": [
"disused:amenity=charging_station",
"operational_status=broken"
]
},
"then": "close:#c22;"
},
{
"if": {
"or": [
"proposed:amenity=charging_station",
"planned:amenity=charging_station"
]
},
"then": "./assets/layers/charging_station/under_construction.svg"
},
{
"if": {
"and": [
"bicycle=yes",
{
"or": [
"motorcar=yes",
"car=yes"
]
}
]
},
"then": "circle:#fff;./assets/themes/charging_stations/car.svg"
}
],
"anchor": "bottom",
"iconSize": "50,50"
}
],
"lineRendering": [
{
"color": "black",
"width": 2,
"fillColor": "#80808080"
}
],
"presets": [
{
"tags": [
"amenity=charging_station",
"motorcar=no",
"bicycle=yes"
],
"title": {
"en": "charging station for electrical bikes",
"nl": "oplaadpunt voor elektrische fietsen",
"de": "Ladestation für Elektrofahrräder"
}
},
{
"tags": [
"amenity=charging_station",
"motorcar=yes",
"bicycle=no"
],
"title": {
"en": "charging station for cars",
"nl": "oplaadstation voor elektrische auto's",
"de": "Ladestation für Autos"
}
}
],
"tagRenderings": [
"images",
{
@ -2778,109 +2880,6 @@
}
}
],
"lineRendering": [
{
"color": "black",
"width": 2,
"fillColor": "#80808080"
}
],
"pointRendering": [
{
"location": [
"point",
"centroid"
],
"marker": [
{
"icon": "pin",
"color": "#fff"
},
{
"icon": {
"render": "./assets/themes/charging_stations/plug.svg",
"mappings": [
{
"if": "bicycle=yes",
"then": "./assets/themes/charging_stations/bicycle.svg"
},
{
"if": {
"or": [
"car=yes",
"motorcar=yes"
]
},
"then": "./assets/themes/charging_stations/car.svg"
}
]
}
}
],
"iconBadges": [
{
"if": {
"or": [
"disused:amenity=charging_station",
"operational_status=broken"
]
},
"then": "close:#c22;"
},
{
"if": {
"or": [
"proposed:amenity=charging_station",
"planned:amenity=charging_station"
]
},
"then": "./assets/layers/charging_station/under_construction.svg"
},
{
"if": {
"and": [
"bicycle=yes",
{
"or": [
"motorcar=yes",
"car=yes"
]
}
]
},
"then": "circle:#fff;./assets/themes/charging_stations/car.svg"
}
],
"anchor": "bottom",
"iconSize": "50,50"
}
],
"presets": [
{
"tags": [
"amenity=charging_station",
"motorcar=no",
"bicycle=yes"
],
"title": {
"en": "charging station for electrical bikes",
"nl": "oplaadpunt voor elektrische fietsen",
"de": "Ladestation für Elektrofahrräder"
}
},
{
"tags": [
"amenity=charging_station",
"motorcar=yes",
"bicycle=no"
],
"title": {
"en": "charging station for cars",
"nl": "oplaadstation voor elektrische auto's",
"de": "Ladestation für Autos"
}
}
],
"filter": [
{
"id": "vehicle-type",
@ -3128,6 +3127,19 @@
]
}
],
"deletion": {
"softDeletionTags": {
"and": [
"amenity=",
"disused:amenity=charging_station"
]
},
"neededChangesets": 10
},
"allowMove": {
"enableRelocation": false,
"enableImproveAccuracy": true
},
"units": [
{
"maxstay": {
@ -3322,17 +3334,5 @@
}
}
],
"allowMove": {
"enableRelocation": false,
"enableImproveAccuracy": true
},
"deletion": {
"softDeletionTags": {
"and": [
"amenity=",
"disused:amenity=charging_station"
]
},
"neededChangesets": 10
}
}
"#": "no-question-hint-check"
}

View file

@ -34,9 +34,6 @@
]
}
},
"snapName": {
"en": "a wall, cliff or rock"
},
"minzoom": 18,
"title": {
"render": {
@ -152,5 +149,8 @@
}
],
"allowMove": false,
"snapName": {
"en": "a wall, cliff or rock"
},
"doCount": false
}

View file

@ -9,10 +9,6 @@
"ca": "Vies ciclistes i carreteres",
"cs": "Cyklostezky a silnice"
},
"snapName": {
"en": "a road or a cycleway",
"nl": "een weg, straat of fietspad"
},
"description": {
"en": "All infrastructure that someone can cycle over, accompanied with questions about this infrastructure",
"nl": "Alle infrastructuur waar je over kunt fietsen, met vragen over die infrastructuur",
@ -1917,5 +1913,9 @@
}
],
"allowMove": false,
"allowSplit": true
"allowSplit": true,
"snapName": {
"en": "a road or a cycleway",
"nl": "een weg, straat of fietspad"
}
}

View file

@ -18,7 +18,24 @@
"pl": "Stacje zrzutów sanitarnych",
"pt": "Estações de despejo sanitário"
},
"minzoom": 7,
"description": {
"en": "Sanitary dump stations",
"ru": "Ассенизационные сливные станции",
"ja": "衛生ゴミ捨て場",
"it": "Luoghi di sversamento delle acque reflue",
"fr": "Site de vidange sanitaire",
"pt_BR": "Estações de despejo sanitário",
"de": "Sanitäre Entsorgungsstationen",
"zh_Hant": "垃圾處理站",
"id": "Tempat pembuangan sanitasi",
"nl": "Loosplaatsen",
"ca": "Estacions d'abocament sanitari",
"da": "Sanitære afleveringspladser",
"cs": "Sanitární skládky",
"es": "Vertederos Sanitarios",
"pl": "Stacje zrzutów sanitarnych",
"pt": "Estações de despejo sanitário"
},
"source": {
"osmTags": {
"and": [
@ -27,6 +44,7 @@
]
}
},
"minzoom": 7,
"title": {
"render": {
"en": "Dump station {name}",
@ -70,24 +88,66 @@
}
]
},
"description": {
"en": "Sanitary dump stations",
"ru": "Ассенизационные сливные станции",
"ja": "衛生ゴミ捨て場",
"it": "Luoghi di sversamento delle acque reflue",
"fr": "Site de vidange sanitaire",
"pt_BR": "Estações de despejo sanitário",
"de": "Sanitäre Entsorgungsstationen",
"zh_Hant": "垃圾處理站",
"id": "Tempat pembuangan sanitasi",
"nl": "Loosplaatsen",
"ca": "Estacions d'abocament sanitari",
"da": "Sanitære afleveringspladser",
"cs": "Sanitární skládky",
"es": "Vertederos Sanitarios",
"pl": "Stacje zrzutów sanitarnych",
"pt": "Estações de despejo sanitário"
},
"pointRendering": [
{
"marker": [
{
"icon": "circle",
"color": "white"
},
{
"icon": "./assets/themes/campersite/sanitary_dump_station.svg"
}
],
"iconSize": "32,32",
"location": [
"point"
],
"anchor": "center"
}
],
"lineRendering": [
{
"color": "#00f",
"width": "8"
}
],
"presets": [
{
"tags": [
"amenity=sanitary_dump_station"
],
"title": {
"en": "a sanitary dump station",
"ja": "衛生ゴミ捨て場",
"it": "una luogo di sversamento delle acque reflue",
"fr": "une site de vidange",
"de": "eine sanitäre Entsorgungsstation",
"zh_Hant": "垃圾丟棄站",
"nl": "een loosplaats",
"da": "en sanitær afleveringsplads",
"ca": "una estació d'abocament sanitari",
"cs": "sanitární skládka",
"es": "un vertedero sanitario",
"pl": "stacja zrzutu sanitarnego"
},
"description": {
"en": "Add a new sanitary dump station. This is a place where camper drivers can dump waste water or chemical toilet waste. Often there's also drinking water and electricity.",
"ja": "新しい衛生ゴミ捨て場を追加します。ここは、キャンピングカーの運転手が排水や携帯トイレの廃棄物を捨てることができる場所です。飲料水や電気もあることが多いです。",
"it": "Aggiungi un nuovo luogo di sversamento delle acque reflue. Si tratta di luoghi dove chi viaggia in camper può smaltire le acque grigie o le acque nere. Spesso forniscono anche acqua ed elettricità.",
"fr": "Ajouter un nouveau site de vidange. Un espace où évacuer ses eaux usées (grises et/ou noires). Généralement alimenté en eau potable et électricité.",
"de": "Fügen Sie eine neue sanitäre Entsorgungsstation hinzu. Hier können Camper Abwasser oder chemischen Toilettenabfälle entsorgen. Oft gibt es auch Trinkwasser und Strom.",
"zh_Hant": "新增垃圾站,這通常是提供露營駕駛丟棄廢水與化學性廁所廢水的地方,也會有飲用水與電力。",
"hu": "Új egészségügyihulldék-lerakó hozzáadása. Ez egy olyan hely, ahol a lakókocsisok a szennyvizet vagy a vegyi WC hulladékát kiüríthetik. Gyakran van ivóvíz és áram is.",
"nl": "Voeg een nieuwe loosplaats toe. Dat is een plaats waar campers hun grijs water en toiletten kunnen lozen. Vaak is er ook een kraan om water te tanken en een stopcontact.",
"da": "Tilføj en ny sanitær afleveringsplads. Dette er et sted, hvor autocamperchauffører kan dumpe spildevand eller kemisk toiletaffald. Ofte er der også drikkevand og el.",
"cs": "Přidejte novou sanitární skládku. Toto je místo, kam mohou řidiči obytných vozů vypouštět odpadní vodu nebo odpad z chemických toalet. Často je zde také dostupná pitná voda a elektřina.",
"es": "Añadir un nuevo vertedero sanitario. Se trata de un lugar donde los autocaravanistas pueden verter las aguas residuales o los residuos químicos de los aseos. A menudo también hay agua potable y electricidad.",
"ca": "Afegir una nova estació d'abocador sanitari. Aquest és un lloc on els conductors de campers poden abocar aigües residuals o residus de vàter químic. Sovint també hi ha aigua potable i electricitat.",
"pl": "Dodaj nową stację zrzutu sanitarnego. To miejsce, w którym kierowcy kamperów mogą wyrzucać ścieki lub odpady z toalet chemicznych. Często jest tam też woda pitna i prąd."
}
}
],
"tagRenderings": [
"images",
{
@ -569,66 +629,6 @@
"id": "dumpstations-network"
}
],
"presets": [
{
"tags": [
"amenity=sanitary_dump_station"
],
"title": {
"en": "a sanitary dump station",
"ja": "衛生ゴミ捨て場",
"it": "una luogo di sversamento delle acque reflue",
"fr": "une site de vidange",
"de": "eine sanitäre Entsorgungsstation",
"zh_Hant": "垃圾丟棄站",
"nl": "een loosplaats",
"da": "en sanitær afleveringsplads",
"ca": "una estació d'abocament sanitari",
"cs": "sanitární skládka",
"es": "un vertedero sanitario",
"pl": "stacja zrzutu sanitarnego"
},
"description": {
"en": "Add a new sanitary dump station. This is a place where camper drivers can dump waste water or chemical toilet waste. Often there's also drinking water and electricity.",
"ja": "新しい衛生ゴミ捨て場を追加します。ここは、キャンピングカーの運転手が排水や携帯トイレの廃棄物を捨てることができる場所です。飲料水や電気もあることが多いです。",
"it": "Aggiungi un nuovo luogo di sversamento delle acque reflue. Si tratta di luoghi dove chi viaggia in camper può smaltire le acque grigie o le acque nere. Spesso forniscono anche acqua ed elettricità.",
"fr": "Ajouter un nouveau site de vidange. Un espace où évacuer ses eaux usées (grises et/ou noires). Généralement alimenté en eau potable et électricité.",
"de": "Fügen Sie eine neue sanitäre Entsorgungsstation hinzu. Hier können Camper Abwasser oder chemischen Toilettenabfälle entsorgen. Oft gibt es auch Trinkwasser und Strom.",
"zh_Hant": "新增垃圾站,這通常是提供露營駕駛丟棄廢水與化學性廁所廢水的地方,也會有飲用水與電力。",
"hu": "Új egészségügyihulldék-lerakó hozzáadása. Ez egy olyan hely, ahol a lakókocsisok a szennyvizet vagy a vegyi WC hulladékát kiüríthetik. Gyakran van ivóvíz és áram is.",
"nl": "Voeg een nieuwe loosplaats toe. Dat is een plaats waar campers hun grijs water en toiletten kunnen lozen. Vaak is er ook een kraan om water te tanken en een stopcontact.",
"da": "Tilføj en ny sanitær afleveringsplads. Dette er et sted, hvor autocamperchauffører kan dumpe spildevand eller kemisk toiletaffald. Ofte er der også drikkevand og el.",
"cs": "Přidejte novou sanitární skládku. Toto je místo, kam mohou řidiči obytných vozů vypouštět odpadní vodu nebo odpad z chemických toalet. Často je zde také dostupná pitná voda a elektřina.",
"es": "Añadir un nuevo vertedero sanitario. Se trata de un lugar donde los autocaravanistas pueden verter las aguas residuales o los residuos químicos de los aseos. A menudo también hay agua potable y electricidad.",
"ca": "Afegir una nova estació d'abocador sanitari. Aquest és un lloc on els conductors de campers poden abocar aigües residuals o residus de vàter químic. Sovint també hi ha aigua potable i electricitat.",
"pl": "Dodaj nową stację zrzutu sanitarnego. To miejsce, w którym kierowcy kamperów mogą wyrzucać ścieki lub odpady z toalet chemicznych. Często jest tam też woda pitna i prąd."
}
}
],
"pointRendering": [
{
"marker": [
{
"icon": "circle",
"color": "white"
},
{
"icon": "./assets/themes/campersite/sanitary_dump_station.svg"
}
],
"iconSize": "32,32",
"location": [
"point"
],
"anchor": "center"
}
],
"lineRendering": [
{
"color": "#00f",
"width": "8"
}
],
"allowMove": {
"enableImproveAccuracy": true,
"enableRelocation": false

View file

@ -1,8 +1,7 @@
{
"id": "geocoded_image",
"source": "special",
"name": null,
"tagRenderings": [],
"source": "special",
"pointRendering": [
{
"location": [
@ -66,5 +65,6 @@
],
"iconSize": "14,14"
}
]
],
"tagRenderings": []
}

View file

@ -8,10 +8,6 @@
"ca": "Interiors",
"cs": "Vnitřní prostory"
},
"snapName": {
"en": "an indoor wall",
"nl": "een binnenmuur"
},
"description": {
"en": "Basic indoor mapping: shows room outlines",
"de": "Grundlegende Innenraumkartierung: zeigt Umrisse von Räumen",
@ -623,5 +619,9 @@
"allowMove": {
"enableImproveAccuracy": true,
"enableRelocation": false
},
"snapName": {
"en": "an indoor wall",
"nl": "een binnenmuur"
}
}

View file

@ -11,9 +11,6 @@
"ca": "Vroades",
"cs": "Obrubníky"
},
"snapName": {
"en": "a kerb"
},
"description": {
"en": "A layer showing kerbs.",
"nl": "Een laag met stoepranden.",
@ -409,5 +406,8 @@
]
}
}
]
],
"snapName": {
"en": "a kerb"
}
}

View file

@ -291,6 +291,23 @@
}
]
},
{
"id": "search_not_any",
"options": [
{
"osmTags": "_all_comments!~i~.*{search}.*",
"fields": [
{
"name": "search"
}
],
"question": {
"en": "Should <b>not</b> mention {search} in <b>any</b> comment"
}
}
]
},
{
"id": "opened_by",
"options": [

View file

@ -8,9 +8,6 @@
"ca": "Camins per a vianants",
"cs": "Cesty pro chodce"
},
"snapName": {
"en": "a pedestrian path"
},
"description": {
"en": "Pedestrian footpaths, especially used for indoor navigation and snapping entrances to this layer",
"nl": "Pad voor voetgangers, in het bijzonder gebruikt voor navigatie binnen gebouwen en om aan toegangen vast te klikken in deze laag",
@ -49,5 +46,8 @@
"dashArray": "12 6"
}
],
"allowMove": false
"allowMove": false,
"snapName": {
"en": "a pedestrian path"
}
}

View file

@ -0,0 +1,12 @@
[
{
"path": "police.svg",
"license": "CC-BY 4.0",
"authors": [
"Twemoji"
],
"sources": [
"https://commons.wikimedia.org/wiki/File:Twemoji12_1f693.svg"
]
}
]

View file

@ -0,0 +1,142 @@
{
"id": "police",
"name": {
"en": "Police stations"
},
"description": {
"en": "Many types of police facilities "
},
"source": {
"osmTags": {
"or": [
"amenity=police",
"police~*"
]
}
},
"minzoom": 10,
"title": {
"render": {
"en": "{name}"
}
},
"pointRendering": [
{
"location": [
"point",
"centroid"
],
"marker": [
{
"icon": "circle",
"color": "#00000000"
},
{
"icon": "./assets/layers/police/police.svg"
}
]
}
],
"lineRendering": [
{
"width": 1,
"color": "blue"
}
],
"presets": [
{
"tags": [
"amenity=police"
],
"title": {
"en": "a police office"
},
"description": {
"en": "A police office where the general public can enter for inquiries"
}
},
{
"tags": [
"police=checkpoint"
],
"title": {
"en": "a police checkpoint"
},
"description": {
"en": "A place where police performs checks on travelling people"
}
},
{
"tags": [
"police=offices"
],
"title": {
"en": "an administrative, police backoffice"
},
"description": {
"en": "An administrative police office without services for the general public."
}
},
{
"tags": [
"police=detention"
],
"title": "a police detention center",
"description": {
"en": "A jail run by the police without public services. People are detained here for a short time (at most a few days), e.g. for small misdemeanors, disturbance of the public order or awaiting a trial"
}
},
{
"tags": [
"police=naval_base"
],
"title": "a police naval base",
"description": {
"en": "A naval or maritime base for the maritime police; often with a pier and police boats nearby"
}
}
],
"tagRenderings": [
"images",
"reviews",
{
"question": {
"en": "What is the name of this police facility?"
},
"id": "police_name",
"render": {
"en": "<b>{name}</b>"
},
"freeform": {
"key": "name"
}
},
"{preset_type_select()}",
"contact",
"opening_hours",
{
"question": {
"en": "Does this police office have detention facilities?"
},
"id": "4_z2nrdhy6tyyh4fd",
"condition": "amenity=police",
"mappings": [
{
"if": "detention=yes",
"then": {
"en": "This police office has some cells to detain people"
}
},
{
"if": "detention=no",
"then": {
"en": "This police office does not have cells to detain people"
}
}
]
}
],
"deletion": true,
"allowMove": true,
"enableMorePrivacy": true
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#E1E8ED" d="M32 22s-2-8-5-8H16c-3 0-7 7-7 7s-8 1-8 5v2c0 .09.021.175.026.263C.417 28.605 0 29.251 0 30c0 1.104.896 2 2 2h30c2.209 0 4-1.791 4-4v-2c0-2.209-1.791-4-4-4z"/><path fill="#292F33" d="M1 26v2c0 .09.021.175.026.263C.417 28.605 0 29.251 0 30c0 1.104.896 2 2 2h30c2.209 0 4-1.791 4-4v-2c0-.348-.059-.679-.142-1H1.201c-.117.312-.201.641-.201 1z"/><path fill="#66757F" d="M15.91 32c.055-.326.09-.658.09-1 0-3.313-2.686-6-6-6-3.313 0-6 2.687-6 6 0 .342.035.674.09 1h11.82zm17 0c.055-.326.09-.658.09-1 0-3.313-2.687-6-6-6s-6 2.687-6 6c0 .342.035.674.09 1h11.82z"/><circle fill="#292F33" cx="10" cy="31" r="4"/><circle fill="#E1E8ED" cx="10" cy="31" r="2"/><circle fill="#292F33" cx="27" cy="31" r="4"/><circle fill="#E1E8ED" cx="27" cy="31" r="2"/><path fill="#DD2E44" d="M21 13c0 .552-.447 1-1 1h-3c-.552 0-1-.448-1-1s.448-1 1-1h3c.553 0 1 .448 1 1z"/><path fill="#55ACEE" d="M22 13c0 .552-.447 1-1 1h-2c-.552 0-1-.448-1-1s.448-1 1-1h2c.553 0 1 .448 1 1zm1 8h7s-2-5-3-5h-4v5zm-2-5h-5c-2 0-5 5-5 5h10v-5z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,2 @@
SPDX-FileCopyrightText: Twemoji
SPDX-License-Identifier: CC-BY 4.0

View file

@ -1380,6 +1380,17 @@
],
"filter": [
"open_now",
{
"id": "centres_only",
"options": [
{
"osmTags": "recycling_type=centre",
"question": {
"en": "Recycling centre"
}
}
]
},
{
"id": "recyclingType",
"options": [

View file

@ -8,9 +8,6 @@
"fr": "Abri",
"cs": "Přístřešek"
},
"snapName": {
"en": "a shelter"
},
"description": {
"en": "Layer showing shelter structures",
"de": "Eine Ebene, die verschiedene Bauformen von Unterständen zeigt",
@ -128,5 +125,8 @@
"allowMove": {
"enableRelocation": false,
"enableImproveAccuracy": true
},
"snapName": {
"en": "a shelter"
}
}

View file

@ -12,10 +12,6 @@
"zh_Hant": "特殊的內建圖層顯示所有牆壁與建築。這個圖層對於規畫要靠牆的東西 (例如 AED、郵筒、入口、地址、監視器等) 相當實用。這個圖層預設顯示而且無法由使用者開關。",
"pl": "Specjalna warstwa zabudowana zapewniająca wszystkie mury i budynki. Warstwa ta jest przydatna w ustawieniach wstępnych obiektów, które można umieścić przy ścianach (np. AED, skrzynki pocztowe, wejścia, adresy, kamery monitorujące itp.). Warstwa ta jest domyślnie niewidoczna i użytkownik nie może jej przełączać."
},
"snapName": {
"en": "a wall or building",
"nl": "een muur of gebouw"
},
"source": {
"osmTags": {
"or": [
@ -144,5 +140,9 @@
]
}
}
]
],
"snapName": {
"en": "a wall or building",
"nl": "een muur of gebouw"
}
}

View file

@ -17,9 +17,38 @@
"icon": "./assets/themes/disaster_response/CivilDefence.svg",
"socialImage": "./assets/themes/disaster_response/social.svg",
"layers": [
"hospital",
"assembly_point",
"disaster_response"
{
"builtin": [
"hospital",
"fire_station",
"disaster_response",
"police"
],
"override": {
"minzoom": 6
}
},
{
"builtin": [
"extinguisher",
"assembly_point",
"defibrillator",
"hydrant"
],
"override": {
"minzoom": 15
}
},
{
"builtin": [
"doctors",
"ambulancestation",
"pharmacy"
],
"override": {
"minzoom": 14
}
}
],
"docs": "https://wiki.openstreetmap.org/wiki/Emergency_facilities_and_amenities"
}
}

View file

@ -1,13 +1,18 @@
{
"id": "mapcomplete-changes",
"title": {
"en": "Changes made with MapComplete"
"en": "Changes made with MapComplete",
"de": "Änderungen mit MapComplete"
},
"shortDescription": {
"en": "Shows changes made by MapComplete"
"en": "Shows changes made by MapComplete",
"de": "Zeigt die von MapComplete vorgenommenen Änderungen an"
},
"description": {
"en": "This maps shows all the changes made with MapComplete"
"en": "This maps shows all the changes made with MapComplete",
"de": "Diese Karte zeigt alle mit MapComplete vorgenommenen Änderungen",
"es": "Este mapa muestra todos los cambios realizados con MapComplete",
"pl": "Ta mapa pokazuje wszystkie zmiany wprowadzone za pomocą MapComplete"
},
"icon": "./assets/svg/logo.svg",
"hideFromOverview": true,
@ -18,7 +23,8 @@
{
"id": "mapcomplete-changes",
"name": {
"en": "Changeset centers"
"en": "Changeset centers",
"de": "Changeset-Zentren"
},
"minzoom": 0,
"source": {
@ -28,41 +34,49 @@
},
"title": {
"render": {
"en": "Changeset for {theme}"
"en": "Changeset for {theme}",
"de": "Änderungssatz für {theme}"
}
},
"description": {
"en": "Shows all MapComplete changes"
"en": "Shows all MapComplete changes",
"de": "Zeigt alle MapComplete-Änderungen",
"es": "Muestra todos los cambios de MapComplete"
},
"tagRenderings": [
{
"id": "show_changeset_id",
"render": {
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>",
"de": "Änderungssatz <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
}
},
{
"id": "contributor",
"question": {
"en": "What contributor did make this change?"
"en": "What contributor did make this change?",
"de": "Wer hat zu dieser Änderung beigetragen?"
},
"freeform": {
"key": "user"
},
"render": {
"en": "Change made by <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>"
"en": "Change made by <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>",
"de": "Änderung vorgenommen von <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>"
}
},
{
"id": "theme-id",
"question": {
"en": "What theme was used to make this change?"
"en": "What theme was used to make this change?",
"de": "Welches Thema wurde für diese Änderung verwendet?"
},
"freeform": {
"key": "theme"
},
"render": {
"en": "Change with theme <a href='https://mapcomplete.org/{theme}'>{theme}</a>"
"en": "Change with theme <a href='https://mapcomplete.org/{theme}'>{theme}</a>",
"de": "Änderung mit Thema <a href='https://mapcomplete.org/{theme}'>{theme}</a>"
}
},
{
@ -71,19 +85,23 @@
"key": "locale"
},
"question": {
"en": "What locale (language) was this change made in?"
"en": "What locale (language) was this change made in?",
"de": "In welcher Sprache (Locale) wurde diese Änderung vorgenommen?"
},
"render": {
"en": "User locale is {locale}"
"en": "User locale is {locale}",
"de": "Die Benutzersprache ist {locale}"
}
},
{
"id": "host",
"render": {
"en": "Change with with <a href='{host}'>{host}</a>"
"en": "Change with with <a href='{host}'>{host}</a>",
"de": "Änderung mit <a href='{host}'>{host}</a>"
},
"question": {
"en": "What host (website) was this change made with?"
"en": "What host (website) was this change made with?",
"de": "Bei welchem Host (Website) wurde diese Änderung vorgenommen?"
},
"freeform": {
"key": "host"
@ -104,10 +122,12 @@
{
"id": "version",
"question": {
"en": "What version of MapComplete was used to make this change?"
"en": "What version of MapComplete was used to make this change?",
"de": "Welche Version von MapComplete wurde verwendet, um diese Änderung vorzunehmen?"
},
"render": {
"en": "Made with {editor}"
"en": "Made with {editor}",
"de": "Erstellt mit {editor}"
},
"freeform": {
"key": "editor"
@ -505,7 +525,10 @@
}
],
"question": {
"en": "Themename contains {search}"
"en": "Themename contains {search}",
"de": "Themenname enthält {search}",
"es": "El nombre contiene {search}",
"pl": "Nazwa tematu zawiera {search}"
}
}
]
@ -521,7 +544,9 @@
}
],
"question": {
"en": "Themename does <b>not</b> contain {search}"
"en": "Themename does <b>not</b> contain {search}",
"de": "Themename enthält <b>nicht</b> {search}",
"es": "El nombre del tema <b>no</b> contiene {search}"
}
}
]
@ -537,7 +562,9 @@
}
],
"question": {
"en": "Made by contributor {search}"
"en": "Made by contributor {search}",
"de": "Erstellt von Mitwirkendem {search}",
"es": "Hecho por el colaborador {search}"
}
}
]
@ -553,7 +580,9 @@
}
],
"question": {
"en": "<b>Not</b> made by contributor {search}"
"en": "<b>Not</b> made by contributor {search}",
"de": "<b>Nicht</b> erstellt von Mitwirkendem {search}",
"es": "<b>No</b> realizado por el colaborador {search}"
}
}
]
@ -570,7 +599,9 @@
}
],
"question": {
"en": "Made before {search}"
"en": "Made before {search}",
"de": "Erstellt vor {search}",
"es": "Realizado antes de {search}"
}
}
]
@ -587,7 +618,9 @@
}
],
"question": {
"en": "Made after {search}"
"en": "Made after {search}",
"de": "Erstellt nach {search}",
"es": "Realizado después de {search}"
}
}
]
@ -603,7 +636,9 @@
}
],
"question": {
"en": "User language (iso-code) {search}"
"en": "User language (iso-code) {search}",
"de": "Benutzersprache (ISO-Code) {search}",
"es": "Idioma del usuario (código iso) {search}"
}
}
]
@ -619,7 +654,8 @@
}
],
"question": {
"en": "Made with host {search}"
"en": "Made with host {search}",
"de": "Erstellt mit Host {search}"
}
}
]
@ -630,7 +666,8 @@
{
"osmTags": "add-image>0",
"question": {
"en": "Changeset added at least one image"
"en": "Changeset added at least one image",
"de": "Changeset hat mindestens ein Bild hinzugefügt"
}
}
]
@ -641,7 +678,8 @@
{
"osmTags": "theme!=grb",
"question": {
"en": "Exclude GRB theme"
"en": "Exclude GRB theme",
"de": "GRB-Thema ausschließen"
}
}
]
@ -652,7 +690,9 @@
{
"osmTags": "theme!=etymology",
"question": {
"en": "Exclude etymology theme"
"en": "Exclude etymology theme",
"de": "Etymologie-Thema ausschließen",
"es": "Excluir el tema de la etimología"
}
}
]
@ -667,7 +707,8 @@
{
"id": "link_to_more",
"render": {
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>"
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>",
"de": "Weitere Statistiken findest du <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>hier</a>"
}
},
{

View file

@ -1,13 +1,18 @@
{
"id": "mapcomplete-changes",
"title": {
"en": "Changes made with MapComplete"
"en": "Changes made with MapComplete",
"de": "Änderungen mit MapComplete"
},
"shortDescription": {
"en": "Shows changes made by MapComplete"
"en": "Shows changes made by MapComplete",
"de": "Zeigt die von MapComplete vorgenommenen Änderungen an"
},
"description": {
"en": "This maps shows all the changes made with MapComplete"
"en": "This maps shows all the changes made with MapComplete",
"de": "Diese Karte zeigt alle mit MapComplete vorgenommenen Änderungen",
"es": "Este mapa muestra todos los cambios realizados con MapComplete",
"pl": "Ta mapa pokazuje wszystkie zmiany wprowadzone za pomocą MapComplete"
},
"icon": "./assets/svg/logo.svg",
"hideFromOverview": true,
@ -18,7 +23,8 @@
{
"id": "mapcomplete-changes",
"name": {
"en": "Changeset centers"
"en": "Changeset centers",
"de": "Changeset-Zentren"
},
"minzoom": 0,
"source": {
@ -28,41 +34,49 @@
},
"title": {
"render": {
"en": "Changeset for {theme}"
"en": "Changeset for {theme}",
"de": "Änderungssatz für {theme}"
}
},
"description": {
"en": "Shows all MapComplete changes"
"en": "Shows all MapComplete changes",
"de": "Zeigt alle MapComplete-Änderungen",
"es": "Muestra todos los cambios de MapComplete"
},
"tagRenderings": [
{
"id": "show_changeset_id",
"render": {
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>",
"de": "Änderungssatz <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
}
},
{
"id": "contributor",
"question": {
"en": "What contributor did make this change?"
"en": "What contributor did make this change?",
"de": "Wer hat zu dieser Änderung beigetragen?"
},
"freeform": {
"key": "user"
},
"render": {
"en": "Change made by <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>"
"en": "Change made by <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>",
"de": "Änderung vorgenommen von <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>"
}
},
{
"id": "theme-id",
"question": {
"en": "What theme was used to make this change?"
"en": "What theme was used to make this change?",
"de": "Welches Thema wurde für diese Änderung verwendet?"
},
"freeform": {
"key": "theme"
},
"render": {
"en": "Change with theme <a href='https://mapcomplete.org/{theme}'>{theme}</a>"
"en": "Change with theme <a href='https://mapcomplete.org/{theme}'>{theme}</a>",
"de": "Änderung mit Thema <a href='https://mapcomplete.org/{theme}'>{theme}</a>"
}
},
{
@ -71,19 +85,23 @@
"key": "locale"
},
"question": {
"en": "What locale (language) was this change made in?"
"en": "What locale (language) was this change made in?",
"de": "In welcher Sprache (Locale) wurde diese Änderung vorgenommen?"
},
"render": {
"en": "User locale is {locale}"
"en": "User locale is {locale}",
"de": "Die Benutzersprache ist {locale}"
}
},
{
"id": "host",
"render": {
"en": "Change with with <a href='{host}'>{host}</a>"
"en": "Change with with <a href='{host}'>{host}</a>",
"de": "Änderung mit <a href='{host}'>{host}</a>"
},
"question": {
"en": "What host (website) was this change made with?"
"en": "What host (website) was this change made with?",
"de": "Bei welchem Host (Website) wurde diese Änderung vorgenommen?"
},
"freeform": {
"key": "host"
@ -104,10 +122,12 @@
{
"id": "version",
"question": {
"en": "What version of MapComplete was used to make this change?"
"en": "What version of MapComplete was used to make this change?",
"de": "Welche Version von MapComplete wurde verwendet, um diese Änderung vorzunehmen?"
},
"render": {
"en": "Made with {editor}"
"en": "Made with {editor}",
"de": "Erstellt mit {editor}"
},
"freeform": {
"key": "editor"
@ -143,7 +163,10 @@
}
],
"question": {
"en": "Themename contains {search}"
"en": "Themename contains {search}",
"de": "Themenname enthält {search}",
"es": "El nombre contiene {search}",
"pl": "Nazwa tematu zawiera {search}"
}
}
]
@ -159,7 +182,9 @@
}
],
"question": {
"en": "Themename does <b>not</b> contain {search}"
"en": "Themename does <b>not</b> contain {search}",
"de": "Themename enthält <b>nicht</b> {search}",
"es": "El nombre del tema <b>no</b> contiene {search}"
}
}
]
@ -175,7 +200,9 @@
}
],
"question": {
"en": "Made by contributor {search}"
"en": "Made by contributor {search}",
"de": "Erstellt von Mitwirkendem {search}",
"es": "Hecho por el colaborador {search}"
}
}
]
@ -191,7 +218,9 @@
}
],
"question": {
"en": "<b>Not</b> made by contributor {search}"
"en": "<b>Not</b> made by contributor {search}",
"de": "<b>Nicht</b> erstellt von Mitwirkendem {search}",
"es": "<b>No</b> realizado por el colaborador {search}"
}
}
]
@ -208,7 +237,9 @@
}
],
"question": {
"en": "Made before {search}"
"en": "Made before {search}",
"de": "Erstellt vor {search}",
"es": "Realizado antes de {search}"
}
}
]
@ -225,7 +256,9 @@
}
],
"question": {
"en": "Made after {search}"
"en": "Made after {search}",
"de": "Erstellt nach {search}",
"es": "Realizado después de {search}"
}
}
]
@ -241,7 +274,9 @@
}
],
"question": {
"en": "User language (iso-code) {search}"
"en": "User language (iso-code) {search}",
"de": "Benutzersprache (ISO-Code) {search}",
"es": "Idioma del usuario (código iso) {search}"
}
}
]
@ -257,7 +292,8 @@
}
],
"question": {
"en": "Made with host {search}"
"en": "Made with host {search}",
"de": "Erstellt mit Host {search}"
}
}
]
@ -268,7 +304,8 @@
{
"osmTags": "add-image>0",
"question": {
"en": "Changeset added at least one image"
"en": "Changeset added at least one image",
"de": "Changeset hat mindestens ein Bild hinzugefügt"
}
}
]
@ -279,7 +316,8 @@
{
"osmTags": "theme!=grb",
"question": {
"en": "Exclude GRB theme"
"en": "Exclude GRB theme",
"de": "GRB-Thema ausschließen"
}
}
]
@ -290,7 +328,9 @@
{
"osmTags": "theme!=etymology",
"question": {
"en": "Exclude etymology theme"
"en": "Exclude etymology theme",
"de": "Etymologie-Thema ausschließen",
"es": "Excluir el tema de la etimología"
}
}
]
@ -305,7 +345,8 @@
{
"id": "link_to_more",
"render": {
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>"
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>",
"de": "Weitere Statistiken findest du <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>hier</a>"
}
},
{

View file

@ -59,7 +59,8 @@
"override": {
"minzoom": 12
}
}
},
"police"
],
"enableMorePrivacy": true
}

View file

@ -683,8 +683,8 @@
}
],
"allowMove": {
"enableImproveAccuraccy": true,
"enableRelocation": false
"enableRelocation": false,
"enableImproveAccuracy": true
}
},
"named_streets"

View file

@ -194,7 +194,7 @@
"josmNotOpened": "JOSM konnte nicht erreicht werden. Bitte sicherstellen, dass das Programm geöffnet und Remote Control aktiviert ist",
"josmOpened": "JOSM ist geöffnet",
"madeBy": "Erstellt von <b>{author}</b>",
"mapContributionsBy": "Die angezeigten Daten wurden bearbeitet durch {contributors}",
"mapContributionsBy": "Angezeigte Daten wurden bearbeitet durch {contributors}",
"mapContributionsByAndHidden": "Die angezeigten Daten wurden bearbeitet von {contributors} und {hiddenCount} weiteren Beitragenden",
"mapDataByOsm": "Kartendaten: OpenStreetMap",
"mapillaryHelp": "<b>Mapillary</b> ist ein Online-Dienst, der Straßenbilder sammelt und sie unter einer freien Lizenz anbietet. Mitwirkende dürfen diese Bilder verwenden, um OpenStreetMap zu verbessern",

View file

@ -633,7 +633,7 @@
"#": "These texts are shown above the theme buttons when no theme is loaded",
"about": "About MapComplete",
"featuredThemeTitle": "Featured this week",
"intro": "Maps about various topics which you contribute to",
"intro": "Maps about various topics which you can contribute to",
"learnMore": "Learn more",
"logIn": "Log in to see other themes you previously visited",
"pickTheme": "Pick a theme below to get started.",
@ -865,6 +865,9 @@
"description": "a positive, whole number",
"noZero": "Zero is not allowed"
},
"regex": {
"description": "a regular expression"
},
"slope": {
"inputExplanation": "Place your phone on the ground with the top side of your phone pointing towards the top of the slope.",
"inputIncorrect": "For correct measurements, make sure the arrow is within the green area."

View file

@ -420,7 +420,8 @@
"index": {
"#": "Estos textos son mostrados sobre los botones del tema cuando no hay un tema cargado",
"featuredThemeTitle": "Esta semana destacamos",
"intro": "Mapas sobre diversos temas a los que contribuye",
"intro": "Mapas sobre diversos temas a los que puedes contribuir",
"learnMore": "Más información",
"logIn": "Inicia sesión para ver otros temas que visitaste anteriormente",
"pickTheme": "Elige un tema de abajo para empezar.",
"title": "MapComplete"

View file

@ -5137,14 +5137,21 @@
}
}
},
"11": {
"10": {
"options": {
"0": {
"question": "Editat per última vega pel contribuïdor {search}"
}
}
},
"12": {
"options": {
"0": {
"question": "Creada abans de {search}"
}
}
},
"12": {
"13": {
"options": {
"0": {
"question": "Creada després de {search}"
@ -5178,26 +5185,19 @@
}
}
},
"6": {
"7": {
"options": {
"0": {
"question": "Obert pel contribuïdor {search}"
}
}
},
"7": {
"8": {
"options": {
"0": {
"question": "<b>No</b> obert pel contribuïdor {search}"
}
}
},
"9": {
"options": {
"0": {
"question": "Editat per última vega pel contribuïdor {search}"
}
}
}
},
"name": "Notes d'OpenStreetMap",

View file

@ -5363,14 +5363,21 @@
}
}
},
"11": {
"10": {
"options": {
"0": {
"question": "Naposledy upravil přispěvatel {search}"
}
}
},
"12": {
"options": {
"0": {
"question": "Vytvořeno před {search}"
}
}
},
"12": {
"13": {
"options": {
"0": {
"question": "Vytvořeno po {search}"
@ -5404,26 +5411,19 @@
}
}
},
"6": {
"7": {
"options": {
"0": {
"question": "Otevřeno přispěvatelem {search}"
}
}
},
"7": {
"8": {
"options": {
"0": {
"question": "<b>Není</b> otevřeno přispěvatelem {search}"
}
}
},
"9": {
"options": {
"0": {
"question": "Naposledy upravil přispěvatel {search}"
}
}
}
},
"name": "Poznámky OpenStreetMap",

View file

@ -1640,7 +1640,7 @@
},
"note": {
"filter": {
"9": {
"10": {
"options": {
"0": {
"question": "Senest redigeret af bidragsyder {search}"

View file

@ -6777,14 +6777,21 @@
}
}
},
"11": {
"10": {
"options": {
"0": {
"question": "Zuletzt bearbeitet von {search}"
}
}
},
"12": {
"options": {
"0": {
"question": "Erstellt vor dem {search}"
}
}
},
"12": {
"13": {
"options": {
"0": {
"question": "Erstellt nach dem {search}"
@ -6818,26 +6825,19 @@
}
}
},
"6": {
"7": {
"options": {
"0": {
"question": "Erstellt von {search}"
}
}
},
"7": {
"8": {
"options": {
"0": {
"question": "<b>Nicht</b> erstellt von {search}"
}
}
},
"9": {
"options": {
"0": {
"question": "Zuletzt bearbeitet von {search}"
}
}
}
},
"name": "OpenStreetMap-Hinweise",

View file

@ -6805,32 +6805,39 @@
"10": {
"options": {
"0": {
"question": "Not edited as last by {search}"
"question": "Last edited by contributor {search}"
}
}
},
"11": {
"options": {
"0": {
"question": "Created before {search}"
"question": "Not edited as last by {search}"
}
}
},
"12": {
"options": {
"0": {
"question": "Created after {search}"
"question": "Created before {search}"
}
}
},
"13": {
"options": {
"0": {
"question": "Last edited before {search}"
"question": "Created after {search}"
}
}
},
"14": {
"options": {
"0": {
"question": "Last edited before {search}"
}
}
},
"15": {
"options": {
"0": {
"question": "Last edited after {search}"
@ -6874,28 +6881,28 @@
"6": {
"options": {
"0": {
"question": "Opened by contributor {search}"
"question": "Should <b>not</b> mention {search} in <b>any</b> comment"
}
}
},
"7": {
"options": {
"0": {
"question": "<b>Not</b> opened by contributor {search}"
"question": "Opened by contributor {search}"
}
}
},
"8": {
"options": {
"0": {
"question": "Edited or commented on by any user with name {search}"
"question": "<b>Not</b> opened by contributor {search}"
}
}
},
"9": {
"options": {
"0": {
"question": "Last edited by contributor {search}"
"question": "Edited or commented on by any user with name {search}"
}
}
}
@ -7716,6 +7723,50 @@
"render": "Playground device"
}
},
"police": {
"description": "Many types of police facilities ",
"name": "Police stations",
"presets": {
"0": {
"description": "A police office where the general public can enter for inquiries",
"title": "a police office"
},
"1": {
"description": "A place where police performs checks on travelling people",
"title": "a police checkpoint"
},
"2": {
"description": "An administrative police office without services for the general public.",
"title": "an administrative, police backoffice"
},
"3": {
"description": "A jail run by the police without public services. People are detained here for a short time (at most a few days), e.g. for small misdemeanors, disturbance of the public order or awaiting a trial"
},
"4": {
"description": "A naval or maritime base for the maritime police; often with a pier and police boats nearby"
}
},
"tagRenderings": {
"4_z2nrdhy6tyyh4fd": {
"mappings": {
"0": {
"then": "This police office has some cells to detain people"
},
"1": {
"then": "This police office does not have cells to detain people"
}
},
"question": "Does this police office have detention facilities?"
},
"police_name": {
"question": "What is the name of this police facility?",
"render": "<b>{name}</b>"
}
},
"title": {
"render": "{name}"
}
},
"postboxes": {
"description": "The layer showing postboxes.",
"name": "Postboxes",

View file

@ -3146,14 +3146,21 @@
}
}
},
"11": {
"10": {
"options": {
"0": {
"question": "Editada por última vez por el contributor {search}"
}
}
},
"12": {
"options": {
"0": {
"question": "Creada antes de {search}"
}
}
},
"12": {
"13": {
"options": {
"0": {
"question": "Creada después de {search}"
@ -3187,26 +3194,19 @@
}
}
},
"6": {
"7": {
"options": {
"0": {
"question": "Abierto por el contributor {search}"
}
}
},
"7": {
"8": {
"options": {
"0": {
"question": "<b>No</b> abierto por el contributor {search}"
}
}
},
"9": {
"options": {
"0": {
"question": "Editada por última vez por el contributor {search}"
}
}
}
},
"name": "Notas de OpenStreetMap",

View file

@ -4439,14 +4439,21 @@
}
}
},
"11": {
"10": {
"options": {
"0": {
"question": "Dernière modification par {search}"
}
}
},
"12": {
"options": {
"0": {
"question": "Créée avant le {search}"
}
}
},
"12": {
"13": {
"options": {
"0": {
"question": "Créée après le {search}"
@ -4460,26 +4467,19 @@
}
}
},
"6": {
"7": {
"options": {
"0": {
"question": "Ouverte par {search}"
}
}
},
"7": {
"8": {
"options": {
"0": {
"question": "<b>Exclure</b>les notes ouvertes par {search}"
}
}
},
"9": {
"options": {
"0": {
"question": "Dernière modification par {search}"
}
}
}
},
"name": "Notes OpenStreetMap",

View file

@ -5566,14 +5566,21 @@
}
}
},
"11": {
"10": {
"options": {
"0": {
"question": "Laatst bewerkt door bijdrager {search}"
}
}
},
"12": {
"options": {
"0": {
"question": "Aangemaakt voor {search}"
}
}
},
"12": {
"13": {
"options": {
"0": {
"question": "Aangemaakt na {search}"
@ -5607,26 +5614,19 @@
}
}
},
"6": {
"7": {
"options": {
"0": {
"question": "Geopend door bijdrager {search}"
}
}
},
"7": {
"8": {
"options": {
"0": {
"question": "<b>Niet</b> geopend door bijdrager {search}"
}
}
},
"9": {
"options": {
"0": {
"question": "Laatst bewerkt door bijdrager {search}"
}
}
}
},
"name": "OpenStreetMap Notes",

View file

@ -808,6 +808,72 @@
"description": "Los faros son edificios altos con una luz en la parte superior para guiar el tráfico marítimo.",
"title": "Faros"
},
"mapcomplete-changes": {
"description": "Este mapa muestra todos los cambios realizados con MapComplete",
"layers": {
"0": {
"description": "Muestra todos los cambios de MapComplete",
"filter": {
"0": {
"options": {
"0": {
"question": "El nombre contiene {search}"
}
}
},
"1": {
"options": {
"0": {
"question": "El nombre del tema <b>no</b> contiene {search}"
}
}
},
"10": {
"options": {
"0": {
"question": "Excluir el tema de la etimología"
}
}
},
"2": {
"options": {
"0": {
"question": "Hecho por el colaborador {search}"
}
}
},
"3": {
"options": {
"0": {
"question": "<b>No</b> realizado por el colaborador {search}"
}
}
},
"4": {
"options": {
"0": {
"question": "Realizado antes de {search}"
}
}
},
"5": {
"options": {
"0": {
"question": "Realizado después de {search}"
}
}
},
"6": {
"options": {
"0": {
"question": "Idioma del usuario (código iso) {search}"
}
}
}
}
}
}
},
"maproulette": {
"description": "Tema que muestra las tareas de MapRoulette, permitiendo buscarlas, filtrarlas y arreglarlas.",
"title": "Tareas de MapRoulette"

View file

@ -644,6 +644,22 @@
},
"title": "Krawężniki i przejścia"
},
"mapcomplete-changes": {
"description": "Ta mapa pokazuje wszystkie zmiany wprowadzone za pomocą MapComplete",
"layers": {
"0": {
"filter": {
"0": {
"options": {
"0": {
"question": "Nazwa tematu zawiera {search}"
}
}
}
}
}
}
},
"maproulette": {
"description": "Temat pokazujący zadania MapRoulette, umożliwiający ich wyszukiwanie, filtrowanie i naprawianie.",
"title": "Zadania MapRoulette"

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "mapcomplete",
"version": "0.46.8",
"version": "0.46.9",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "mapcomplete",
"version": "0.46.8",
"version": "0.46.9",
"license": "GPL-3.0-or-later",
"dependencies": {
"@comunica/core": "^3.0.1",

View file

@ -1,6 +1,6 @@
{
"name": "mapcomplete",
"version": "0.46.8",
"version": "0.46.9",
"repository": "https://github.com/pietervdvn/MapComplete",
"description": "A small website to edit OSM easily",
"bugs": "https://github.com/pietervdvn/MapComplete/issues",
@ -123,7 +123,7 @@
"reuse-compliance": "reuse lint",
"housekeeping": "git pull && npx update-browserslist-db@latest && npm run weblate:merge-heavy && npm run generate && npm run generate:docs && npm run generate:schemas && npm run generate:contributor-list && vite-node scripts/fetchLanguages.ts && vite-node scripts/generateSunnyUnlabeled.ts && npm run format && git add assets/ langs/ Docs/ **/*.ts Docs/* src/* && git commit -m 'chore: automated housekeeping...'",
"###": "MICROSERVICES AND SERVER MAINTAINENCE",
"release": "standard-version",
"release": "standard-version && git push --follow-tags",
"release:minor": "standard-version --release-as minor",
"release:patch": "standard-version --release-as patch",
"release:major": "standard-version --release-as major",

View file

@ -94,14 +94,28 @@ export default class ScriptUtils {
})
}
public static getThemePaths(): string[] {
return ScriptUtils.readDirRecSync("./assets/themes")
public static getThemePaths(useTranslationPaths = false): string[] {
const normalFiles = ScriptUtils.readDirRecSync("./assets/themes")
.filter((path) => path.endsWith(".json") && !path.endsWith(".proto.json"))
.filter((path) => path.indexOf("license_info.json") < 0)
if (!useTranslationPaths) {
return normalFiles
}
const specialfiles = ["./assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json"]
const blacklist = ["assets/themes/mapcomplete-changes/mapcomplete-changes.json"]
const filtered = normalFiles.filter(path => !blacklist.some(black => path.endsWith(black)))
return filtered.concat(specialfiles)
}
public static getThemeFiles(): { parsed: LayoutConfigJson; path: string; raw: string }[] {
return this.getThemePaths().map((path) => {
public static getThemeFiles(useTranslationPaths = false): {
parsed: LayoutConfigJson;
path: string;
raw: string
}[] {
return this.getThemePaths(useTranslationPaths).map((path) => {
try {
const contents = readFileSync(path, { encoding: "utf8" })
if (contents === "") {
@ -148,6 +162,7 @@ export default class ScriptUtils {
const data = await ScriptUtils.Download(url, headers)
return JSON.parse(data["content"])
}
public static async DownloadFetch(
url: string,
headers?: any
@ -158,6 +173,7 @@ export default class ScriptUtils {
console.log("Fetched", url, data)
return { content: data }
}
public static Download(
url: string,
headers?: any
@ -193,17 +209,17 @@ export default class ScriptUtils {
path: urlObj.pathname + urlObj.search,
port: urlObj.port,
headers: headers,
headers: headers
},
(res) => {
const parts: string[] = []
res.setEncoding("utf8")
res.on("data", function (chunk) {
res.on("data", function(chunk) {
// @ts-ignore
parts.push(chunk)
})
res.addListener("end", function () {
res.addListener("end", function() {
if (res.statusCode === 301 || res.statusCode === 302) {
console.log("Got a redirect:", res.headers.location)
resolve({ redirect: res.headers.location })
@ -221,7 +237,7 @@ export default class ScriptUtils {
})
}
)
request.on("error", function (e) {
request.on("error", function(e) {
reject(e)
})
} catch (e) {

View file

@ -504,7 +504,8 @@ class LayerOverviewUtils extends Script {
priviliged.delete("last_click")
priviliged.delete("search")
if (priviliged.size > 0 && !forceReload) {
const isBoostrapping = AllSharedLayers.getSharedLayersConfigs().size == 0
if (!isBoostrapping && priviliged.size > 0) {
throw (
"Priviliged layer " +
Array.from(priviliged).join(", ") +

View file

@ -670,7 +670,7 @@ function removeNonEnglishTranslations(object: any) {
* Load the translations into the theme files
*/
function mergeThemeTranslations(englishOnly: boolean = false) {
const themeFiles = ScriptUtils.getThemeFiles()
const themeFiles = ScriptUtils.getThemeFiles(true)
for (const themeFile of themeFiles) {
let config = themeFile.parsed
mergeLayerTranslation(config, themeFile.path, loadTranslationFilesFrom("themes"))
@ -723,7 +723,7 @@ class GenerateTranslations extends Script {
{
const l1 = generateTranslationsObjectFrom(ScriptUtils.getLayerFiles(), "layers")
const l2 = generateTranslationsObjectFrom(
ScriptUtils.getThemeFiles().filter(
ScriptUtils.getThemeFiles(true).filter(
(th) => th.parsed.mustHaveLanguage === undefined
),
"themes"

View file

@ -15,7 +15,7 @@ export default class PlantNet {
for (const image of imageUrls) {
url += "&images=" + encodeURIComponent(image)
}
return Utils.downloadJsonCached(url, 365 * 24 * 60 * 60 * 1000)
return Utils.downloadJsonCached(url, 365 * 24 * 60 * 60 * 1000, undefined, true)
}
public static exampleResult: PlantNetResult = {

View file

@ -86,17 +86,29 @@ export default class Constants {
static distanceToChangeObjectBins = [25, 50, 100, 500, 1000, 5000, Number.MAX_VALUE]
static themeOrder = [
"personal",
"cyclofix",
"waste",
"etymology",
"waste",
"food",
"cafes_and_pubs",
"shops",
"playgrounds",
"hailhydrant",
"toilets",
"aed",
"healthcare",
"sports",
"artwork",
"bookcases",
"playgrounds",
"drinking_water",
"toilets",
"vending_machine",
"aed",
"clock",
"surveillance",
"advertising",
"circular_economy",
]
/**
* Upon initialization, the GPS will search the location.

View file

@ -131,6 +131,13 @@ export default class FilteredLayer {
return values
}
/**
* import Translations from "../UI/i18n/Translations"
* import { RegexTag } from "../Logic/Tags/RegexTag"
*
* const option: FilterConfigOption = {question: Translations.T("question"), osmTags: undefined, originalTagsSpec: "key~.*{search}.*", fields: [{name: "search", type: "string"}] }
* FilteredLayer.fieldsToTags(option, {search: "value_regex"}) // => new RegexTag("key", /^(.*(value_regex).*)$/)
*/
private static fieldsToTags(
option: FilterConfigOption,
fieldstate: string | Record<string, string>
@ -153,7 +160,7 @@ export default class FilteredLayer {
}
for (const key in properties) {
v = (<string>v).replace("{" + key + "}", properties[key])
v = (<string>v).replace("{" + key + "}", "(" + properties[key] + ")")
}
return v

View file

@ -60,7 +60,7 @@ export default class FilterConfig {
}
const fields: { name: string; type: ValidatorType }[] = (option.fields ?? []).map((f, i) => {
const type = <ValidatorType> f.type ?? "string"
const type = <ValidatorType> f.type ?? "regex"
if(Validators.availableTypes.indexOf(type) < 0){
throw `Invalid filter: type is not a valid validator. Did you mean one of ${Utils.sortedByLevenshteinDistance(type, <any>Validators.availableTypes, x => x).slice(0, 3)}`
}
@ -70,12 +70,12 @@ export default class FilterConfig {
}
return {
name: f.name,
type,
type
}
})
for (const field of fields) {
for (let ln in question.translations) {
for (const ln in question.translations) {
const txt = question.translations[ln]
if (ln.startsWith("_")) {
continue
@ -226,7 +226,7 @@ export default class FilterConfig {
opt.osmTags?.asHumanString() ?? "",
opt.fields?.length > 0
? opt.fields.map((f) => f.name + " (" + f.type + ")").join(" ")
: undefined,
: undefined
])
)
})

View file

@ -8,6 +8,8 @@
import { Utils } from "../../Utils"
import type { ValidatorType } from "../InputElement/Validators"
import InputHelper from "../InputElement/InputHelper.svelte"
import { Translation } from "../i18n/Translation"
import Tr from "../Base/Tr.svelte"
export let filteredLayer: FilteredLayer
export let option: FilterConfigOption
@ -36,7 +38,7 @@
appliedFilter?.setData(FilteredLayer.fieldsToString(properties))
}
let firstValue : UIEventSource<string>
let firstValue: UIEventSource<string>
for (const field of option.fields) {
// A bit of cheating: the 'parts' will have '}' suffixed for fields
const src = new UIEventSource<string>(initialState[field.name] ?? "")
@ -47,9 +49,10 @@
onDestroy(
src.stabilized(200).addCallback(() => {
setFields()
}),
})
)
}
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined)
</script>
<div class="low-interaction p-1 rounded-2xl px-3" class:interactive={$firstValue?.length > 0}>
@ -58,11 +61,15 @@
<!-- This is a field! -->
<span class="mx-1">
<InputHelper value={fieldValues[part["subs"]]} type={fieldTypes[part["subs"]]}>
<ValidatedInput slot="fallback" value={fieldValues[part["subs"]]} type={fieldTypes[part["subs"]]} />
<ValidatedInput slot="fallback" value={fieldValues[part["subs"]]} type={fieldTypes[part["subs"]]}
{feedback} />
</InputHelper>
</span>
{:else}
{@html part["message"]}
{/if}
{/each}
{#if $feedback}
<Tr cls="alert" t={$feedback}/>
{/if}
</div>

View file

@ -90,13 +90,13 @@
<LoginButton osmConnection={state.osmConnection} slot="not-logged-in" />
<div class="flex items-center gap-x-4">
{#if $userdetails.img}
<img src={$userdetails.img} class="h-14 w-14 rounded-full" />
<img alt="avatar" src={$userdetails.img} class="h-14 w-14 rounded-full" />
{/if}
<b>{$userdetails.name}</b>
</div>
</LoginToggle>
<Page {onlyLink} shown={pg.usersettings} bodyPadding="p-0">
<Page {onlyLink} shown={pg.usersettings} bodyPadding="p-0 pb-4">
<svelte:fragment slot="header">
<CogIcon />
<Tr t={UserRelatedState.usersettingsConfig.title.GetRenderValue({})} />

View file

@ -220,8 +220,8 @@
<td/>
{/if}
{#each range(7) as wd}
<OHCell type="half" {h} {wd} on:start={() => startSelection(wd, h)} on:end={() => endSelection(wd, h)}
on:move={() => moved(wd, h)} on:clear={() => clearSelection()} />
<OHCell type="half" {h} {wd} on:start={() => startSelection(wd, h + 0.5)} on:end={() => endSelection(wd, h + 0.5)}
on:move={() => moved(wd, h + 0.5)} on:clear={() => clearSelection()} />
{/each}
</tr>

View file

@ -15,9 +15,6 @@ import UrlValidator from "./Validators/UrlValidator"
import PhoneValidator from "./Validators/PhoneValidator"
import OpeningHoursValidator from "./Validators/OpeningHoursValidator"
import ColorValidator from "./Validators/ColorValidator"
import BaseUIElement from "../BaseUIElement"
import Combine from "../Base/Combine"
import Title from "../Base/Title"
import SimpleTagValidator from "./Validators/SimpleTagValidator"
import ImageUrlValidator from "./Validators/ImageUrlValidator"
import TagKeyValidator from "./Validators/TagKeyValidator"
@ -30,6 +27,7 @@ import SlopeValidator from "./Validators/SlopeValidator"
import VeloparkValidator from "./Validators/VeloparkValidator"
import NameSuggestionIndexValidator from "./Validators/NameSuggestionIndexValidator"
import CurrencyValidator from "./Validators/CurrencyValidator"
import RegexValidator from "./Validators/RegexValidator"
export type ValidatorType = (typeof Validators.availableTypes)[number]
@ -64,6 +62,7 @@ export default class Validators {
"velopark",
"nsi",
"currency",
"regex"
] as const
public static readonly AllValidators: ReadonlyArray<Validator> = [
@ -95,6 +94,7 @@ export default class Validators {
new VeloparkValidator(),
new NameSuggestionIndexValidator(),
new CurrencyValidator(),
new RegexValidator()
]
private static _byType = Validators._byTypeConstructor()

View file

@ -0,0 +1,22 @@
import StringValidator from "./StringValidator"
import { s } from "vitest/dist/env-afee91f0"
import { Translation } from "../../i18n/Translation"
import Translations from "../../i18n/Translations"
export default class RegexValidator extends StringValidator{
constructor() {
super("regex", "Validates a regex")
}
getFeedback(s: string): Translation | undefined {
try{
new RegExp(s)
}catch (e) {
return Translations.T("Not a valid Regex: "+e)
}
}
isValid(s: string): boolean {
return this.getFeedback(s) === undefined
}
}

View file

@ -9,8 +9,8 @@
import BackButton from "../Base/BackButton.svelte"
import NextButton from "../Base/NextButton.svelte"
import WikipediaPanel from "../Wikipedia/WikipediaPanel.svelte"
import { createEventDispatcher } from "svelte"
import Plantnet_logo from "../../assets/svg/Plantnet_logo.svelte"
import ArrowPath from "@babeard/svelte-heroicons/mini/ArrowPath"
/**
* The main entry point for the plantnet wizard
@ -23,7 +23,6 @@
*/
export let imageUrls: Store<string[]>
export let onConfirm: (wikidataId: string) => void
const dispatch = createEventDispatcher<{ selected: string }>()
let collapsedMode = true
let options: UIEventSource<PlantNetSpeciesMatch[]> = new UIEventSource<PlantNetSpeciesMatch[]>(
undefined
@ -38,18 +37,20 @@
let done = false
function speciesSelected(species: PlantNetSpeciesMatch) {
function speciesSelected(species: string) {
console.log("Selected:", species)
selectedOption = species
}
async function detectSpecies() {
error = undefined
collapsedMode = false
try {
const result = await PlantNet.query(imageUrls.data.slice(0, 5))
options.set(result.results.filter((r) => r.score > 0.005).slice(0, 8))
} catch (e) {
console.error("Caught", e)
error = e
}
}
@ -60,8 +61,12 @@
<button class="w-full" on:click={detectSpecies}>
<Tr t={t.button} />
</button>
{:else if $error !== undefined}
{:else if error !== undefined}
<Tr cls="alert" t={t.error.Subs({ error })} />
<button on:click={() => detectSpecies()}>
<ArrowPath class="w-6 h-6"/>
<Tr t={Translations.t.general.retry}/>
</button>
{:else if $imageUrls.length === 0}
<!-- No urls are available, show the explanation instead-->
<div class=" border-region relative mb-1 p-2">

View file

@ -4,6 +4,7 @@
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import Searchbar from "../Base/Searchbar.svelte"
import Translations from "../i18n/Translations"
import { Utils } from "../../Utils"
export let tags: UIEventSource<Record<string, any>>
export let tagKeys = tags.map((tgs) => (tgs === undefined ? [] : Object.keys(tgs)))
@ -34,10 +35,19 @@
const metaKeys: string[] = [].concat(...SimpleMetaTaggers.metatags.map((k) => k.keys))
let allCalculatedTags = new Set<string>([...calculatedTags, ...metaKeys])
let search = new UIEventSource<string>("")
function downloadAsJson(){
Utils.offerContentsAsDownloadableFile(
JSON.stringify(tags.data, null, " "), "tags-"+(tags.data.id ?? layer?.id ?? "")+".json"
)
}
</script>
<section>
<Searchbar value={search} placeholder={Translations.T("Search a key")}></Searchbar>
<button class="as-link" on:click={() => downloadAsJson()}>
Download as JSON
</button>
<table class="zebra-table break-all">
<tr>
<th>Key</th>

View file

@ -30,7 +30,7 @@
.getSchemaStartingWith(schema.path)
.filter((part) => part.path.length - 1 === schema.path.length)
let usesOverride = value["builtin"] !== undefined
let usesOverride = value?.["builtin"] !== undefined
function schemaForMultitype() {
const sch = { ...schema }
@ -138,7 +138,7 @@
</div>
{:else if typeof value === "string"}
Builtin: <b>{value}</b>
{:else if value["builtin"]}
{:else if value?.["builtin"]}
reused tagrendering <span class="font-bold">{JSON.stringify(value["builtin"])}</span>
{:else}
<Tr cls="font-bold" t={Translations.T(value?.question ?? value?.render)} />

View file

@ -159,6 +159,9 @@ export abstract class EditJsonState<T> {
}
public getSchemaStartingWith(path: string[]) {
if(path === undefined){
return undefined
}
return this.schema.filter(
(sch) =>
!path.some((part, i) => !(sch.path.length > path.length && sch.path[i] === part))

View file

@ -5,18 +5,23 @@
import { TrashIcon } from "@babeard/svelte-heroicons/mini"
import ShowConversionMessage from "./ShowConversionMessage.svelte"
import Markdown from "../Base/Markdown.svelte"
import type { QuestionableTagRenderingConfigJson } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
import type {
QuestionableTagRenderingConfigJson
} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
import CollapsedTagRenderingPreview from "./CollapsedTagRenderingPreview.svelte"
import { Accordion } from "flowbite-svelte"
import { Utils } from "../../Utils"
export let state: EditJsonState<any>
export let path: (string | number)[] = []
let schema: ConfigMeta = state.getSchema(path)[0]
console.log("SBA got schema", schema, "for path", path)
let title = schema.path.at(-1)
let title = schema?.path?.at(-1)
let singular = title
if (title?.endsWith("s")) {
singular = title.slice(0, title.length - 1)
singular = title?.slice(0, title.length - 1)
}
let article = "a"
if (singular?.match(/^[aeoui]/)) {
@ -25,18 +30,20 @@
const isTagRenderingBlock = path.length === 1 && path[0] === "tagRenderings"
if (isTagRenderingBlock) {
if (isTagRenderingBlock && schema !== undefined) {
schema = { ...schema }
schema.description = undefined
}
const subparts: ConfigMeta[] = state
.getSchemaStartingWith(schema.path)
.filter((part) => part.path.length - 1 === schema.path.length)
.getSchemaStartingWith(schema?.path)
?.filter((part) => part.path.length - 1 === schema?.path?.length)
let messages = state.messagesFor(path)
let datapath = path
const currentValue = state.getStoreFor<(string | QuestionableTagRenderingConfigJson)[]>(datapath)
currentValue.set(Utils.DedupT(currentValue.data))
console.log("Current value is", currentValue.data)
if (currentValue.data === undefined) {
currentValue.setData([])
}
@ -62,68 +69,69 @@
currentValue.ping()
}
</script>
{#if schema !== undefined}
<div class="pl-2">
<h3>{schema.path.at(-1)}</h3>
<div class="pl-2">
<h3>{schema.path.at(-1)}</h3>
{#if subparts.length > 0}
<Markdown src={schema.description} />
{/if}
{#if $currentValue === undefined}
No array defined
{:else if !Array.isArray($currentValue)}
Not an array: {typeof $currentValue}
{JSON.stringify(path)}
{JSON.stringify($currentValue).slice(0, 120)}
{:else if $currentValue?.length === 0}
No values are defined
{#if $messages.length > 0}
{#each $messages as message}
<ShowConversionMessage {message} />
{/each}
{#if subparts.length > 0}
<Markdown src={schema.description} />
{/if}
{:else if subparts.length === 0}
<!-- We need an array of values, so we use the typehint of the _parent_ element as field -->
{#each $currentValue as value, i}
<div class="flex w-full">
<SchemaBasedField {state} {schema} path={fusePath(i)} />
<button
class="h-fit w-fit rounded-full border border-black p-1"
on:click={() => {
{#if $currentValue === undefined}
No array defined
{:else if !Array.isArray($currentValue)}
Not an array: {typeof $currentValue}
{JSON.stringify(path)}
{JSON.stringify($currentValue).slice(0, 120)}
{:else if $currentValue?.length === 0}
No values are defined
{#if $messages.length > 0}
{#each $messages as message}
<ShowConversionMessage {message} />
{/each}
{/if}
{:else if subparts.length === 0}
<!-- We need an array of values, so we use the typehint of the _parent_ element as field -->
{#each $currentValue as value, i}
<div class="flex w-full">
<SchemaBasedField {state} {schema} path={fusePath(i)} />
<button
class="h-fit w-fit rounded-full border border-black p-1"
on:click={() => {
del(i)
}}
>
<TrashIcon class="h-4 w-4" />
</button>
</div>
{/each}
{:else}
<Accordion>
{#each $currentValue as value, i (value)}
<CollapsedTagRenderingPreview
{state}
{isTagRenderingBlock}
{schema}
{currentValue}
{value}
{i}
{singular}
path={fusePath(i)}
/>
>
<TrashIcon class="h-4 w-4" />
</button>
</div>
{/each}
</Accordion>
{/if}
<div class="flex">
<button on:click={() => createItem()}>Add {article} {singular}</button>
{#if path.length === 1 && path[0] === "tagRenderings"}
<button
on:click={() => {
{:else}
<Accordion>
{#each $currentValue as value, i}
<CollapsedTagRenderingPreview
{state}
{isTagRenderingBlock}
{schema}
{currentValue}
{value}
{i}
{singular}
path={fusePath(i)}
/>
{/each}
</Accordion>
{/if}
<div class="flex">
<button on:click={() => createItem()}>Add {article} {singular}</button>
{#if path.length === 1 && path[0] === "tagRenderings"}
<button
on:click={() => {
createItem("images")
}}
>
Add a builtin tagRendering
</button>
{/if}
<slot name="extra-button" />
>
Add a builtin tagRendering
</button>
{/if}
<slot name="extra-button" />
</div>
</div>
</div>
{/if}

View file

@ -48,7 +48,7 @@
import ChevronRight from "@babeard/svelte-heroicons/mini/ChevronRight"
import ChevronLeft from "@babeard/svelte-heroicons/solid/ChevronLeft"
import { Drawer } from "flowbite-svelte"
import { linear, sineIn } from "svelte/easing"
import { linear } from "svelte/easing"
export let state: ThemeViewState
@ -440,7 +440,6 @@
<MenuDrawer onlyLink={true} {state} />
</div>
</DrawerLeft>
<MenuDrawer onlyLink={false} {state} />
{#if $selectedElement !== undefined && $selectedLayer !== undefined && !$selectedLayer.popupInFloatover}
<!-- right modal with the selected element view -->
@ -494,4 +493,6 @@
{/if}
{/if}
<MenuDrawer onlyLink={false} {state} />
</main>

View file

@ -401,6 +401,19 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
return newArr
}
public static DedupT<T>(arr: T[]): T[]{
if(!arr){
return arr
}
const items = []
for (const item of arr) {
if(items.indexOf(item) < 0){
items.push(item)
}
}
return items
}
/**
* Finds all duplicates in a list of strings
*
@ -1064,19 +1077,22 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
public static async downloadJsonCached<T = object | []>(
url: string,
maxCacheTimeMs: number,
headers?: Record<string, string>
headers?: Record<string, string>,
dontCacheErrors: boolean = false
): Promise<T> {
const result = await Utils.downloadJsonCachedAdvanced(url, maxCacheTimeMs, headers)
const result = await Utils.downloadJsonCachedAdvanced(url, maxCacheTimeMs, headers, dontCacheErrors)
if (result["content"]) {
return result["content"]
}
throw result["error"]
}
public static async downloadJsonCachedAdvanced<T = object | []>(
url: string,
maxCacheTimeMs: number,
headers?: Record<string, string>
headers?: Record<string, string>,
dontCacheErrors = false
): Promise<{ content: T } | { error: string; url: string; statuscode?: number }> {
const cached = Utils._download_cache.get(url)
if (cached !== undefined) {
@ -1090,7 +1106,15 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
headers
)
Utils._download_cache.set(url, { promise, timestamp: new Date().getTime() })
try {
return await promise
}catch (e) {
if(dontCacheErrors){
Utils._download_cache.delete(url)
}
throw e
}
}
public static async downloadJson<T = object | []>(