Compare commits

...

25 commits

Author SHA1 Message Date
214e419e50 Merge pull request 'Few patches, small winter_service theme' () from Robin-patch-1 into develop
Reviewed-on: 
2025-03-17 12:23:14 +01:00
be68837ffb Feature: add user_block endpoint 2025-03-17 02:05:45 +01:00
75a0eeed83 Scripts: fixes to deploy-hosted 2025-03-17 02:04:40 +01:00
ecd8f5e1da Feature(grb): add popup feature to validate e.g. a user profile 2025-03-17 01:17:02 +01:00
c3d905b26a Scripts: deploy hosted now actually now uses the '/tmp/' directory 2025-03-17 01:16:30 +01:00
c0f7de25fd Fix tests 2025-03-16 23:47:46 +01:00
b3009367a3 Scripts: deploy hosted now actually stops when the tests fail 2025-03-16 23:47:12 +01:00
ac5565d546 Chore: ignore 'bing.json' 2025-03-16 22:49:47 +01:00
1933b8a7be Themes(entrance): add question about reference numbers 2025-03-16 22:48:54 +01:00
1dd78563ef Themes(toilets): add condition to supervision question: only ask if a public toilet 2025-03-16 22:48:12 +01:00
40c6a582c7 Themes(toilets): add supervision, hand_drying questions 2025-03-16 18:49:48 +01:00
6f59c95792
Merge branch 'develop' into Robin-patch-1 2025-03-16 14:58:46 +01:00
fb4fbe2be3 Chore: rm obsolete log 2025-03-15 01:34:08 +01:00
ac19702189 Themes(wayside_shrine): add level, do not count 'artwork' 2025-03-15 01:27:12 +01:00
904b628a81
Merge branch 'develop' into Robin-patch-1 2025-03-14 11:38:30 +01:00
c465f756d6
Themes(guideposts): Clean tags when changing 2025-03-13 22:19:42 +01:00
d2ed83972f
Themes(winter_service): add colour to serviced_streets, also show winter_service=limited 2025-03-13 21:49:23 +01:00
455f540cbd
Themes(guideposts): Add mappings for empty ref, name and elevation 2025-03-13 21:33:07 +01:00
5c7246766e
Themes(kerbs and crossings): Remove crossing type, add tactile_paving=partial, invalid values 2025-03-13 20:35:53 +01:00
e19a59c74b
Merge branch 'develop' into Robin-patch-1 2025-03-13 20:25:33 +01:00
19189edbc0
Chore: Gitlens settings 2025-03-13 19:11:09 +01:00
ad3a0a10cb
Merge branch 'develop' into Robin-patch-1 2025-03-13 18:53:22 +01:00
4a23fb87a1
Themes(guideposts): Add question for name, ref and elevation () 2025-03-10 00:03:22 +01:00
cf1ae2f354
Themes(postboxes): Drop old tagging, add returns_only as option 2025-03-09 23:52:36 +01:00
748eccba59
Themes: winter_service theme, split off all_streets from street_lighting 2025-03-09 23:51:56 +01:00
61 changed files with 1467 additions and 804 deletions

View file

@ -16,7 +16,7 @@ jobs:
node-version: "20"
cache: "npm"
cache-dependency-path: package-lock.json
- name: install deps
run: npm ci
shell: bash
@ -43,8 +43,7 @@ jobs:
export NODE_OPTIONS="--max-old-space-size=8192"
npm run clean:tests
npm run generate:doctests 2>&1 | grep -v "No doctests found in"
vitest --run test
npm run clean:tests
vitest --run test && npm run clean:tests
shell: bash
@ -53,11 +52,13 @@ jobs:
- name: Zipping dist file
run: |
mv dist ${{ github.ref_name }}
mv -f dist /tmp/${{ github.ref_name }}
cd /tmp
zip ${{ github.ref_name }}.zip -r ${{ github.ref_name }}/*
cd -
- name: uploading file
run: scp ${{ github.ref_name }}.zip hetzner:/root/staging/
run: scp /tmp/${{ github.ref_name }}.zip hetzner:/root/staging/
- name: unzipping remote file
run: ssh hetzner "cd /root/staging && rm -rf ${{ github.ref_name }} && unzip ${{ github.ref_name }}.zip && rm -rf /root/public/${{ github.ref_name }} && mv /root/staging/${{ github.ref_name }}/ /root/public/ && rm ${{ github.ref_name }}.zip"

1
.gitignore vendored
View file

@ -51,3 +51,4 @@ dist-full/
public/assets/icons/*.webp
uploaded_images.json
/app/dist/
src/assets/bing.json

View file

@ -53,5 +53,12 @@
"[svelte]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.formatOnSave": true
"editor.formatOnSave": true,
"gitlens.remotes": [
{
"domain": "source.mapcomplete.org",
"type": "Gitea",
"name": "MapComplete Forgejo"
}
]
}

View file

@ -17,7 +17,8 @@ All notable changes to this project will be documented in this file. See [standa
* **onwheels:** move building magic back to onwheels theme, decrease minzoom for entrances ([98e8adf](https://github.com/pietervdvn/mapcomplete/commits/98e8adf41b3e296dcdf26ac9c6df21c1f5259f46))
* **wayside_shrine,artwork:** add artwork as adjacent concept to shrines ([266e91e](https://github.com/pietervdvn/mapcomplete/commits/266e91e45db85d27d5271267a1db2175e2588c1d))
* **wayside_shrine:** add preset to snap to a wal ([e8951e2](https://github.com/pietervdvn/mapcomplete/commits/e8951e2b80ff2e4a9818452bc0c0f03f058e7cf2))
* **wayside_shrine:** add preset to snap to a
wall ([e8951e2](https://github.com/pietervdvn/mapcomplete/commits/e8951e2b80ff2e4a9818452bc0c0f03f058e7cf2))
* **wayside_shrines:** integrate wayside shrines ([1f7b156](https://github.com/pietervdvn/mapcomplete/commits/1f7b156a2c18200ece3c3ec9aa3d86f814d2590b))
* **wayside_shrines:** small language fixes ([aaf46cd](https://github.com/pietervdvn/mapcomplete/commits/aaf46cd7b01a9f11720d5e47ac6ffcde15b29add))

View file

@ -0,0 +1,86 @@
{
"id": "all_streets",
"isCounted": false,
"name": {
"en": "All streets",
"nl": "Alle straten",
"ru": "Все улицы",
"zh_Hant": "所有道路",
"hu": "Minden utca",
"de": "Alle Straßen",
"ca": "Tots els carrers",
"es": "Todas las calles",
"fr": "Toutes les rues",
"nb_NO": "Alle gater",
"da": "Alle gader",
"pa_PK": "ساریاں سڑکاں",
"cs": "Všechny ulice",
"it": "Tutte le strade",
"pl": "Wszystkie ulice",
"ko": "모든 거리"
},
"description": {
"en": "Layer with (almost) all streets",
"nl": "Laag met (bijna) alle straten"
},
"source": {
"osmTags": {
"and": [
"highway!=",
"service!=driveway",
"highway!=platform"
]
}
},
"minzoom": 18,
"title": {
"render": {
"en": "Street",
"nl": "Straat",
"ru": "Улица",
"zh_Hant": "照明",
"hu": "Utca",
"de": "Straße",
"ca": "Carrer",
"nb_NO": "Gate",
"fr": "Rue",
"da": "Gade",
"pa_PK": "سڑک",
"es": "Calle",
"cs": "Ulice",
"eu": "Kalea",
"it": "Strada",
"pl": "Ulica",
"ko": "거리"
},
"mappings": [
{
"if": "name~*",
"then": "{name}"
}
]
},
"tagRenderings": [
"images"
],
"allowSplit": true,
"pointRendering": null,
"lineRendering": [
{
"color": {
"render": "#a9a9a9",
"mappings": [
{
"if": "lit=no",
"then": "#303030"
},
{
"if": "lit=yes",
"then": "#ff0"
}
]
}
}
],
"allowMove": false
}

View file

@ -166,69 +166,44 @@
"tagRenderings": [
"images",
{
"id": "crossing-type",
"id": "signals",
"question": {
"en": "What kind of crossing is this?",
"nl": "Wat voor oversteekplaats is dit?",
"de": "Was ist das für eine Kreuzung?",
"es": "¿Qué tipo de cruce es este?",
"fr": "Quel type de passage piéton est-ce ?",
"ca": "Quin tipus de creuament és aquest?",
"cs": "Co je to za přechod?"
"en": "Are there traffic signals at this crossing?",
"nl": "Zijn er verkeerslichten bij deze oversteekplaats?"
},
"condition": "highway=crossing",
"mappings": [
{
"if": "crossing=uncontrolled",
"if": "crossing:signals=no",
"then": {
"en": "Crossing, without traffic lights",
"nl": "Oversteekplaats, zonder verkeerslichten",
"de": "Kreuzungen ohne Ampeln",
"es": "Cruce, sin semáforos",
"fr": "Passage piéton, sans feux de signalisation",
"ca": "Creuament, sense semàfors",
"cs": "Přechod bez světelné signalizace"
"en": "There are no traffic signals at this crossing",
"nl": "Er zijn geen verkeerslichten bij deze oversteekplaats"
}
},
{
"if": "crossing:signals=yes",
"then": {
"en": "There are traffic signals at this crossing",
"nl": "Er zijn verkeerslichten bij deze oversteekplaats"
},
"icon": {
"class": "small",
"path": "./assets/layers/crossings/traffic_lights.svg"
}
},
{
"if": "crossing=traffic_signals",
"then": {
"en": "Crossing with traffic signals",
"nl": "Oversteekplaats met verkeerslichten",
"de": "Kreuzungen mit Ampeln",
"es": "Cruce con semáforos",
"fr": "Passage piéton avec des feux de signalisation",
"ca": "Creuament amb semàfors",
"cs": "Přechod se světelnou signalizací"
}
},
{
"if": "crossing=zebra",
"then": {
"en": "Zebra crossing",
"nl": "Zebrapad",
"de": "Zebrastreifen",
"ca": "Pas de zebra",
"es": "Paso de peatones",
"fr": "Passage piéton",
"cs": "Zebra přechod"
"en": "There are traffic signals at this crossing",
"nl": "Er zijn verkeerslichten bij deze oversteekplaats"
},
"hideInAnswer": true
},
{
"if": "crossing=unmarked",
"then": {
"en": "Crossing without crossing markings",
"nl": "Oversteekplaats zonder kruispuntmarkeringen",
"de": "Kreuzung ohne Kreuzungsmarkierungen",
"es": "Cruce sin marcas de cruce",
"fr": "Passage piéton sans marquages",
"ca": "Creuament sense senyalitzar",
"cs": "Přechod bez označení přechodu"
"icon": {
"class": "small",
"path": "./assets/layers/crossings/traffic_lights.svg"
},
"hideInAnswer": true
}
]
],
"condition": "highway=crossing"
},
{
"id": "markings",
@ -467,7 +442,9 @@
"fixme=Free-form value used in MapComplete for crossing:markings"
]
},
"multiAnswer": true
"multiAnswer": true,
"condition": "highway=crossing",
"invalidValues": "crossing:markings=yes"
},
{
"id": "crossing-bicycle-allowed",
@ -599,6 +576,13 @@
"cs": "Tento přechod má hmatovou dlažbu, ale ne správně"
},
"hideInAnswer": true
},
{
"if": "tactile_paving=partial",
"then": {
"en": "This crrosing has tactile paving, but only on one side",
"nl": "Deze oversteekplaats heeft een geleidelijn, maar slechts aan één kant"
}
}
]
},
@ -949,4 +933,4 @@
"enableImproveAccuracy": true,
"enableRelocation": false
}
}
}

View file

@ -33,17 +33,17 @@
"minzoom": 14,
"title": {
"render": {
"en": "Entrance",
"nl": "Ingang",
"ca": "Entrada",
"da": "Indgang",
"de": "Eingang",
"es": "Entrada",
"fr": "Entrée",
"pa_PK": "دروازہ",
"pl": "Wejście",
"cs": "Vchod",
"cy": "Mynedfa"
"en": "Entrance {ref}",
"nl": "Ingang {ref}",
"ca": "Entrada {ref}",
"da": "Indgang {ref}",
"de": "Eingang {ref}",
"es": "Entrada {ref}",
"fr": "Entrée {ref}",
"pa_PK": "دروازہ{ref}",
"pl": "Wejście {ref}",
"cs": "Vchod {ref}",
"cy": "Mynedfa {ref}"
}
},
"pointRendering": [
@ -68,7 +68,16 @@
]
}
}
]
],
"label": {
"mappings": [
{
"if": "ref~*",
"then": "{ref}"
}
]
},
"labelCssClasses": "rounded bg-white px-2"
}
],
"lineRendering": [],
@ -578,6 +587,29 @@
}
}
]
},
{
"id": "ref",
"question": {
"en": "Does this door have a reference number?",
"nl": "Heeft deze toegang een referentienummer?"
},
"render": {
"en": "This door has <b>{ref}</b> as reference number",
"nl": "Deze deur heeft <b>{ref}</b> als referentienummer"
},
"mappings": [
{
"if": "ref=",
"then": {
"en": "No reference number",
"nl": "Geen referentienummer"
}
}
],
"freeform": {
"key": "ref"
}
}
],
"filter": [

View file

@ -133,6 +133,98 @@
}
}
]
},
{
"id": "name",
"question": {
"en": "What is the name noted on this guidepost?"
},
"freeform": {
"key": "name",
"type": "string",
"placeholder": {
"en": "Name on the guidepost"
},
"addExtraTags": [
"noname="
]
},
"render": {
"en": "Name noted on the guidepost: {name}"
},
"mappings": [
{
"if": "noname=yes",
"then": {
"en": "There is no name noted on this guidepost"
}
},
{
"addExtraTags": [
"name="
]
}
]
},
{
"id": "ref",
"question": {
"en": "What is the reference number of this guidepost?"
},
"freeform": {
"key": "ref",
"type": "string",
"placeholder": {
"en": "Reference number of the guidepost"
},
"addExtraTags": [
"noref="
]
},
"render": {
"en": "Reference number of the guidepost: {ref}"
},
"mappings": [
{
"if": "noref=yes",
"then": {
"en": "There is no reference number noted on this guidepost"
},
"addExtraTags": [
"ref="
]
}
]
},
{
"id": "ele",
"question": {
"en": "What is the elevation noted on this guidepost?"
},
"freeform": {
"key": "ele",
"type": "float",
"placeholder": {
"en": "Elevation on the guidepost (in meters)"
},
"addExtraTags": [
"noele="
]
},
"render": {
"en": "Elevation noted on the guidepost: {ele} m"
},
"mappings": [
{
"if": "noele=yes",
"then": {
"en": "There is no elevation noted on this guidepost"
},
"addExtraTags": [
"ele="
]
}
]
}
],
"deletion": true,
@ -140,4 +232,4 @@
"enableImproveAccuracy": true,
"enableRelocation": false
}
}
}

View file

@ -21,17 +21,7 @@
"es": "Capa que muestra taquillas para recoger y enviar paquetes."
},
"source": {
"osmTags": {
"or": [
"amenity=parcel_locker",
{
"and": [
"amenity=vending_machine",
"vending=parcel_pickup;parcel_mail_in"
]
}
]
}
"osmTags": "amenity=parcel_locker"
},
"minzoom": 12,
"title": {
@ -259,9 +249,15 @@
"cs": "Z této schránky na balíky <b>nemůžete posílat balíky</b>",
"es": "No puedes enviar paquetes desde esta taquilla"
}
},
{
"if": "parcel_mail_in=returns_only",
"then": {
"en": "You can send packages from this parcel locker, but only for returns",
"nl": "Je kan pakk etten versturen vanuit deze pakketautomaat, maar alleen voor retouren"
}
}
],
"condition": "amenity=parcel_locker"
]
},
{
"id": "pickup",
@ -302,8 +298,7 @@
"es": "No puedes recoger paquetes de esta taquilla"
}
}
],
"condition": "amenity=parcel_locker"
]
}
],
"filter": [
@ -313,4 +308,4 @@
"allowMove": {
"enableImproveAccuracy": true
}
}
}

View file

@ -954,48 +954,48 @@
"id": "toilet-changing_table:location"
},
{
"labels": [
"relevant-questions"
],
"id": "toilet-handwashing",
"id": "toilet-supervised",
"question": {
"en": "Do these toilets have a sink to wash your hands?",
"nl": "Hebben deze toiletten een lavabo om de handen te wassen?",
"de": "Gibt es hier ein Handwaschbecken?",
"es": "¿Estos baños tienen un lavabo para lavarse las manos?",
"fr": "Ces toilettes ont-ils un lavabo pour se laver les mains ?",
"da": "Har disse toiletter en håndvask til at vaske hænder?",
"ca": "Aquests lavabos tenen una pica per a rentar-se les mans?",
"cs": "Mají tyto toalety umyvadlo na mytí rukou?"
"en": "Is this toilets supervised by a person?",
"nl": "Is er toezicht op deze toilet?"
},
"questionHint": {
"en": "This is typically a person tasked with keeping the toilets clean and collecting the fee",
"nl": "Deze persoon houdt typisch de toiletten proper en int het toiletgeld"
},
"mappings": [
{
"if": "toilets:handwashing=yes",
"if": "supervised=yes",
"then": {
"en": "These toilets have a sink to wash your hands",
"nl": "Deze toiletten hebben een lavabo waar men de handen kan wassen",
"de": "Die Toilette hat ein Handwaschbecken",
"es": "Estos baños tienen un lavabo para lavarse las manos",
"fr": "Ces toilettes ont un lavabo pour se laver les mains",
"da": "Dette toilet har en vask til at vaske dine hænder",
"ca": "Aquests lavabos tenen una pica per a rentar-se les mans",
"cs": "Tyto toalety mají umyvadlo na mytí rukou"
"en": "There is a person supervising these toilets during (most of) the opening hours",
"nl": "Er is een persoon die toezicht houdt op deze toiletten"
}
},
{
"if": "toilets:handwashing=no",
"if": "supervised=interval",
"then": {
"en": "These toilets <b>don't</b> have a sink to wash your hands",
"nl": "Deze toiletten hebben <b>geen</b> lavabo waar men de handen kan wassen",
"de": "Die Toilette hat <b>kein</b> Handwaschbecken",
"es": "Estos baños <b>no</b> tienen un lavabo para lavarse las manos",
"fr": "Ces toilettes <b>n'ont pas</b> de lavabo pour se laver les mains",
"da": "Disse toiletter <b> har ikke </b> en vask til at vaske dine hænder",
"ca": "Aquests lavabos <b>no</b> tenen una pica per a rentar-se les mans",
"cs": "Tyto toalety <b>nemají umyvadlo na mytí rukou</b>"
"en": "There is a person supervising these toilets, but they are present only during certain times of the opening hours",
"nl": "Er is een persoon die toezicht houdt op deze toiletten, maar deze is slechts op enkele vaste momenten aanwezig"
}
},
{
"if": "supervised=no",
"then": {
"en": "These toilets are not supervised",
"nl": "Er is geen persoon die toezicht houdt"
}
}
]
],
"condition": {
"and": [
{
"or": [
"access=yes",
"access="
]
}
]
}
},
{
"id": "toilet-has-paper",
@ -1047,6 +1047,96 @@
]
}
},
{
"labels": [
"relevant-questions"
],
"id": "toilet-handwashing",
"question": {
"en": "Do these toilets have a sink to wash your hands?",
"nl": "Hebben deze toiletten een lavabo om de handen te wassen?",
"de": "Gibt es hier ein Handwaschbecken?",
"es": "¿Estos baños tienen un lavabo para lavarse las manos?",
"fr": "Ces toilettes ont-ils un lavabo pour se laver les mains ?",
"da": "Har disse toiletter en håndvask til at vaske hænder?",
"ca": "Aquests lavabos tenen una pica per a rentar-se les mans?",
"cs": "Mají tyto toalety umyvadlo na mytí rukou?"
},
"mappings": [
{
"if": "toilets:handwashing=yes",
"then": {
"en": "These toilets have a sink to wash your hands",
"nl": "Deze toiletten hebben een lavabo waar men de handen kan wassen",
"de": "Die Toilette hat ein Handwaschbecken",
"es": "Estos baños tienen un lavabo para lavarse las manos",
"fr": "Ces toilettes ont un lavabo pour se laver les mains",
"da": "Dette toilet har en vask til at vaske dine hænder",
"ca": "Aquests lavabos tenen una pica per a rentar-se les mans",
"cs": "Tyto toalety mají umyvadlo na mytí rukou"
}
},
{
"if": "toilets:handwashing=no",
"then": {
"en": "These toilets <b>don't</b> have a sink to wash your hands",
"nl": "Deze toiletten hebben <b>geen</b> lavabo waar men de handen kan wassen",
"de": "Die Toilette hat <b>kein</b> Handwaschbecken",
"es": "Estos baños <b>no</b> tienen un lavabo para lavarse las manos",
"fr": "Ces toilettes <b>n'ont pas</b> de lavabo pour se laver les mains",
"da": "Disse toiletter <b> har ikke </b> en vask til at vaske dine hænder",
"ca": "Aquests lavabos <b>no</b> tenen una pica per a rentar-se les mans",
"cs": "Tyto toalety <b>nemají umyvadlo na mytí rukou</b>"
}
}
]
},
{
"id": "toilet-drying",
"question": {
"en": "Do these toilets have a device to dry your hands?",
"nl": "Hebben deze toiletten een apparaat om je handen te drogen?"
},
"multiAnswer": true,
"mappings": [
{
"if": "toilets:hands_drying=electric_hand_dryer",
"then": {
"en": "Electric hand dryers are available for drying hands.",
"nl": "Elektrische handdrogers zijn beschikbaar om handen te drogen."
}
},
{
"if": "toilets:hands_drying=paper_towel",
"then": {
"en": "Paper towels are available for drying hands.",
"nl": "Papieren wegwerphanddoeken zijn beschikbaar om handen te drogen."
}
},
{
"if": "toilets:hands_drying=towel_cabinet",
"then": {
"en": "A towel roll cabinet is available for drying hands",
"nl": "Een apparaat met een handdoekrol is beschikbaar om handen te drogen"
}
},
{
"if": "toilets:hands_drying=towel",
"then": {
"en": "A fabric towel available to dry your hands.",
"nl": "Een stoffen handdoek is beschikbaar om handen te drogen."
}
},
{
"if": "toilets:hands_drying=no",
"then": {
"en": "There are no hand drying facilities available.",
"nl": "Er zijn geen handdroogvoorzieningen beschikbaar."
}
}
],
"condition": "toilets:handwashing=yes"
},
"description"
],
"filter": [

View file

@ -379,7 +379,8 @@
"religion!="
]
}
}
},
"level"
],
"deletion": {
"softDeletionTags": {

View file

@ -451,12 +451,6 @@
"authors": [],
"sources": []
},
{
"path": "gear.svg",
"license": "TRIVIAL",
"authors": [],
"sources": []
},
{
"path": "gender_bi.svg",
"license": "CC0-1.0",
@ -1103,6 +1097,17 @@
],
"sources": []
},
{
"path": "snowflake.svg",
"license": "CC0-1.0",
"authors": [
"Schnouf25",
"Razorbliss"
],
"sources": [
"https://commons.wikimedia.org/wiki/File:Snow_flake.svg"
]
},
{
"path": "speech_bubble.svg",
"license": "CC-BY-4.0",

41
assets/svg/snowflake.svg Normal file
View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="500"
height="500"
viewBox="0 0 500 500"
fill="none"
version="1.1"
id="svg1"
sodipodi:docname="snowflake.svg"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="0.31068504"
inkscape:cx="82.07669"
inkscape:cy="856.17253"
inkscape:window-width="3072"
inkscape:window-height="1659"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<path
d="m 470.00001,218.85 -82.564,-46.95 m 0,0 V 78.1 m 0,93.8 82.564,-46.9 m -82.564,46.9 L 30.000014,375 m 0,-93.85 82.563596,46.95 v 93.8 m 220.0004,-375 -82.564,46.95 -82.5636,-46.95 m 0,406.2 82.5636,-46.95 82.564,46.95 m -220.0004,-375 v 93.8 m 0,0 -82.563596,46.95 M 112.56361,171.9 30.000014,125 m 82.563596,46.9 357.4364,203.1 m -82.564,46.9 v -93.8 l 82.564,-46.95 M 250.00001,0 v 500"
stroke="#000000"
stroke-width="26.6666"
stroke-miterlimit="10"
id="path1" />
</svg>

After

(image error) Size: 1.5 KiB

View file

@ -0,0 +1,2 @@
SPDX-FileCopyrightText: Schnouf25; Razorbliss
SPDX-License-Identifier: CC0-1.0

View file

@ -19,6 +19,50 @@
"shortDescription": {
"nl": "Grb import helper tool"
},
"popup": [
{
"id": "wikilink-needed",
"condition": "_description!~.*https://wiki.openstreetmap.org/wiki/WikiProject_Belgium/Building_and_address_import.*",
"dismissable": false,
"title": {
"render": {
"en": "Profile mention obligated",
"nl": "Link op profiel verplicht"
}
},
"body": [
{
"render": {
"special": {
"type": "link",
"href": "https://www.openstreetmap.org/profile/edit",
"text": {
"en": "Edit your user profile",
"nl": "Pas je profiel aan"
}
},
"after": {
"en": "to include the link <span class='literal-code'>https://wiki.openstreetmap.org/wiki/WikiProject_Belgium/Building_and_address_import</code>",
"nl": " en voeg deze link toe: <span class='literal-code'>https://wiki.openstreetmap.org/wiki/WikiProject_Belgium/Building_and_address_import</code>"
}
}
},
{
"id": "reload_profile",
"render": {
"special": {
"type": "login_button",
"force": "yes",
"message": {
"en": "Reload your profile",
"nl": "Herlaad je profiel"
}
}
}
}
]
}
],
"icon": "./assets/themes/grb/logo.svg",
"startZoom": 9,
"startLat": 51.0249,

View file

@ -612,6 +612,10 @@
{
"if": "theme=width",
"then": "./assets/themes/width/icon.svg"
},
{
"if": "theme=winter_service",
"then": "./assets/svg/snowflake.svg"
}
]
}

View file

@ -211,184 +211,109 @@
"allowMove": false
},
{
"id": "all_streets",
"isCounted": false,
"name": {
"en": "All streets",
"nl": "Alle straten",
"ru": "Все улицы",
"zh_Hant": "所有道路",
"hu": "Minden utca",
"de": "Alle Straßen",
"ca": "Tots els carrers",
"es": "Todas las calles",
"fr": "Toutes les rues",
"nb_NO": "Alle gater",
"da": "Alle gader",
"pa_PK": "ساریاں سڑکاں",
"cs": "Všechny ulice",
"it": "Tutte le strade",
"pl": "Wszystkie ulice",
"ko": "모든 거리"
},
"source": {
"osmTags": {
"and": [
"highway!=",
"service!=driveway",
"highway!=platform"
]
}
},
"minzoom": 18,
"title": {
"render": {
"en": "Street",
"nl": "Straat",
"ru": "Улица",
"zh_Hant": "照明",
"hu": "Utca",
"de": "Straße",
"ca": "Carrer",
"nb_NO": "Gate",
"fr": "Rue",
"da": "Gade",
"pa_PK": "سڑک",
"es": "Calle",
"cs": "Ulice",
"eu": "Kalea",
"it": "Strada",
"pl": "Ulica",
"ko": "거리"
},
"mappings": [
"builtin": "all_streets",
"override": {
"tagRenderings+": [
{
"if": "name~*",
"then": "{name}"
}
]
},
"tagRenderings": [
"images",
{
"id": "lit",
"question": {
"en": "Is this street lit?",
"nl": "Is deze straat verlicht?",
"zh_Hant": "這道路有照明嗎?",
"hu": "Ki van-e világítva ez az utca?",
"de": "Ist diese Straße beleuchtet?",
"nb_NO": "Er denne gaten belyst?",
"fr": "Cette rue est-elle éclairée ?",
"da": "Er denne gade oplyst?",
"ca": "Aquest carrer està il·luminat?",
"es": "¿Está iluminada esta calle?",
"cs": "Je tato ulice osvětlená?",
"it": "Questa strada è illuminata?",
"pl": "Czy ta ulica jest oświetlona?",
"ko": "이 거리는 밝나요?"
},
"mappings": [
{
"if": "lit=yes",
"then": {
"en": "This street is lit",
"nl": "Deze straat is verlicht",
"zh_Hant": "這道路有照明",
"hu": "Ez az utca ki van világítva",
"de": "Diese Straße ist beleuchtet",
"es": "Esta calle está iluminada",
"nb_NO": "Denne gaten er belyst",
"fr": "Cette rue est éclairée",
"da": "Denne gade er oplyst",
"ca": "Aquest carrer està il·luminat",
"cs": "Tato ulice je osvětlená",
"it": "Questa strada è illuminata",
"pl": "Ta ulica jest oświetlona",
"ko": "이 거리는 밝습니다"
}
"id": "lit",
"question": {
"en": "Is this street lit?",
"nl": "Is deze straat verlicht?",
"zh_Hant": "這道路有照明嗎?",
"hu": "Ki van-e világítva ez az utca?",
"de": "Ist diese Straße beleuchtet?",
"nb_NO": "Er denne gaten belyst?",
"fr": "Cette rue est-elle éclairée ?",
"da": "Er denne gade oplyst?",
"ca": "Aquest carrer està il·luminat?",
"es": "¿Está iluminada esta calle?",
"cs": "Je tato ulice osvětlená?",
"it": "Questa strada è illuminata?",
"pl": "Czy ta ulica jest oświetlona?",
"ko": "이 거리는 밝나요?"
},
{
"if": "lit=no",
"then": {
"en": "This street is not lit",
"nl": "Deze straat is niet verlicht",
"zh_Hant": "這道路沒有照明",
"hu": "Ez az utca nincs kivilágítva",
"de": "Diese Straße ist nicht beleuchtet",
"es": "Esta calle no está iluminada",
"nb_NO": "Denne gaten er ikke belyst",
"fr": "Cette rue nest pas éclairée",
"da": "Denne gade er ikke oplyst",
"ca": "Aquest carrer no està il·luminat",
"cs": "Tato ulice není osvětlená",
"it": "Questa strada non è illuminata",
"pl": "Ta ulica nie jest oświetlona",
"ko": "이 거리는 밝지 않습니다"
}
},
{
"if": "lit=sunset-sunrise",
"then": {
"en": "This street is lit at night",
"nl": "Deze straat is 's nachts verlicht",
"zh_Hant": "這道路晚上有照明",
"hu": "Ez az utca éjjel ki van világítva",
"de": "Diese Straße ist nachts beleuchtet",
"nb_NO": "Denne gaten er belyst nattestid",
"fr": "Cette rue est éclairée la nuit",
"da": "Denne gade er oplyst om natten",
"ca": "Aquest carrer està il·luminat per la nit",
"es": "Esta calle está iluminada por la noche",
"cs": "Tato ulice je v noci osvětlená",
"it": "Questa strada è illuminata di sera",
"pl": "Ta ulica jest oświetlona w nocy",
"ko": "이 거리는 밤에 밝습니다"
},
"hideInAnswer": true
},
{
"if": "lit=24/7",
"then": {
"en": "This street is lit 24/7",
"nl": "Deze straat is 24/7 verlicht",
"zh_Hant": "這道路 24/7 有照明",
"hu": "Ez az utca éjjel-nappal ki van világítva",
"de": "Diese Straße ist durchgehend beleuchtet",
"nb_NO": "Denne gaten er belyst døgnet rundt",
"fr": "Cette rue est éclairée en permanence",
"da": "Denne gade er oplyst 24/7",
"ca": "Aquest carrer està il·luminat 24/7",
"es": "Esta calle está iluminada 24/7",
"cs": "Tato ulice je osvětlena 24/7",
"it": "Questa strada è illuminata 24 ore su 24",
"pl": "Ta ulica jest oświetlona 24/7",
"ko": "이 거리는 24시간 밝습니다"
}
}
]
}
],
"allowSplit": true,
"pointRendering": null,
"lineRendering": [
{
"color": {
"render": "#a9a9a9",
"mappings": [
{
"if": "lit=no",
"then": "#303030"
"if": "lit=yes",
"then": {
"en": "This street is lit",
"nl": "Deze straat is verlicht",
"zh_Hant": "這道路有照明",
"hu": "Ez az utca ki van világítva",
"de": "Diese Straße ist beleuchtet",
"es": "Esta calle está iluminada",
"nb_NO": "Denne gaten er belyst",
"fr": "Cette rue est éclairée",
"da": "Denne gade er oplyst",
"ca": "Aquest carrer està il·luminat",
"cs": "Tato ulice je osvětlená",
"it": "Questa strada è illuminata",
"pl": "Ta ulica jest oświetlona",
"ko": "이 거리는 밝습니다"
}
},
{
"if": "lit=yes",
"then": "#ff0"
"if": "lit=no",
"then": {
"en": "This street is not lit",
"nl": "Deze straat is niet verlicht",
"zh_Hant": "這道路沒有照明",
"hu": "Ez az utca nincs kivilágítva",
"de": "Diese Straße ist nicht beleuchtet",
"es": "Esta calle no está iluminada",
"nb_NO": "Denne gaten er ikke belyst",
"fr": "Cette rue nest pas éclairée",
"da": "Denne gade er ikke oplyst",
"ca": "Aquest carrer no està il·luminat",
"cs": "Tato ulice není osvětlená",
"it": "Questa strada non è illuminata",
"pl": "Ta ulica nie jest oświetlona",
"ko": "이 거리는 밝지 않습니다"
}
},
{
"if": "lit=sunset-sunrise",
"then": {
"en": "This street is lit at night",
"nl": "Deze straat is 's nachts verlicht",
"zh_Hant": "這道路晚上有照明",
"hu": "Ez az utca éjjel ki van világítva",
"de": "Diese Straße ist nachts beleuchtet",
"nb_NO": "Denne gaten er belyst nattestid",
"fr": "Cette rue est éclairée la nuit",
"da": "Denne gade er oplyst om natten",
"ca": "Aquest carrer està il·luminat per la nit",
"es": "Esta calle está iluminada por la noche",
"cs": "Tato ulice je v noci osvětlená",
"it": "Questa strada è illuminata di sera",
"pl": "Ta ulica jest oświetlona w nocy",
"ko": "이 거리는 밤에 밝습니다"
},
"hideInAnswer": true
},
{
"if": "lit=24/7",
"then": {
"en": "This street is lit 24/7",
"nl": "Deze straat is 24/7 verlicht",
"zh_Hant": "這道路 24/7 有照明",
"hu": "Ez az utca éjjel-nappal ki van világítva",
"de": "Diese Straße ist durchgehend beleuchtet",
"nb_NO": "Denne gaten er belyst døgnet rundt",
"fr": "Cette rue est éclairée en permanence",
"da": "Denne gade er oplyst 24/7",
"ca": "Aquest carrer està il·luminat 24/7",
"es": "Esta calle está iluminada 24/7",
"cs": "Tato ulice je osvětlena 24/7",
"it": "Questa strada è illuminata 24 ore su 24",
"pl": "Ta ulica jest oświetlona 24/7",
"ko": "이 거리는 24시간 밝습니다"
}
}
]
}
}
],
"allowMove": false
]
}
}
]
}
}

View file

@ -14,6 +14,7 @@
"artwork"
],
"override": {
"isCounted": false,
"minzoom": 18
}
}

View file

@ -0,0 +1,132 @@
{
"credits": "Robin van der Linde",
"credits:uid": 5093765,
"id": "winter_service",
"title": {
"en": "Winter Service"
},
"icon": "./assets/svg/snowflake.svg",
"layers": [
{
"id": "serviced_streets",
"name": {
"en": "Serviced streets"
},
"description": {
"en": "Streets that have some form of winter service"
},
"source": {
"osmTags": {
"and": [
"highway!=",
"service!=driveway",
"highway!=platform",
{
"or": [
"winter_service=yes",
"winter_service=limited"
]
}
]
}
},
"minzoom": 16,
"title": {
"render": {
"en": "Serviced street"
},
"mappings": [
{
"if": "name~*",
"then": "{name}"
}
]
},
"lineRendering": [
{
"color": {
"mappings": [
{
"if": "winter_service=yes",
"then": "#00ff00"
},
{
"if": "winter_service=limited",
"then": "#ffff00"
},
{
"if": "winter_service=no",
"then": "#ff0000"
}
]
}
}
],
"pointRendering": null,
"allowMove": false,
"tagRenderings": []
},
{
"builtin": "all_streets",
"override": {
"lineRendering": [
{
"color": {
"mappings": [
{
"if": "winter_service=yes",
"then": "#00ff00"
},
{
"if": "winter_service=limited",
"then": "#ffff00"
},
{
"if": "winter_service=no",
"then": "#ff0000"
}
]
}
}
]
}
}
],
"description": {
"en": "A map showing roads and whether they're cleared in winter"
},
"overrideAll": {
"tagRenderings+": [
{
"id": "winter_service",
"question": {
"en": "Is this road serviced (e.g. cleared of snow) in winter?"
},
"mappings": [
{
"if": "winter_service=yes",
"then": {
"en": "This road is serviced in winter"
},
"icon": "snowflake:green"
},
{
"if": "winter_service=limited",
"then": {
"en": "This road is serviced in winter, but only to a limited extent. This is often signposted as well."
},
"icon": "snowflake:yellow"
},
{
"if": "winter_service=no",
"then": {
"en": "This road is not serviced in winter"
},
"icon": "snowflake:red"
}
]
}
]
},
"hideFromOverview": true
}

View file

@ -357,6 +357,12 @@
"render": "Telefèric {name}"
}
},
"all_streets": {
"name": "Tots els carrers",
"title": {
"render": "Carrer"
}
},
"ambulancestation": {
"description": "Una estició d'abulàncies és una àrea per a emmagatzemar ambulàncies, equipament mèdic, equips de protecció personal i altres subministraments mèdics.",
"name": "Mapa d'estacions d'ambulàncies",
@ -3814,23 +3820,6 @@
},
"question": "Aquest creuament té superfície podotàctil?"
},
"crossing-type": {
"mappings": {
"0": {
"then": "Creuament, sense semàfors"
},
"1": {
"then": "Creuament amb semàfors"
},
"2": {
"then": "Pas de zebra"
},
"3": {
"then": "Creuament sense senyalitzar"
}
},
"question": "Quin tipus de creuament és aquest?"
},
"crossing-vibration": {
"mappings": {
"0": {
@ -5245,7 +5234,7 @@
}
},
"title": {
"render": "Entrada"
"render": "Entrada {ref}"
}
},
"etymology": {

View file

@ -357,6 +357,12 @@
"render": "Dráha {name}"
}
},
"all_streets": {
"name": "Všechny ulice",
"title": {
"render": "Ulice"
}
},
"ambulancestation": {
"description": "Stanice záchranné služby je prostor pro umístění sanitních vozidel, zdravotnického vybavení, osobních ochranných prostředků a dalšího zdravotnického materiálu.",
"name": "Mapa stanic rychlé záchranné služby",
@ -3842,23 +3848,6 @@
},
"question": "Má tento přechod hmatovou dlažbu?"
},
"crossing-type": {
"mappings": {
"0": {
"then": "Přechod bez světelné signalizace"
},
"1": {
"then": "Přechod se světelnou signalizací"
},
"2": {
"then": "Zebra přechod"
},
"3": {
"then": "Přechod bez označení přechodu"
}
},
"question": "Co je to za přechod?"
},
"crossing-vibration": {
"mappings": {
"0": {
@ -5049,7 +5038,7 @@
}
},
"title": {
"render": "Vchod"
"render": "Vchod {ref}"
}
},
"etymology": {

View file

@ -356,7 +356,7 @@
"entrance": {
"name": "Mynedfa",
"title": {
"render": "Mynedfa"
"render": "Mynedfa {ref}"
}
},
"extinguisher": {

View file

@ -24,6 +24,12 @@
"render": "Kendt adresse"
}
},
"all_streets": {
"name": "Alle gader",
"title": {
"render": "Gade"
}
},
"ambulancestation": {
"description": "En ambulancestation er et område til opbevaring af ambulancekøretøjer, medicinsk udstyr, personlige værnemidler og andre medicinske forsyninger.",
"name": "Kort over ambulancestationer",
@ -1564,7 +1570,7 @@
}
},
"title": {
"render": "Indgang"
"render": "Indgang {ref}"
}
},
"etymology": {

View file

@ -357,6 +357,12 @@
"render": "Seilbahn {name}"
}
},
"all_streets": {
"name": "Alle Straßen",
"title": {
"render": "Straße"
}
},
"ambulancestation": {
"description": "Eine Rettungswache ist ein Ort, an dem Rettungsfahrzeuge, medizinische Ausrüstung, persönliche Schutzausrüstung und anderes medizinisches Material untergebracht sind.",
"name": "Rettungswachen",
@ -3766,23 +3772,6 @@
},
"question": "Gibt es an dieser Kreuzung ein Blindenleitsystem?"
},
"crossing-type": {
"mappings": {
"0": {
"then": "Kreuzungen ohne Ampeln"
},
"1": {
"then": "Kreuzungen mit Ampeln"
},
"2": {
"then": "Zebrastreifen"
},
"3": {
"then": "Kreuzung ohne Kreuzungsmarkierungen"
}
},
"question": "Was ist das für eine Kreuzung?"
},
"crossing-vibration": {
"mappings": {
"0": {
@ -5204,7 +5193,7 @@
}
},
"title": {
"render": "Eingang"
"render": "Eingang {ref}"
}
},
"etymology": {

View file

@ -357,6 +357,13 @@
"render": "Aerialway {name}"
}
},
"all_streets": {
"description": "Layer with (almost) all streets",
"name": "All streets",
"title": {
"render": "Street"
}
},
"ambulancestation": {
"description": "An ambulance station is an area for storage of ambulance vehicles, medical equipment, personal protective equipment, and other medical supplies.",
"name": "Map of ambulance stations",
@ -3885,27 +3892,13 @@
},
"2": {
"then": "This crossing has tactile paving, but is not correct"
},
"3": {
"then": "This crrosing has tactile paving, but only on one side"
}
},
"question": "Does this crossing have tactile paving?"
},
"crossing-type": {
"mappings": {
"0": {
"then": "Crossing, without traffic lights"
},
"1": {
"then": "Crossing with traffic signals"
},
"2": {
"then": "Zebra crossing"
},
"3": {
"then": "Crossing without crossing markings"
}
},
"question": "What kind of crossing is this?"
},
"crossing-vibration": {
"mappings": {
"0": {
@ -3967,6 +3960,20 @@
},
"question": "What kind of markings does this crossing have?",
"render": "This crossing has {crossing:markings} markings"
},
"signals": {
"mappings": {
"0": {
"then": "There are no traffic signals at this crossing"
},
"1": {
"then": "There are traffic signals at this crossing"
},
"2": {
"then": "There are traffic signals at this crossing"
}
},
"question": "Are there traffic signals at this crossing?"
}
},
"title": {
@ -5321,13 +5328,22 @@
"question": "What is the height of this kerb?",
"render": "The kerb height of this door is {kerb:height}"
},
"ref": {
"mappings": {
"0": {
"then": "No reference number"
}
},
"question": "Does this door have a reference number?",
"render": "This door has <b>{ref}</b> as reference number"
},
"width": {
"question": "What is the width of this door/entrance?",
"render": "This door has a width of {canonical(width)}"
}
},
"title": {
"render": "Entrance"
"render": "Entrance {ref}"
}
},
"etymology": {
@ -6385,6 +6401,27 @@
}
},
"tagRenderings": {
"ele": {
"freeform": {
"placeholder": "Elevation on the guidepost (in meters)"
},
"question": "What is the elevation noted on this guidepost?",
"render": "Elevation noted on the guidepost: {ele} m"
},
"name": {
"freeform": {
"placeholder": "Name on the guidepost"
},
"question": "What is the name noted on this guidepost?",
"render": "Name noted on the guidepost: {name}"
},
"ref": {
"freeform": {
"placeholder": "Reference number of the guidepost"
},
"question": "What is the reference number of this guidepost?",
"render": "Reference number of the guidepost: {ref}"
},
"type": {
"mappings": {
"0": {
@ -7937,6 +7974,9 @@
},
"1": {
"then": "You <b>can't</b> send packages from this parcel locker"
},
"2": {
"then": "You can send packages from this parcel locker, but only for returns"
}
},
"question": "Can you send packages from this parcel locker?"
@ -12133,6 +12173,26 @@
"question": "How much does one have to pay for these toilets?",
"render": "The fee is {charge}"
},
"toilet-drying": {
"mappings": {
"0": {
"then": "Electric hand dryers are available for drying hands."
},
"1": {
"then": "Paper towels are available for drying hands."
},
"2": {
"then": "A towel roll cabinet is available for drying hands"
},
"3": {
"then": "A fabric towel available to dry your hands."
},
"4": {
"then": "There are no hand drying facilities available."
}
},
"question": "Do these toilets have a device to dry your hands?"
},
"toilet-handwashing": {
"mappings": {
"0": {
@ -12162,6 +12222,21 @@
}
}
},
"toilet-supervised": {
"mappings": {
"0": {
"then": "There is a person supervising these toilets during (most of) the opening hours"
},
"1": {
"then": "There is a person supervising these toilets, but they are present only during certain times of the opening hours"
},
"2": {
"then": "These toilets are not supervised"
}
},
"question": "Is this toilets supervised by a person?",
"questionHint": "This is typically a person tasked with keeping the toilets clean and collecting the fee"
},
"toilets-changing-table": {
"mappings": {
"0": {

View file

@ -339,6 +339,12 @@
"render": "Teleférico {name}"
}
},
"all_streets": {
"name": "Todas las calles",
"title": {
"render": "Calle"
}
},
"ambulancestation": {
"description": "Una estación de ambulancias es un área para el almacenamiento de vehículos de ambulancia, equipo médico, equipo de protección personal y otros suministros médicos.",
"name": "Mapa de estaciones de ambulancias",
@ -3537,23 +3543,6 @@
},
"question": "¿Este cruce tiene pavimento táctil?"
},
"crossing-type": {
"mappings": {
"0": {
"then": "Cruce, sin semáforos"
},
"1": {
"then": "Cruce con semáforos"
},
"2": {
"then": "Paso de peatones"
},
"3": {
"then": "Cruce sin marcas de cruce"
}
},
"question": "¿Qué tipo de cruce es este?"
},
"crossing-vibration": {
"mappings": {
"0": {
@ -4903,7 +4892,7 @@
}
},
"title": {
"render": "Entrada"
"render": "Entrada {ref}"
}
},
"etymology": {

View file

@ -262,6 +262,12 @@
}
}
},
"all_streets": {
"name": "Toutes les rues",
"title": {
"render": "Rue"
}
},
"ambulancestation": {
"description": "Une station dambulance est un lieu où sont stockés les véhicules durgence ainsi que de léquipement médical.",
"name": "Couche des ambulances",
@ -2528,23 +2534,6 @@
},
"question": "Est-ce que ce passage piéton a une surface podotactile ?"
},
"crossing-type": {
"mappings": {
"0": {
"then": "Passage piéton, sans feux de signalisation"
},
"1": {
"then": "Passage piéton avec des feux de signalisation"
},
"2": {
"then": "Passage piéton"
},
"3": {
"then": "Passage piéton sans marquages"
}
},
"question": "Quel type de passage piéton est-ce ?"
},
"crossing-vibration": {
"mappings": {
"0": {
@ -3467,7 +3456,7 @@
}
},
"title": {
"render": "Entrée"
"render": "Entrée {ref}"
}
},
"etymology": {

View file

@ -343,6 +343,13 @@
"render": "Kabelbaan {name}"
}
},
"all_streets": {
"description": "Laag met (bijna) alle straten",
"name": "Alle straten",
"title": {
"render": "Straat"
}
},
"ambulancestation": {
"description": "Een ambulancestation is een plaats waar ambulances, medisch materiaal, persoonlijk beschermingsmateriaal en aanverwanten worden bewaard.",
"name": "Kaart van ambulancestations",
@ -3693,27 +3700,13 @@
},
"2": {
"then": "Deze oversteekplaats heeft een geleidelijn, die incorrect is."
},
"3": {
"then": "Deze oversteekplaats heeft een geleidelijn, maar slechts aan één kant"
}
},
"question": "Heeft deze oversteekplaats een geleidelijn?"
},
"crossing-type": {
"mappings": {
"0": {
"then": "Oversteekplaats, zonder verkeerslichten"
},
"1": {
"then": "Oversteekplaats met verkeerslichten"
},
"2": {
"then": "Zebrapad"
},
"3": {
"then": "Oversteekplaats zonder kruispuntmarkeringen"
}
},
"question": "Wat voor oversteekplaats is dit?"
},
"crossing-vibration": {
"mappings": {
"0": {
@ -3775,6 +3768,20 @@
},
"question": "Wat voor markering heeft deze oversteekplaats?",
"render": "Deze oversteekplaats heeft {crossing:markings} markeringen"
},
"signals": {
"mappings": {
"0": {
"then": "Er zijn geen verkeerslichten bij deze oversteekplaats"
},
"1": {
"then": "Er zijn verkeerslichten bij deze oversteekplaats"
},
"2": {
"then": "Er zijn verkeerslichten bij deze oversteekplaats"
}
},
"question": "Zijn er verkeerslichten bij deze oversteekplaats?"
}
},
"title": {
@ -4990,13 +4997,22 @@
"question": "Hoe hoog is de drempel?",
"render": "De drempel bij deze deur is {kerb:height}"
},
"ref": {
"mappings": {
"0": {
"then": "Geen referentienummer"
}
},
"question": "Heeft deze toegang een referentienummer?",
"render": "Deze deur heeft <b>{ref}</b> als referentienummer"
},
"width": {
"question": "Wat is de breedte van deze deur/toegang?",
"render": "Deze deur heeft een breedte van {canonical(width)}"
}
},
"title": {
"render": "Ingang"
"render": "Ingang {ref}"
}
},
"etymology": {
@ -6834,6 +6850,9 @@
},
"1": {
"then": "Je kan <b>geen</b> pakketten versturen vanuit deze pakketautomaat"
},
"2": {
"then": "Je kan pakk etten versturen vanuit deze pakketautomaat, maar alleen voor retouren"
}
},
"question": "Kan je pakketten versturen vanuit deze pakketautomaat?"
@ -9757,6 +9776,26 @@
"question": "Hoeveel moet men betalen om deze toiletten te gebruiken?",
"render": "De toiletten gebruiken kost {charge}"
},
"toilet-drying": {
"mappings": {
"0": {
"then": "Elektrische handdrogers zijn beschikbaar om handen te drogen."
},
"1": {
"then": "Papieren wegwerphanddoeken zijn beschikbaar om handen te drogen."
},
"2": {
"then": "Een apparaat met een handdoekrol is beschikbaar om handen te drogen"
},
"3": {
"then": "Een stoffen handdoek is beschikbaar om handen te drogen."
},
"4": {
"then": "Er zijn geen handdroogvoorzieningen beschikbaar."
}
},
"question": "Hebben deze toiletten een apparaat om je handen te drogen?"
},
"toilet-handwashing": {
"mappings": {
"0": {
@ -9786,6 +9825,21 @@
}
}
},
"toilet-supervised": {
"mappings": {
"0": {
"then": "Er is een persoon die toezicht houdt op deze toiletten"
},
"1": {
"then": "Er is een persoon die toezicht houdt op deze toiletten, maar deze is slechts op enkele vaste momenten aanwezig"
},
"2": {
"then": "Er is geen persoon die toezicht houdt"
}
},
"question": "Is er toezicht op deze toilet?",
"questionHint": "Deze persoon houdt typisch de toiletten proper en int het toiletgeld"
},
"toilets-changing-table": {
"mappings": {
"0": {

View file

@ -151,7 +151,7 @@
"entrance": {
"name": "دروازہ",
"title": {
"render": "دروازہ"
"render": "دروازہ{ref}"
}
},
"food": {

View file

@ -1881,7 +1881,7 @@
}
},
"title": {
"render": "Wejście"
"render": "Wejście {ref}"
}
},
"etymology": {

View file

@ -899,28 +899,26 @@
}
},
"2": {
"name": "Tots els carrers",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Aquest carrer està il·luminat"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Aquest carrer està il·luminat"
},
"1": {
"then": "Aquest carrer no està il·luminat"
},
"2": {
"then": "Aquest carrer està il·luminat per la nit"
},
"3": {
"then": "Aquest carrer està il·luminat 24/7"
}
},
"1": {
"then": "Aquest carrer no està il·luminat"
},
"2": {
"then": "Aquest carrer està il·luminat per la nit"
},
"3": {
"then": "Aquest carrer està il·luminat 24/7"
}
},
"question": "Aquest carrer està il·luminat?"
"question": "Aquest carrer està il·luminat?"
}
}
},
"title": {
"render": "Carrer"
}
}
},

View file

@ -1257,28 +1257,26 @@
}
},
"2": {
"name": "Všechny ulice",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Tato ulice je osvětlená"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Tato ulice je osvětlená"
},
"1": {
"then": "Tato ulice není osvětlená"
},
"2": {
"then": "Tato ulice je v noci osvětlená"
},
"3": {
"then": "Tato ulice je osvětlena 24/7"
}
},
"1": {
"then": "Tato ulice není osvětlená"
},
"2": {
"then": "Tato ulice je v noci osvětlená"
},
"3": {
"then": "Tato ulice je osvětlena 24/7"
}
},
"question": "Je tato ulice osvětlená?"
"question": "Je tato ulice osvětlená?"
}
}
},
"title": {
"render": "Ulice"
}
}
},

View file

@ -710,28 +710,26 @@
}
},
"2": {
"name": "Alle gader",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Denne gade er oplyst"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Denne gade er oplyst"
},
"1": {
"then": "Denne gade er ikke oplyst"
},
"2": {
"then": "Denne gade er oplyst om natten"
},
"3": {
"then": "Denne gade er oplyst 24/7"
}
},
"1": {
"then": "Denne gade er ikke oplyst"
},
"2": {
"then": "Denne gade er oplyst om natten"
},
"3": {
"then": "Denne gade er oplyst 24/7"
}
},
"question": "Er denne gade oplyst?"
"question": "Er denne gade oplyst?"
}
}
},
"title": {
"render": "Gade"
}
}
},

View file

@ -1238,28 +1238,26 @@
}
},
"2": {
"name": "Alle Straßen",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Diese Straße ist beleuchtet"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Diese Straße ist beleuchtet"
},
"1": {
"then": "Diese Straße ist nicht beleuchtet"
},
"2": {
"then": "Diese Straße ist nachts beleuchtet"
},
"3": {
"then": "Diese Straße ist durchgehend beleuchtet"
}
},
"1": {
"then": "Diese Straße ist nicht beleuchtet"
},
"2": {
"then": "Diese Straße ist nachts beleuchtet"
},
"3": {
"then": "Diese Straße ist durchgehend beleuchtet"
}
},
"question": "Ist diese Straße beleuchtet?"
"question": "Ist diese Straße beleuchtet?"
}
}
},
"title": {
"render": "Straße"
}
}
},

View file

@ -623,6 +623,30 @@
}
}
}
},
"popup": {
"0": {
"body": {
"0": {
"render": {
"special": {
"after": "to include the link <span class='literal-code'>https://wiki.openstreetmap.org/wiki/WikiProject_Belgium/Building_and_address_import</code>",
"text": "Edit your user profile"
}
}
},
"1": {
"render": {
"special": {
"msg": "Reload your profile"
}
}
}
},
"title": {
"render": "Profile mention obligated"
}
}
}
},
"guideposts": {
@ -1257,28 +1281,26 @@
}
},
"2": {
"name": "All streets",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "This street is lit"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "This street is lit"
},
"1": {
"then": "This street is not lit"
},
"2": {
"then": "This street is lit at night"
},
"3": {
"then": "This street is lit 24/7"
}
},
"1": {
"then": "This street is not lit"
},
"2": {
"then": "This street is lit at night"
},
"3": {
"then": "This street is lit 24/7"
}
},
"question": "Is this street lit?"
"question": "Is this street lit?"
}
}
},
"title": {
"render": "Street"
}
}
},
@ -1405,5 +1427,36 @@
"wayside_shrines": {
"description": "This map shows shrines found on the side of roads and paths, and allows adding new ones",
"title": "Wayside shrines"
},
"winter_service": {
"description": "A map showing roads and whether they're cleared in winter",
"layers": {
"0": {
"description": "Streets that have some form of winter service",
"name": "Serviced streets",
"title": {
"render": "Serviced street"
}
}
},
"overrideAll": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "This road is serviced in winter"
},
"1": {
"then": "This road is serviced in winter, but only to a limited extent. This is often signposted as well."
},
"2": {
"then": "This road is not serviced in winter"
}
},
"question": "Is this road serviced (e.g. cleared of snow) in winter?"
}
}
},
"title": "Winter Service"
}
}

View file

@ -1182,28 +1182,26 @@
}
},
"2": {
"name": "Todas las calles",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Esta calle está iluminada"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Esta calle está iluminada"
},
"1": {
"then": "Esta calle no está iluminada"
},
"2": {
"then": "Esta calle está iluminada por la noche"
},
"3": {
"then": "Esta calle está iluminada 24/7"
}
},
"1": {
"then": "Esta calle no está iluminada"
},
"2": {
"then": "Esta calle está iluminada por la noche"
},
"3": {
"then": "Esta calle está iluminada 24/7"
}
},
"question": "¿Está iluminada esta calle?"
"question": "¿Está iluminada esta calle?"
}
}
},
"title": {
"render": "Calle"
}
}
},

View file

@ -178,15 +178,6 @@
"sports": {
"title": "Kirolak"
},
"street_lighting": {
"layers": {
"2": {
"title": {
"render": "Kalea"
}
}
}
},
"trees": {
"title": "Zuhaitzak"
},

View file

@ -982,28 +982,26 @@
}
},
"2": {
"name": "Toutes les rues",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Cette rue est éclairée"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Cette rue est éclairée"
},
"1": {
"then": "Cette rue nest pas éclairée"
},
"2": {
"then": "Cette rue est éclairée la nuit"
},
"3": {
"then": "Cette rue est éclairée en permanence"
}
},
"1": {
"then": "Cette rue nest pas éclairée"
},
"2": {
"then": "Cette rue est éclairée la nuit"
},
"3": {
"then": "Cette rue est éclairée en permanence"
}
},
"question": "Cette rue est-elle éclairée ?"
"question": "Cette rue est-elle éclairée ?"
}
}
},
"title": {
"render": "Rue"
}
}
},

View file

@ -431,28 +431,26 @@
}
},
"2": {
"name": "Minden utca",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Ez az utca ki van világítva"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Ez az utca ki van világítva"
},
"1": {
"then": "Ez az utca nincs kivilágítva"
},
"2": {
"then": "Ez az utca éjjel ki van világítva"
},
"3": {
"then": "Ez az utca éjjel-nappal ki van világítva"
}
},
"1": {
"then": "Ez az utca nincs kivilágítva"
},
"2": {
"then": "Ez az utca éjjel ki van világítva"
},
"3": {
"then": "Ez az utca éjjel-nappal ki van világítva"
}
},
"question": "Ki van-e világítva ez az utca?"
"question": "Ki van-e világítva ez az utca?"
}
}
},
"title": {
"render": "Utca"
}
}
},

View file

@ -566,28 +566,26 @@
}
},
"2": {
"name": "Tutte le strade",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Questa strada è illuminata"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Questa strada è illuminata"
},
"1": {
"then": "Questa strada non è illuminata"
},
"2": {
"then": "Questa strada è illuminata di sera"
},
"3": {
"then": "Questa strada è illuminata 24 ore su 24"
}
},
"1": {
"then": "Questa strada non è illuminata"
},
"2": {
"then": "Questa strada è illuminata di sera"
},
"3": {
"then": "Questa strada è illuminata 24 ore su 24"
}
},
"question": "Questa strada è illuminata?"
"question": "Questa strada è illuminata?"
}
}
},
"title": {
"render": "Strada"
}
}
},

View file

@ -1168,28 +1168,26 @@
}
},
"2": {
"name": "모든 거리",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "이 거리는 밝습니다"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "이 거리는 밝습니다"
},
"1": {
"then": "이 거리는 밝지 않습니다"
},
"2": {
"then": "이 거리는 밤에 밝습니다"
},
"3": {
"then": "이 거리는 24시간 밝습니다"
}
},
"1": {
"then": "이 거리는 밝지 않습니다"
},
"2": {
"then": "이 거리는 밤에 밝습니다"
},
"3": {
"then": "이 거리는 24시간 밝습니다"
}
},
"question": "이 거리는 밝나요?"
"question": "이 거리는 밝나요?"
}
}
},
"title": {
"render": "거리"
}
}
},

View file

@ -440,28 +440,26 @@
}
},
"2": {
"name": "Alle gater",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Denne gaten er belyst"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Denne gaten er belyst"
},
"1": {
"then": "Denne gaten er ikke belyst"
},
"2": {
"then": "Denne gaten er belyst nattestid"
},
"3": {
"then": "Denne gaten er belyst døgnet rundt"
}
},
"1": {
"then": "Denne gaten er ikke belyst"
},
"2": {
"then": "Denne gaten er belyst nattestid"
},
"3": {
"then": "Denne gaten er belyst døgnet rundt"
}
},
"question": "Er denne gaten belyst?"
"question": "Er denne gaten belyst?"
}
}
},
"title": {
"render": "Gate"
}
}
},

View file

@ -669,6 +669,30 @@
}
}
},
"popup": {
"0": {
"body": {
"0": {
"render": {
"special": {
"after": " en voeg deze link toe: <span class='literal-code'>https://wiki.openstreetmap.org/wiki/WikiProject_Belgium/Building_and_address_import</code>",
"text": "Pas je profiel aan"
}
}
},
"1": {
"render": {
"special": {
"msg": "Herlaad je profiel"
}
}
}
},
"title": {
"render": "Link op profiel verplicht"
}
}
},
"shortDescription": "Grb import helper tool",
"title": "GRB import helper"
},
@ -1293,28 +1317,26 @@
}
},
"2": {
"name": "Alle straten",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Deze straat is verlicht"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Deze straat is verlicht"
},
"1": {
"then": "Deze straat is niet verlicht"
},
"2": {
"then": "Deze straat is 's nachts verlicht"
},
"3": {
"then": "Deze straat is 24/7 verlicht"
}
},
"1": {
"then": "Deze straat is niet verlicht"
},
"2": {
"then": "Deze straat is 's nachts verlicht"
},
"3": {
"then": "Deze straat is 24/7 verlicht"
}
},
"question": "Is deze straat verlicht?"
"question": "Is deze straat verlicht?"
}
}
},
"title": {
"render": "Straat"
}
}
},

View file

@ -158,12 +158,6 @@
"title": {
"render": "روشنی والی سڑک"
}
},
"2": {
"name": "ساریاں سڑکاں",
"title": {
"render": "سڑک"
}
}
},
"title": "سڑک دیاں روشنیاں"

View file

@ -855,28 +855,26 @@
}
},
"2": {
"name": "Wszystkie ulice",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "Ta ulica jest oświetlona"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "Ta ulica jest oświetlona"
},
"1": {
"then": "Ta ulica nie jest oświetlona"
},
"2": {
"then": "Ta ulica jest oświetlona w nocy"
},
"3": {
"then": "Ta ulica jest oświetlona 24/7"
}
},
"1": {
"then": "Ta ulica nie jest oświetlona"
},
"2": {
"then": "Ta ulica jest oświetlona w nocy"
},
"3": {
"then": "Ta ulica jest oświetlona 24/7"
}
},
"question": "Czy ta ulica jest oświetlona?"
"question": "Czy ta ulica jest oświetlona?"
}
}
},
"title": {
"render": "Ulica"
}
}
},

View file

@ -236,14 +236,6 @@
"title": "Спортивные объекты"
},
"street_lighting": {
"layers": {
"2": {
"name": "Все улицы",
"title": {
"render": "Улица"
}
}
},
"title": "Уличное освещение"
},
"surveillance": {

View file

@ -807,28 +807,26 @@
}
},
"2": {
"name": "所有道路",
"tagRenderings": {
"lit": {
"mappings": {
"0": {
"then": "這道路有照明"
"override": {
"tagRenderings+": {
"0": {
"mappings": {
"0": {
"then": "這道路有照明"
},
"1": {
"then": "這道路沒有照明"
},
"2": {
"then": "這道路晚上有照明"
},
"3": {
"then": "這道路 24/7 有照明"
}
},
"1": {
"then": "這道路沒有照明"
},
"2": {
"then": "這道路晚上有照明"
},
"3": {
"then": "這道路 24/7 有照明"
}
},
"question": "這道路有照明嗎?"
"question": "這道路有照明嗎?"
}
}
},
"title": {
"render": "照明"
}
}
},

View file

@ -9,16 +9,12 @@ import {
DoesImageExist,
PrevalidateTheme,
ValidateLayer,
ValidateThemeEnsemble,
ValidateThemeEnsemble
} from "../src/Models/ThemeConfig/Conversion/Validation"
import { Translation } from "../src/UI/i18n/Translation"
import { PrepareLayer } from "../src/Models/ThemeConfig/Conversion/PrepareLayer"
import { PrepareTheme } from "../src/Models/ThemeConfig/Conversion/PrepareTheme"
import {
Conversion,
DesugaringContext,
DesugaringStep,
} from "../src/Models/ThemeConfig/Conversion/Conversion"
import { Conversion, DesugaringContext, DesugaringStep } from "../src/Models/ThemeConfig/Conversion/Conversion"
import { Utils } from "../src/Utils"
import Script from "./Script"
import { AllSharedLayers } from "../src/Customizations/AllSharedLayers"
@ -501,7 +497,7 @@ class LayerOverviewUtils extends Script {
priviliged.delete(key)
})
// These two get a free pass
// These get a free pass
priviliged.delete("summary")
priviliged.delete("last_click")
priviliged.delete("search")

View file

@ -65,6 +65,16 @@ interface OsmUserInfo {
}
}
interface UserBlock {
"id": number,
"created_at": string,
"updated_at": string,
"ends_at": string,
"needs_view": boolean,
"user": { "uid": number, "user": string },
"creator": { "uid": number, "user": string }
}
export default interface UserDetails {
name: string
uid: number
@ -77,7 +87,8 @@ export default interface UserDetails {
account_created: string
tracesCount: number
description?: string
languages: string[]
languages: string[],
active_blocks: number
}
export type OsmServiceState = "online" | "readonly" | "offline" | "unknown" | "unreachable"
@ -309,6 +320,7 @@ export class OsmConnection {
account_created: user.account_created,
tracesCount: user.traces?.count ?? 0,
unreadMessages: user.messages.received?.unread ?? 0,
active_blocks: user.blocks.received.active ?? 0
}
this.userDetails.set(userdetails)
this.loadingStatus.setData("logged-in")
@ -559,6 +571,14 @@ export class OsmConnection {
})
}
/**
* Have you been banned by the DWG?
*/
public async getUserBlocks(): Promise<UserBlock[]> {
const raw = await this.interact("/user/blocks/active.json")
return JSON.parse(raw)["user_blocks"]
}
/**
* To be called by land.html
*/

View file

@ -191,6 +191,7 @@ export default class Constants {
"resolved",
"ring",
"scissors",
"snowflake",
"square",
"square_rounded",
"teardrop",

View file

@ -1,16 +1,6 @@
import {
Concat,
Conversion,
DesugaringContext,
DesugaringStep,
Each,
Fuse,
On,
Pass,
SetDefault,
} from "./Conversion"
import { Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault } from "./Conversion"
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import { PrepareLayer } from "./PrepareLayer"
import { PrepareLayer, RewriteSpecial } from "./PrepareLayer"
import { LayerConfigJson } from "../Json/LayerConfigJson"
import { Utils } from "../../../Utils"
import Constants from "../../Constants"
@ -40,7 +30,7 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
const knownLayers = Array.from(state.sharedLayers.keys())
const withDistance: [string, number][] = knownLayers.map((lname) => [
lname,
Utils.levenshteinDistance(name, lname),
Utils.levenshteinDistance(name, lname)
])
withDistance.sort((a, b) => a[1] - b[1])
const ids = withDistance.map((n) => n[0])
@ -130,9 +120,9 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
usedLabels.add(labels[forbiddenLabel])
context.info(
"Dropping tagRendering " +
tr["id"] +
" as it has a forbidden label: " +
labels[forbiddenLabel]
tr["id"] +
" as it has a forbidden label: " +
labels[forbiddenLabel]
)
continue
}
@ -150,10 +140,10 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
usedLabels.add(tr["group"])
context.info(
"Dropping tagRendering " +
tr["id"] +
" as its group `" +
tr["group"] +
"` is a forbidden label"
tr["id"] +
" as its group `" +
tr["group"] +
"` is a forbidden label"
)
continue
}
@ -164,8 +154,8 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
if (unused.length > 0) {
context.err(
"This theme specifies that certain tagrenderings have to be removed based on forbidden layers. One or more of these layers did not match any tagRenderings and caused no deletions: " +
unused.join(", ") +
"\n This means that this label can be removed or that the original tagRendering that should be deleted does not have this label anymore"
unused.join(", ") +
"\n This means that this label can be removed or that the original tagRendering that should be deleted does not have this label anymore"
)
}
found.tagRenderings = filtered
@ -205,10 +195,10 @@ export class AddDefaultLayers extends DesugaringStep<ThemeConfigJson> {
if (alreadyLoaded.has(v.id)) {
context.warn(
"Layout " +
context +
" already has a layer with name " +
v.id +
"; skipping inclusion of this builtin layer"
context +
" already has a layer with name " +
v.id +
"; skipping inclusion of this builtin layer"
)
continue
}
@ -352,10 +342,10 @@ class AddDependencyLayersToTheme extends DesugaringStep<ThemeConfigJson> {
.enters("layer dependency")
.err(
"Layer " +
dependency.neededLayer +
" is loaded because " +
dependency.reason +
"; so it must specify a `snapName`. This is used in the sentence `move this point to snap it to {snapName}`"
dependency.neededLayer +
" is loaded because " +
dependency.reason +
"; so it must specify a `snapName`. This is used in the sentence `move this point to snap it to {snapName}`"
)
}
}
@ -380,12 +370,12 @@ class AddDependencyLayersToTheme extends DesugaringStep<ThemeConfigJson> {
if (dep === undefined) {
const message = [
"Loading a dependency failed: layer " +
unmetDependency.neededLayer +
" is not found, neither as layer of " +
themeId +
" nor as builtin layer.",
unmetDependency.neededLayer +
" is not found, neither as layer of " +
themeId +
" nor as builtin layer.",
reason,
"Loaded layers are: " + alreadyLoaded.map((l) => l.id).join(","),
"Loaded layers are: " + alreadyLoaded.map((l) => l.id).join(",")
]
throw message.join("\n\t")
}
@ -395,7 +385,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<ThemeConfigJson> {
dep.description = reason
dependenciesToAdd.unshift({
config: dep,
reason,
reason
})
loadedLayerIds.add(dep.id)
unmetDependencies = unmetDependencies.filter(
@ -440,7 +430,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<ThemeConfigJson> {
return {
...theme,
layers: layers,
layers: layers
}
}
}
@ -510,10 +500,10 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<ThemeConfigJson>
context.warn(
"The theme " +
json.id +
" has an inline layer: " +
layer["id"] +
". This is discouraged."
json.id +
" has an inline layer: " +
layer["id"] +
". This is discouraged."
)
}
return json
@ -555,12 +545,12 @@ class PostvalidateTheme extends DesugaringStep<ThemeConfigJson> {
if (minZoomAll < layer.minzoom) {
context.err(
"There are multiple layers based on " +
basedOn +
". The layer with id " +
layer.id +
" has a minzoom of " +
layer.minzoom +
", and has a name set. Another similar layer has a lower minzoom. As such, the layer selection might show 'zoom in to see features' even though some of the features are already visible. Set `\"name\": null` for this layer and eventually remove the 'name':null for the other layer."
basedOn +
". The layer with id " +
layer.id +
" has a minzoom of " +
layer.minzoom +
", and has a name set. Another similar layer has a lower minzoom. As such, the layer selection might show 'zoom in to see features' even though some of the features are already visible. Set `\"name\": null` for this layer and eventually remove the 'name':null for the other layer."
)
}
}
@ -586,11 +576,11 @@ class PostvalidateTheme extends DesugaringStep<ThemeConfigJson> {
.enters("layers", config.id, "filter", "sameAs")
.err(
"The layer " +
config.id +
" follows the filter state of layer " +
sameAs +
", but no layer with this name was found.\n\tDid you perhaps mean one of: " +
closeLayers.slice(0, 3).join(", ")
config.id +
" follows the filter state of layer " +
sameAs +
", but no layer with this name was found.\n\tDid you perhaps mean one of: " +
closeLayers.slice(0, 3).join(", ")
)
}
}
@ -618,6 +608,13 @@ export class PrepareTheme extends Fuse<ThemeConfigJson> {
new SetDefault("socialImage", "assets/SocialImage.png", true),
// We expand all tagrenderings first...
new On("layers", new Each(new PrepareLayer(state))),
new On("popup", new Each(
new Fuse("Prepare popups",
new On("body", new Each(new RewriteSpecial())),
new On("title", new RewriteSpecial())
)
)),
// Then we apply the override all. We must first expand everything in case that we override something in an expanded tag
// Note that it'll cheat with tagRenderings+
new ApplyOverrideAll(),

View file

@ -3,6 +3,8 @@ import ExtraLinkConfigJson from "./ExtraLinkConfigJson"
import { RasterLayerProperties } from "../../RasterLayerProperties"
import { Translatable } from "./Translatable"
import { TagConfigJson } from "./TagConfigJson"
import { TagRenderingConfigJson } from "./TagRenderingConfigJson"
/**
* Defines the entire theme.
@ -468,4 +470,24 @@ export interface ThemeConfigJson {
* group: hidden
*/
_usedImages?: string[]
/**
* If set, an _additional_ popup will be shown under the theme introduction page.
*
* The embedded tagRenderingConfigs will be run against the settings-state of the contributor.
* If multiple popups are set, the first popup of the list will be rendered on top (and thus be seen first).
*/
popup?: {
/**
* ifset: the user can dismiss this message
*/
dismissible?: boolean
condition?: TagConfigJson
title: TagRenderingConfigJson,
body: TagRenderingConfigJson[],
/**
* id of the popup, mostly to keep the translations in check
*/
id: string,
}[]
}

View file

@ -701,12 +701,12 @@ export default class TagRenderingConfig {
*
* const config = new TagRenderingConfig({"id":"capacity", "render": "Fits {capcity} books",freeform: {"key":"capacity",type:"pnat"} })
* config.constructChangeSpecification("", undefined, undefined, {}) // => undefined
* config.constructChangeSpecification("5", undefined, undefined, {}).optimize() // => [new Tag("capacity", "5")]
* config.constructChangeSpecification("5", undefined, undefined, {}) // => [new Tag("capacity", "5")]
*
* // Should pick a mapping, even if freeform is usedconstructChange
* const config = new TagRenderingConfig({"id": "shop-types", render: "Shop type is {shop}", freeform: {key: "shop", addExtraTags:["fixme=freeform shop type used"]}, mappings:[{if: "shop=second_hand", then: "Second hand shop"}]})
* config.constructChangeSpecification("freeform", 1, undefined, {}).asHumanString(false, false, {}) // => [new Tag("shop","freeform",new Tag("fixme","freeform shop type used")]
* config.constructChangeSpecification("freeform", undefined, undefined, {}) // => [new Tag("shop","freeform), new Tag("fixme","freeform shop type used")]
* config.constructChangeSpecification("freeform", 1, undefined, {}) // => [new Tag("shop","freeform"),new Tag("fixme","freeform shop type used")]
* config.constructChangeSpecification("freeform", undefined, undefined, {}) // => [new Tag("shop","freeform"), new Tag("fixme","freeform shop type used")]
* config.constructChangeSpecification("second_hand", 1, undefined, {}) // => [new Tag("shop","second_hand")]
*
*

View file

@ -9,6 +9,10 @@ import LanguageUtils from "../../Utils/LanguageUtils"
import { RasterLayerProperties } from "../RasterLayerProperties"
import { Translatable } from "./Json/Translatable"
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
import TagRenderingConfig from "./TagRenderingConfig"
import { TagUtils } from "../../Logic/Tags/TagUtils"
import { TagRenderingConfigJson } from "./Json/TagRenderingConfigJson"
/**
* Minimal information about a theme
@ -93,6 +97,14 @@ export default class ThemeConfig implements ThemeInformation {
public readonly source: ThemeConfigJson
public readonly enableCache: boolean
public readonly popups: Readonly<{
id: string,
dismissible?: boolean,
condition: TagsFilter,
title: TagRenderingConfig,
body: TagRenderingConfig[]
}>[]
constructor(
json: ThemeConfigJson,
official = true,
@ -193,11 +205,26 @@ export default class ThemeConfig implements ThemeInformation {
icon: "./assets/svg/pop-out.svg",
href: "https://{basepath}/{theme}.html?lat={lat}&lon={lon}&z={zoom}&language={language}",
newTab: true,
requirements: ["iframe", "no-welcome-message"],
requirements: ["iframe", "no-welcome-message"]
},
context + ".extraLink"
)
this.popups = (json.popup ?? []).map((p, i) => {
const ctx = context + ".popup." + i
if (!p.id) {
throw (ctx + ": an id is required")
}
const body: TagRenderingConfigJson[] = Array.isArray(p.body) ? p.body : [p.body]
return {
id: p.id,
dismissible: p.dismissible ?? false,
condition: TagUtils.Tag(p.condition),
title: new TagRenderingConfig(p.title, ctx + ".title"),
body: body.map((body, i) => new TagRenderingConfig(body, ctx + ".body." + i))
}
})
this.hideFromOverview = json.hideFromOverview ?? false
this.lockLocation = <[[number, number], [number, number]]>json.lockLocation ?? undefined
this.enableUserBadge = json.enableUserBadge ?? true
@ -351,7 +378,7 @@ export default class ThemeConfig implements ThemeInformation {
// The 'favourite'-layer contains pretty much all images as it bundles all layers, so we exclude it
const jsonNoFavourites = {
...json,
layers: json.layers.filter((l) => l["id"] !== "favourite"),
layers: json.layers.filter((l) => l["id"] !== "favourite")
}
const usedImages = jsonNoFavourites._usedImages
usedImages.sort()

View file

@ -12,7 +12,7 @@ export default class WithContextLoader {
this._context = context
}
/** Given a key, gets the corresponding property from the json (or the default if not found
/** Given a key, gets the corresponding property from the json (or the default if not found)
*
* The found value is interpreted as a tagrendering and fetched/parsed
* */

View file

@ -6,18 +6,26 @@
export let osmConnection: OsmConnection
export let clss: string | undefined = undefined
/**
* Show the button, even though we are logged in
*/
export let forceShow: boolean = false
export let msg: String = undefined
if (osmConnection === undefined) {
console.error("No osmConnection passed into loginButton")
}
let isLoggedIn = osmConnection.isLoggedIn
</script>
{#if !$isLoggedIn}
{#if !$isLoggedIn || forceShow}
<button class={clss} on:click={() => osmConnection.AttemptLogin()} style="margin-left: 0">
<ArrowLeftOnRectangle class="m-1 w-12" />
<slot>
<Tr t={Translations.t.general.loginWithOpenStreetMap} />
{#if msg}
{msg}
{:else}
<Tr t={Translations.t.general.loginWithOpenStreetMap} />
{/if}
</slot>
</button>
{/if}

View file

@ -42,8 +42,8 @@
<Modal
open={_shown}
on:close={() => shown.set(false)}
outsideclose
on:close={() =>shown.set(false)}
outsideclose={dismissable}
size="xl"
{dismissable}
{defaultClass}

View file

@ -611,7 +611,6 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
if (!map) {
return
}
console.log("Bounds are", bbox?.asGeometry())
if (bbox) {
if (GeoOperations.surfaceAreaInSqMeters(bbox.asGeojsonCached()) > 1) {
map?.setMaxBounds(bbox.toLngLat())

View file

@ -111,12 +111,27 @@ export class SettingsVisualisations {
},
{
funcName: "login_button",
args: [],
args: [{
name: "force",
doc: "Always show this button, even if logged in"
}, {
name: "message",
doc: "Message to display on the button"
}],
docs: "Show a login button",
needsUrls: [],
group: "settings",
constr(state: SpecialVisualizationState): SvelteUIElement {
return new SvelteUIElement(LoginButton, { osmConnection: state.osmConnection })
constr(state: SpecialVisualizationState, _, args): SvelteUIElement {
const force = args[0].toLowerCase()
let msg = args[1]
if (msg === "") {
msg = undefined
}
return new SvelteUIElement(LoginButton, {
osmConnection: state.osmConnection,
msg,
forceShow: force === "yes" || force === "true"
})
},
},

View file

@ -49,6 +49,8 @@
import Loading from "./Base/Loading.svelte"
import { WithSearchState } from "../Models/ThemeViewState/WithSearchState"
import TitleHandler from "../Logic/Actors/TitleHandler"
import Popup from "./Base/Popup.svelte"
import TagRenderingAnswer from "./Popup/TagRendering/TagRenderingAnswer.svelte"
export let state: WithSearchState
new TitleHandler(state.selectedElement, state)
@ -76,6 +78,7 @@
let mapproperties: MapProperties = state.mapProperties
let searchOpened = state.searchState.showSearchDrawer
let metatags = state.userRelatedState.preferencesAsTags
Orientation.singleton.startMeasurements()
let slideDuration = 150 // ms
@ -148,7 +151,7 @@
const bottomRight = mlmap.unproject([rect.right, rect.bottom])
const bbox = new BBox([
[topLeft.lng, topLeft.lat],
[bottomRight.lng, bottomRight.lat],
[bottomRight.lng, bottomRight.lat]
])
state.visualFeedbackViewportBounds.setData(bbox)
}
@ -500,5 +503,24 @@
{/if}
{/if}
{#each theme.popups as popup}
{#if popup.condition.matchesProperties($metatags)}
<Popup shown={new UIEventSource(true)} dismissable={popup.dismissible}>
<TagRenderingAnswer slot="header" config={popup.title} {state}
tags={metatags}
layer={undefined}
selectedElement={({type: "Feature", properties: $metatags, geometry: {type: "Point", coordinates: [0,0]}})} />
<div class="flex flex-col">
{#each popup.body as body}
<TagRenderingAnswer config={body} {state}
tags={metatags}
layer={undefined}
selectedElement={({type: "Feature", properties: $metatags, geometry: {type: "Point", coordinates: [0,0]}})} />
{/each}
<span class="subtle">{popup.id}</span>
</div>
</Popup>
{/if}
{/each}
<MenuDrawer onlyLink={false} {state} />
</main>

View file

@ -0,0 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus width="500" height="500" viewBox="0 0 500 500" fill="none" version="1.1" id="svg1" sodipodi:docname="snowflake.svg" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs1" /> <sodipodi:namedview id="namedview1" pagecolor="#ffffff" bordercolor="{color}" borderopacity="0.25" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="0.31068504" inkscape:cx="82.07669" inkscape:cy="856.17253" inkscape:window-width="3072" inkscape:window-height="1659" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg1" /> <path d="m 470.00001,218.85 -82.564,-46.95 m 0,0 V 78.1 m 0,93.8 82.564,-46.9 m -82.564,46.9 L 30.000014,375 m 0,-93.85 82.563596,46.95 v 93.8 m 220.0004,-375 -82.564,46.95 -82.5636,-46.95 m 0,406.2 82.5636,-46.95 82.564,46.95 m -220.0004,-375 v 93.8 m 0,0 -82.563596,46.95 M 112.56361,171.9 30.000014,125 m 82.563596,46.9 357.4364,203.1 m -82.564,46.9 v -93.8 l 82.564,-46.95 M 250.00001,0 v 500" stroke="{color}" stroke-width="26.6666" stroke-miterlimit="10" id="path1" /> </svg>