Merge develop

This commit is contained in:
Pieter Vander Vennet 2025-03-17 02:41:31 +01:00
commit 36f9825c73
36 changed files with 961 additions and 262 deletions

View file

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

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)) * **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,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:** integrate wayside shrines ([1f7b156](https://github.com/pietervdvn/mapcomplete/commits/1f7b156a2c18200ece3c3ec9aa3d86f814d2590b))
* **wayside_shrines:** small language fixes ([aaf46cd](https://github.com/pietervdvn/mapcomplete/commits/aaf46cd7b01a9f11720d5e47ac6ffcde15b29add)) * **wayside_shrines:** small language fixes ([aaf46cd](https://github.com/pietervdvn/mapcomplete/commits/aaf46cd7b01a9f11720d5e47ac6ffcde15b29add))

View file

@ -33,17 +33,17 @@
"minzoom": 14, "minzoom": 14,
"title": { "title": {
"render": { "render": {
"en": "Entrance", "en": "Entrance {ref}",
"nl": "Ingang", "nl": "Ingang {ref}",
"ca": "Entrada", "ca": "Entrada {ref}",
"da": "Indgang", "da": "Indgang {ref}",
"de": "Eingang", "de": "Eingang {ref}",
"es": "Entrada", "es": "Entrada {ref}",
"fr": "Entrée", "fr": "Entrée {ref}",
"pa_PK": "دروازہ", "pa_PK": "دروازہ{ref}",
"pl": "Wejście", "pl": "Wejście {ref}",
"cs": "Vchod", "cs": "Vchod {ref}",
"cy": "Mynedfa" "cy": "Mynedfa {ref}"
} }
}, },
"pointRendering": [ "pointRendering": [
@ -68,7 +68,16 @@
] ]
} }
} }
] ],
"label": {
"mappings": [
{
"if": "ref~*",
"then": "{ref}"
}
]
},
"labelCssClasses": "rounded bg-white px-2"
} }
], ],
"lineRendering": [], "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": [ "filter": [

View file

@ -1,40 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) --> <!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg <svg
xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.1"
xmlns:cc="http://creativecommons.org/ns#" width="512"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" height="512"
xmlns:svg="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg" id="svg2"
version="1.1" sodipodi:docname="ice_cream.svg"
width="14" inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
height="14" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 14 14" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
id="svg2"> xmlns="http://www.w3.org/2000/svg"
<metadata xmlns:svg="http://www.w3.org/2000/svg"
id="metadata8"> xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
<rdf:RDF> xmlns:cc="http://creativecommons.org/ns#"
<cc:Work xmlns:dc="http://purl.org/dc/elements/1.1/">
rdf:about=""> <sodipodi:namedview
<dc:format>image/svg+xml</dc:format> id="namedview1"
<dc:type pagecolor="#ffffff"
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> bordercolor="#999999"
<dc:title></dc:title> borderopacity="1"
</cc:Work> inkscape:showpageshadow="2"
</rdf:RDF> inkscape:pageopacity="0"
</metadata> inkscape:pagecheckerboard="0"
<defs inkscape:deskcolor="#d1d1d1"
id="defs6" /> inkscape:zoom="0.5"
<rect inkscape:cx="8"
width="14" inkscape:cy="7"
height="14" inkscape:window-width="1920"
x="0" inkscape:window-height="1005"
y="0" inkscape:window-x="0"
id="canvas" inkscape:window-y="0"
style="fill:none;stroke:none;visibility:hidden" /> inkscape:window-maximized="1"
<path inkscape:current-layer="svg2" />
d="M 5,0 C 3.3431457,0 2,1.3431457 2,3 2,3.3555333 2.0739786,3.6835283 2.1875,4 l 5.625,0 C 7.9260214,3.6835283 8,3.3555333 8,3 8,1.3431457 6.6568543,0 5,0 z M 9,0 C 8.5961418,0 8.2266723,0.105305 7.875,0.25 8.5629725,0.96841289 9,1.9267594 9,3 9,3.3467764 8.931082,3.6790098 8.84375,4 L 11.8125,4 C 11.926021,3.6835283 12,3.3555333 12,3 12,1.3431457 10.656854,0 9,0 z M 3.25,5 7,14 10.75,5 3.25,5 z" <metadata
id="ice-cream" id="metadata8">
style="fill:#C77400;fill-opacity:1;stroke:none" /> <rdf:RDF>
</svg> <cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<rect
width="512"
height="512"
x="0"
y="0"
id="canvas"
style="visibility:hidden;fill:none;stroke:none;stroke-width:36.5714" />
<path
d="M 182.85714,0 C 122.26361,0 73.142857,49.120757 73.142857,109.71429 c 0,13.00236 2.705503,24.9976 6.857143,36.57142 h 205.71429 c 4.15164,-11.57382 6.85714,-23.56906 6.85714,-36.57142 C 292.57143,49.120757 243.45067,0 182.85714,0 Z M 329.14286,0 C 314.37319,0 300.86116,3.8511543 288,9.1428571 313.16014,35.416243 329.14286,70.464344 329.14286,109.71429 c 0,12.6821 -2.52043,24.83235 -5.71429,36.57142 H 432 c 4.15163,-11.57382 6.85714,-23.56906 6.85714,-36.57142 C 438.85714,49.120757 389.73637,0 329.14286,0 Z M 118.85714,182.85714 256,512 393.14286,182.85714 Z"
id="ice-cream"
style="fill:#c77400;fill-opacity:1;stroke:none;stroke-width:36.5714" />
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Before After
Before After

View file

@ -1,64 +1,316 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 128 128" style="display:inline;enable-background:new" version="1.0" id="svg11300" height="128" width="128"> <svg
<title id="title4162">Adwaita Icon Template</title> viewBox="0 0 512 512"
<defs id="defs3"> style="display:inline;enable-background:new"
<linearGradient id="linearGradient1200"> version="1.0"
<stop id="stop1196" offset="0" style="stop-color:#f66151;stop-opacity:1"/> id="svg11300"
<stop id="stop1198" offset="1" style="stop-color:#c01c28;stop-opacity:1"/> height="512"
width="512"
sodipodi:docname="camera.svg"
inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#999999"
borderopacity="1"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="0.29877869"
inkscape:cx="662.69788"
inkscape:cy="-316.28762"
inkscape:window-width="1920"
inkscape:window-height="1005"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg11300" />
<title
id="title4162">Adwaita Icon Template</title>
<defs
id="defs3">
<linearGradient
id="linearGradient1200">
<stop
id="stop1196"
offset="0"
style="stop-color:#f66151;stop-opacity:1" />
<stop
id="stop1198"
offset="1"
style="stop-color:#c01c28;stop-opacity:1" />
</linearGradient> </linearGradient>
<linearGradient id="linearGradient1194"> <linearGradient
<stop style="stop-color:#9a9996;stop-opacity:1" offset="0" id="stop1182"/> id="linearGradient1194">
<stop id="stop1184" offset="0.03571429" style="stop-color:#deddda;stop-opacity:1"/> <stop
<stop style="stop-color:#c0bfbc;stop-opacity:1" offset="0.07142857" id="stop1186"/> style="stop-color:#9a9996;stop-opacity:1"
<stop id="stop1188" offset="0.9285714" style="stop-color:#c0bfbc;stop-opacity:1"/> offset="0"
<stop style="stop-color:#deddda;stop-opacity:1" offset="0.96428573" id="stop1190"/> id="stop1182" />
<stop style="stop-color:#9a9996;stop-opacity:1" offset="1" id="stop1192"/> <stop
id="stop1184"
offset="0.03571429"
style="stop-color:#deddda;stop-opacity:1" />
<stop
style="stop-color:#c0bfbc;stop-opacity:1"
offset="0.07142857"
id="stop1186" />
<stop
id="stop1188"
offset="0.9285714"
style="stop-color:#c0bfbc;stop-opacity:1" />
<stop
style="stop-color:#deddda;stop-opacity:1"
offset="0.96428573"
id="stop1190" />
<stop
style="stop-color:#9a9996;stop-opacity:1"
offset="1"
id="stop1192" />
</linearGradient> </linearGradient>
<radialGradient gradientTransform="matrix(0.20374131,0.02574915,-0.13347722,1.0561446,5.11727,292.38679)" gradientUnits="userSpaceOnUse" r="111.99999" fy="-70.410965" fx="322.32892" cy="-70.410965" cx="322.32892" id="radialGradient957" xlink:href="#linearGradient1039"/> <radialGradient
<linearGradient id="linearGradient1039"> gradientTransform="matrix(0.20374131,0.02574915,-0.13347722,1.0561446,5.11727,292.38679)"
<stop style="stop-color:#949390;stop-opacity:1" offset="0" id="stop1035"/> gradientUnits="userSpaceOnUse"
<stop style="stop-color:#191622;stop-opacity:1" offset="1" id="stop1037"/> r="111.99999"
fy="-70.410965"
fx="322.32892"
cy="-70.410965"
cx="322.32892"
id="radialGradient957"
xlink:href="#linearGradient1039" />
<linearGradient
id="linearGradient1039">
<stop
style="stop-color:#949390;stop-opacity:1"
offset="0"
id="stop1035" />
<stop
style="stop-color:#191622;stop-opacity:1"
offset="1"
id="stop1037" />
</linearGradient> </linearGradient>
<radialGradient gradientTransform="matrix(0.36230333,0,0,0.36230333,-41.78098,227.028)" gradientUnits="userSpaceOnUse" r="80.368896" fy="82.548996" fx="318.92401" cy="82.548996" cx="318.92401" id="radialGradient1116" xlink:href="#linearGradient1045"/> <radialGradient
<linearGradient id="linearGradient1045"> gradientTransform="matrix(0.36230333,0,0,0.36230333,-41.78098,227.028)"
<stop style="stop-color:#68676b;stop-opacity:1" offset="0" id="stop1041"/> gradientUnits="userSpaceOnUse"
<stop style="stop-color:#191622;stop-opacity:1" offset="1" id="stop1043"/> r="80.368896"
fy="82.548996"
fx="318.92401"
cy="82.548996"
cx="318.92401"
id="radialGradient1116"
xlink:href="#linearGradient1045" />
<linearGradient
id="linearGradient1045">
<stop
style="stop-color:#68676b;stop-opacity:1"
offset="0"
id="stop1041" />
<stop
style="stop-color:#191622;stop-opacity:1"
offset="1"
id="stop1043" />
</linearGradient> </linearGradient>
<radialGradient gradientTransform="matrix(0.7272972,0,0,0.7272972,-159.07258,-233.33112)" gradientUnits="userSpaceOnUse" r="49.999992" fy="-31.994987" fx="320.70712" cy="-31.994987" cx="320.70712" id="radialGradient2192" xlink:href="#linearGradient1087"/> <radialGradient
<linearGradient id="linearGradient1087"> gradientTransform="matrix(0.7272972,0,0,0.7272972,-159.07258,-233.33112)"
<stop style="stop-color:#1a4172;stop-opacity:1" offset="0" id="stop1083"/> gradientUnits="userSpaceOnUse"
<stop style="stop-color:#000000;stop-opacity:1" offset="1" id="stop1085"/> r="49.999992"
fy="-31.994987"
fx="320.70712"
cy="-31.994987"
cx="320.70712"
id="radialGradient2192"
xlink:href="#linearGradient1087" />
<linearGradient
id="linearGradient1087">
<stop
style="stop-color:#1a4172;stop-opacity:1"
offset="0"
id="stop1083" />
<stop
style="stop-color:#000000;stop-opacity:1"
offset="1"
id="stop1085" />
</linearGradient> </linearGradient>
<linearGradient gradientUnits="userSpaceOnUse" y2="13" x2="319.99997" y1="93.000008" x1="319.99997" id="linearGradient2224" xlink:href="#linearGradient1075" gradientTransform="matrix(0.25,0,0,0.25,-5.99995,-248.60224)"/> <linearGradient
<linearGradient id="linearGradient1075"> gradientUnits="userSpaceOnUse"
<stop style="stop-color:#ffffff;stop-opacity:1" offset="0" id="stop1071"/> y2="13"
<stop style="stop-color:#4a86cf;stop-opacity:0" offset="1" id="stop1073"/> x2="319.99997"
y1="93.000008"
x1="319.99997"
id="linearGradient2224"
xlink:href="#linearGradient1075"
gradientTransform="matrix(0.25,0,0,0.25,-5.99995,-248.60224)" />
<linearGradient
id="linearGradient1075">
<stop
style="stop-color:#ffffff;stop-opacity:1"
offset="0"
id="stop1071" />
<stop
style="stop-color:#4a86cf;stop-opacity:0"
offset="1"
id="stop1073" />
</linearGradient> </linearGradient>
<linearGradient y2="619.96387" x2="624" y1="619.96387" x1="177" gradientTransform="matrix(0.25,0,0,0.24305558,-35.999947,93.564314)" gradientUnits="userSpaceOnUse" id="linearGradient1444-3-9-0-9" xlink:href="#linearGradient1194"/> <linearGradient
<linearGradient gradientTransform="translate(188.00001,-239.99999)" gradientUnits="userSpaceOnUse" y2="212" x2="35.999992" y1="212" x1="19.999992" id="linearGradient1202" xlink:href="#linearGradient1200"/> y2="619.96387"
x2="624"
y1="619.96387"
x1="177"
gradientTransform="matrix(0.25,0,0,0.24305558,-35.999947,93.564314)"
gradientUnits="userSpaceOnUse"
id="linearGradient1444-3-9-0-9"
xlink:href="#linearGradient1194" />
<linearGradient
gradientTransform="translate(188.00001,-239.99999)"
gradientUnits="userSpaceOnUse"
y2="212"
x2="35.999992"
y1="212"
x1="19.999992"
id="linearGradient1202"
xlink:href="#linearGradient1200" />
</defs> </defs>
<metadata id="metadata4"> <metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:title>Adwaita Icon Template</dc:title>
</cc:Work>
</rdf:RDF>
</metadata> </metadata>
<g transform="translate(0,-172)" style="display:inline" id="layer1"> <g
<g style="display:inline" id="layer9"> transform="matrix(4.4285712,0,0,4.4285712,-27.428541,-807.99996)"
<rect style="display:inline;opacity:1;vector-effect:none;fill:url(#linearGradient1444-3-9-0-9);fill-opacity:1;stroke:none;stroke-width:0.01114019px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" id="rect1480-3-7-1-3-6" width="112" height="70" x="7.9999914" y="218" rx="8" ry="7.7777786"/> style="display:inline"
<path style="display:inline;opacity:1;vector-effect:none;fill:#424048;fill-opacity:1;stroke:none;stroke-width:0.00279558px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" d="m 60.89285,196 h 26.2143 c 1.11788,0 1.950682,0.77034 2.01785,1.72191 L 90,210.1181 c 0.07133,1.01051 -0.95572,1.82857 -2.14285,1.82857 h -27.7143 c -1.18712,0 -2.21417,-0.81806 -2.14285,-1.82857 l 0.875,-12.39619 C 58.9422,196.77034 59.77498,196 60.89285,196 Z" id="rect971"/> id="layer1">
<rect ry="2" rx="12" y="201.21478" x="17.99999" height="7.0392466" width="24" id="rect1647-3-3-8" style="display:inline;opacity:1;vector-effect:none;fill:#949390;fill-opacity:1;stroke:none;stroke-width:0.01725831px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"/> <g
<rect ry="7.8530612" rx="8" y="206" x="8" height="78" width="111.99999" id="rect1480-6-7" style="display:inline;opacity:1;vector-effect:none;fill:#f6f5f4;fill-opacity:1;stroke:none;stroke-width:0.01119398px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"/> style="display:inline"
<path id="rect1482-1-3" d="m 8,216 v 56 H 120 V 216 H 38 c 0,5.52284 -4.47715,10 -10,10 -5.52285,0 -10,-4.47716 -10,-10 z" style="display:inline;opacity:1;vector-effect:none;fill:#2a2a3b;fill-opacity:1;stroke:none;stroke-width:0.01129822px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"/> id="layer9">
<circle style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#68676b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.91564989;marker:none;enable-background:new" id="path15832-3-1-9-8" cx="73.999992" cy="246" r="30"/> <rect
<circle style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:new" id="path15832-3-2-9-4-5" cx="73.999992" cy="246" r="26.999998"/> style="display:inline;opacity:1;vector-effect:none;fill:url(#linearGradient1444-3-9-0-9);fill-opacity:1;stroke:none;stroke-width:0.0111402px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
<circle style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#3d3846;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient957);stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:new" id="path15832-3-2-9-4" cx="73.999992" cy="244" r="26.999998"/> id="rect1480-3-7-1-3-6"
<circle transform="rotate(90)" style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient1202);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8584218;marker:none;enable-background:new" id="path15832-3-2-9-7-4-6" cx="216" cy="-27.999992" r="8"/> width="112"
<circle style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient1116);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114366;marker:none;enable-background:new" id="path15894-3" cx="73.907768" cy="244.05173" r="16.092224"/> height="70"
<circle style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114354;marker:none;enable-background:new" id="path15894-6" cx="73.999992" cy="-244.10229" transform="scale(1,-1)" r="13.999999"/> x="7.9999914"
<circle style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient2192);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114342;marker:none;enable-background:new" id="path15894-6-9" cx="73.999992" cy="-244.10229" transform="scale(1,-1)" r="12.499998"/> y="218"
<circle style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#15365f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114342;marker:none;enable-background:new" id="path15894-6-9-6" cx="73.999992" cy="-244.10229" transform="scale(1,-1)" r="5.5000019"/> rx="8"
<circle style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#2864b0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114342;marker:none;enable-background:new" id="path15894-6-9-7" cx="69.999992" cy="-239.60229" transform="scale(1,-1)" r="4"/> ry="7.7777786" />
<ellipse style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#2864b0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114342;marker:none;enable-background:new" id="path15894-6-9-7-3" cx="79.999992" cy="-249.60229" transform="scale(1,-1)" rx="2.0000017" ry="2"/> <path
<ellipse style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#2864b0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114342;marker:none;enable-background:new" id="path15894-6-9-7-3-2" cx="76.999992" cy="-246.60229" transform="scale(1,-1)" rx="1.0000008" ry="1"/> style="display:inline;opacity:1;vector-effect:none;fill:#424048;fill-opacity:1;stroke:none;stroke-width:0.00279558px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
<circle style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.66399997;fill:url(#linearGradient2224);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114342;marker:none;enable-background:new" id="path15894-6-9-1" cx="73.999992" cy="-244.10229" transform="scale(1,-1)" r="12.499998"/> d="m 60.89285,196 h 26.2143 c 1.11788,0 1.950682,0.77034 2.01785,1.72191 L 90,210.1181 c 0.07133,1.01051 -0.95572,1.82857 -2.14285,1.82857 h -27.7143 c -1.18712,0 -2.21417,-0.81806 -2.14285,-1.82857 l 0.875,-12.39619 C 58.9422,196.77034 59.77498,196 60.89285,196 Z"
id="rect971" />
<rect
ry="2"
rx="12"
y="201.21478"
x="17.99999"
height="7.0392466"
width="24"
id="rect1647-3-3-8"
style="display:inline;opacity:1;vector-effect:none;fill:#949390;fill-opacity:1;stroke:none;stroke-width:0.0172583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
<rect
ry="7.8530612"
rx="8"
y="206"
x="8"
height="78"
width="111.99999"
id="rect1480-6-7"
style="display:inline;opacity:1;vector-effect:none;fill:#f6f5f4;fill-opacity:1;stroke:none;stroke-width:0.011194px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
<path
id="rect1482-1-3"
d="m 8,216 v 56 H 120 V 216 H 38 c 0,5.52284 -4.47715,10 -10,10 -5.52285,0 -10,-4.47716 -10,-10 z"
style="display:inline;opacity:1;vector-effect:none;fill:#2a2a3b;fill-opacity:1;stroke:none;stroke-width:0.0112982px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#68676b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.91565;marker:none;enable-background:new"
id="path15832-3-1-9-8"
cx="73.999992"
cy="246"
r="30" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:new"
id="path15832-3-2-9-4-5"
cx="73.999992"
cy="246"
r="26.999998" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#3d3846;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient957);stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:new"
id="path15832-3-2-9-4"
cx="73.999992"
cy="244"
r="26.999998" />
<circle
transform="rotate(90)"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient1202);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.858422;marker:none;enable-background:new"
id="path15832-3-2-9-7-4-6"
cx="216"
cy="-27.999992"
r="8" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient1116);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114;marker:none;enable-background:new"
id="path15894-3"
cx="73.907768"
cy="244.05173"
r="16.092224" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114;marker:none;enable-background:new"
id="path15894-6"
cx="73.999992"
cy="-244.10229"
transform="scale(1,-1)"
r="13.999999" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient2192);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114;marker:none;enable-background:new"
id="path15894-6-9"
cx="73.999992"
cy="-244.10229"
transform="scale(1,-1)"
r="12.499998" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#15365f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114;marker:none;enable-background:new"
id="path15894-6-9-6"
cx="73.999992"
cy="-244.10229"
transform="scale(1,-1)"
r="5.5000019" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#2864b0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114;marker:none;enable-background:new"
id="path15894-6-9-7"
cx="69.999992"
cy="-239.60229"
transform="scale(1,-1)"
r="4" />
<ellipse
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#2864b0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114;marker:none;enable-background:new"
id="path15894-6-9-7-3"
cx="79.999992"
cy="-249.60229"
transform="scale(1,-1)"
rx="2.0000017"
ry="2" />
<ellipse
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#2864b0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114;marker:none;enable-background:new"
id="path15894-6-9-7-3-2"
cx="76.999992"
cy="-246.60229"
transform="scale(1,-1)"
rx="1.0000008"
ry="1" />
<circle
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.664;fill:url(#linearGradient2224);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.79114;marker:none;enable-background:new"
id="path15894-6-9-1"
cx="73.999992"
cy="-244.10229"
transform="scale(1,-1)"
r="12.499998" />
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before After
Before After

View file

@ -954,48 +954,48 @@
"id": "toilet-changing_table:location" "id": "toilet-changing_table:location"
}, },
{ {
"labels": [ "id": "toilet-supervised",
"relevant-questions"
],
"id": "toilet-handwashing",
"question": { "question": {
"en": "Do these toilets have a sink to wash your hands?", "en": "Is this toilets supervised by a person?",
"nl": "Hebben deze toiletten een lavabo om de handen te wassen?", "nl": "Is er toezicht op deze toilet?"
"de": "Gibt es hier ein Handwaschbecken?", },
"es": "¿Estos baños tienen un lavabo para lavarse las manos?", "questionHint": {
"fr": "Ces toilettes ont-ils un lavabo pour se laver les mains ?", "en": "This is typically a person tasked with keeping the toilets clean and collecting the fee",
"da": "Har disse toiletter en håndvask til at vaske hænder?", "nl": "Deze persoon houdt typisch de toiletten proper en int het toiletgeld"
"ca": "Aquests lavabos tenen una pica per a rentar-se les mans?",
"cs": "Mají tyto toalety umyvadlo na mytí rukou?"
}, },
"mappings": [ "mappings": [
{ {
"if": "toilets:handwashing=yes", "if": "supervised=yes",
"then": { "then": {
"en": "These toilets have a sink to wash your hands", "en": "There is a person supervising these toilets during (most of) the opening hours",
"nl": "Deze toiletten hebben een lavabo waar men de handen kan wassen", "nl": "Er is een persoon die toezicht houdt op deze toiletten"
"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", "if": "supervised=interval",
"then": { "then": {
"en": "These toilets <b>don't</b> have a sink to wash your hands", "en": "There is a person supervising these toilets, but they are present only during certain times of the opening hours",
"nl": "Deze toiletten hebben <b>geen</b> lavabo waar men de handen kan wassen", "nl": "Er is een persoon die toezicht houdt op deze toiletten, maar deze is slechts op enkele vaste momenten aanwezig"
"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", "if": "supervised=no",
"ca": "Aquests lavabos <b>no</b> tenen una pica per a rentar-se les mans", "then": {
"cs": "Tyto toalety <b>nemají umyvadlo na mytí rukou</b>" "en": "These toilets are not supervised",
"nl": "Er is geen persoon die toezicht houdt"
} }
} }
] ],
"condition": {
"and": [
{
"or": [
"access=yes",
"access="
]
}
]
}
}, },
{ {
"id": "toilet-has-paper", "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" "description"
], ],
"filter": [ "filter": [

View file

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

View file

@ -2,12 +2,12 @@
<!-- Created with Inkscape (http://www.inkscape.org/) --> <!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg <svg
width="40mm" width="512mm"
height="40mm" height="512mm"
viewBox="0 0 40 40" viewBox="0 0 512 512"
version="1.1" version="1.1"
id="svg5" id="svg5"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
sodipodi:docname="wall_painting.svg" sodipodi:docname="wall_painting.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
@ -28,47 +28,57 @@
inkscape:snap-global="true" inkscape:snap-global="true"
inkscape:snap-others="false" inkscape:snap-others="false"
inkscape:snap-to-guides="false" inkscape:snap-to-guides="false"
inkscape:zoom="2.5894514" inkscape:zoom="0.27482279"
inkscape:cx="4.2480041" inkscape:cx="871.47066"
inkscape:cy="59.665148" inkscape:cy="678.61911"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="995" inkscape:window-height="1005"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="0" inkscape:window-y="0"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="layer1"> inkscape:current-layer="layer1"
inkscape:showpageshadow="2"
inkscape:deskcolor="#d1d1d1">
<sodipodi:guide <sodipodi:guide
position="-1.158135,35.017833" position="-1.158135,35.017833"
orientation="0,-1" orientation="0,-1"
id="guide1027" /> id="guide1027"
inkscape:locked="false" />
<sodipodi:guide <sodipodi:guide
position="-0.65554813,30.013816" position="-0.65554813,30.013816"
orientation="0,-1" orientation="0,-1"
id="guide1029" /> id="guide1029"
inkscape:locked="false" />
<sodipodi:guide <sodipodi:guide
position="-0.5462901,25.009798" position="-0.5462901,25.009798"
orientation="0,-1" orientation="0,-1"
id="guide1031" /> id="guide1031"
inkscape:locked="false" />
<sodipodi:guide <sodipodi:guide
position="-0.5025869,20.005781" position="-0.5025869,20.005781"
orientation="0,-1" orientation="0,-1"
id="guide1033" /> id="guide1033"
inkscape:locked="false" />
<sodipodi:guide <sodipodi:guide
position="-0.30592246,15.001764" position="-0.30592246,15.001764"
orientation="0,-1" orientation="0,-1"
id="guide1035" /> id="guide1035"
inkscape:locked="false" />
<sodipodi:guide <sodipodi:guide
position="-0.10925802,9.9977463" position="-0.10925802,9.9977463"
orientation="0,-1" orientation="0,-1"
id="guide1037" /> id="guide1037"
inkscape:locked="false" />
<sodipodi:guide <sodipodi:guide
position="-0.021851604,4.993729" position="-0.021851604,4.993729"
orientation="0,-1" orientation="0,-1"
id="guide1039" /> id="guide1039"
inkscape:locked="false" />
<sodipodi:guide <sodipodi:guide
position="-0.15296123,0.033414841" position="-0.15296123,0.033414841"
orientation="0,-1" orientation="0,-1"
id="guide1041" /> id="guide1041"
inkscape:locked="false" />
</sodipodi:namedview> </sodipodi:namedview>
<defs <defs
id="defs2"> id="defs2">
@ -86,26 +96,25 @@
</mask> </mask>
<inkscape:perspective <inkscape:perspective
sodipodi:type="inkscape:persp3d" sodipodi:type="inkscape:persp3d"
inkscape:vp_x="212.23055 : 183.79824 : 1" inkscape:vp_x="212.23055 : 655.79823 : 1"
inkscape:vp_y="-138.82678 : 127.6308 : 0" inkscape:vp_y="-138.82678 : 127.6308 : 0"
inkscape:vp_z="102.00732 : 223.33213 : 1" inkscape:vp_z="102.00732 : 695.33212 : 1"
inkscape:persp3d-origin="275.61188 : 262.5309 : 1" inkscape:persp3d-origin="275.61188 : 734.53089 : 1"
id="perspective7227" /> id="perspective7227" />
</defs> </defs>
<g <g
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer2" id="layer2"
inkscape:label="bg" inkscape:label="bg"
style="display:inline" style="display:inline">
sodipodi:insensitive="true">
<rect <rect
style="fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:0.799999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:100;stroke-dasharray:none;stroke-opacity:1" style="fill:#cccccc;fill-opacity:1;stroke:none;stroke-width:10.0731;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:100;stroke-dasharray:none;stroke-opacity:1"
id="rect3582" id="rect3582"
width="40.666897" width="512.05225"
height="40.617493" height="511.43018"
x="-0.026121488" x="-0.026121488"
y="-0.074673384" y="-0.074673384"
rx="1.0000006" /> rx="12.591385" />
</g> </g>
<g <g
inkscape:label="Layer 1" inkscape:label="Layer 1"
@ -114,7 +123,8 @@
style="display:inline"> style="display:inline">
<g <g
id="g4136" id="g4136"
mask="url(#mask1309)"> mask="url(#mask1309)"
transform="matrix(12.591377,0,0,12.591377,0.30278402,0.86556738)">
<rect <rect
style="fill:#e75316;fill-opacity:1;stroke:#cccccc;stroke-width:0.8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:100;stroke-dasharray:none;stroke-opacity:1" style="fill:#e75316;fill-opacity:1;stroke:#cccccc;stroke-width:0.8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:100;stroke-dasharray:none;stroke-opacity:1"
id="rect1329" id="rect1329"
@ -934,7 +944,7 @@
</g> </g>
<path <path
sodipodi:type="spiral" sodipodi:type="spiral"
style="fill:#001fff;fill-opacity:0.37284482;fill-rule:evenodd;stroke:#ffffff;stroke-width:13.9078929;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.9912985" style="fill:#001fff;fill-opacity:0.372845;fill-rule:evenodd;stroke:#ffffff;stroke-width:13.9079;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.991298"
id="path4178" id="path4178"
sodipodi:cx="354.86203" sodipodi:cx="354.86203"
sodipodi:cy="373.78302" sodipodi:cy="373.78302"
@ -943,11 +953,11 @@
sodipodi:radius="74.712395" sodipodi:radius="74.712395"
sodipodi:argument="-25.492455" sodipodi:argument="-25.492455"
sodipodi:t0="0.038965192" sodipodi:t0="0.038965192"
transform="matrix(0.16181313,0,0,0.14314247,-46.638251,-41.315378)" transform="matrix(2.0374502,0,0,1.8023609,-586.93703,-519.35195)"
d="m 357.71341,374.37007 c 4.26414,3.70709 -1.33671,9.32671 -5.07702,10.22323 -8.90331,2.13404 -16.0483,-6.51539 -16.54354,-14.67451 -0.80844,-13.31906 11.72945,-23.06078 24.27201,-22.86385 17.66382,0.27733 30.16537,16.97051 29.18416,33.8695 -1.27726,21.99757 -22.22018,37.31028 -43.467,35.50447 -26.32945,-2.23779 -44.47651,-27.47377 -41.82478,-53.06449 3.17716,-30.66134 32.72957,-51.65542 62.66199,-48.14509 34.99363,4.10388 58.84245,37.98678 54.46539,72.25948 -4.08654,31.99797 -30.76626,56.97365 -62.46783,60.90649" /> d="m 357.71341,374.37007 c 4.26414,3.70709 -1.33671,9.32671 -5.07702,10.22323 -8.90331,2.13404 -16.0483,-6.51539 -16.54354,-14.67451 -0.80844,-13.31906 11.72945,-23.06078 24.27201,-22.86385 17.66382,0.27733 30.16537,16.97051 29.18416,33.8695 -1.27726,21.99757 -22.22018,37.31028 -43.467,35.50447 -26.32945,-2.23779 -44.47651,-27.47377 -41.82478,-53.06449 3.17716,-30.66134 32.72957,-51.65542 62.66199,-48.14509 34.99363,4.10388 58.84245,37.98678 54.46539,72.25948 -4.08654,31.99797 -30.76626,56.97365 -62.46783,60.90649" />
<path <path
sodipodi:type="star" sodipodi:type="star"
style="opacity:1;fill:#001fff;fill-opacity:0.37284482;stroke:#ffffff;stroke-width:12.71010332;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.9912985" style="opacity:1;fill:#001fff;fill-opacity:0.372845;stroke:#ffffff;stroke-width:12.7101;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.991298"
id="path4180" id="path4180"
sodipodi:sides="5" sodipodi:sides="5"
sodipodi:cx="355.44702" sodipodi:cx="355.44702"
@ -959,9 +969,9 @@
inkscape:flatsided="false" inkscape:flatsided="false"
inkscape:rounded="0" inkscape:rounded="0"
inkscape:randomized="0" inkscape:randomized="0"
inkscape:transform-center-x="-1.420664" inkscape:transform-center-x="-17.888111"
inkscape:transform-center-y="-1.4924413" inkscape:transform-center-y="-18.791889"
transform="matrix(0.14633311,-0.09389576,0.08614253,0.13424997,-69.033262,-12.7164)" transform="matrix(1.8425354,-1.1822769,1.0846531,1.690392,-868.92107,-159.25142)"
d="m 375.44702,604.95685 -31.36911,-32.59461 -39.51394,10.15676 21.30573,-39.90609 -21.87013,-34.44138 44.53677,7.9313 25.99746,-31.4427 6.21951,44.80789 37.93744,15.00872 -40.6929,19.76151 z" /> d="m 375.44702,604.95685 -31.36911,-32.59461 -39.51394,10.15676 21.30573,-39.90609 -21.87013,-34.44138 44.53677,7.9313 25.99746,-31.4427 6.21951,44.80789 37.93744,15.00872 -40.6929,19.76151 z" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Before After
Before After

View file

@ -19,6 +19,50 @@
"shortDescription": { "shortDescription": {
"nl": "Grb import helper tool" "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", "icon": "./assets/themes/grb/logo.svg",
"startZoom": 9, "startZoom": 9,
"startLat": 51.0249, "startLat": 51.0249,

View file

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

View file

@ -5245,7 +5245,7 @@
} }
}, },
"title": { "title": {
"render": "Entrada" "render": "Entrada {ref}"
} }
}, },
"etymology": { "etymology": {

View file

@ -5049,7 +5049,7 @@
} }
}, },
"title": { "title": {
"render": "Vchod" "render": "Vchod {ref}"
} }
}, },
"etymology": { "etymology": {

View file

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

View file

@ -1564,7 +1564,7 @@
} }
}, },
"title": { "title": {
"render": "Indgang" "render": "Indgang {ref}"
} }
}, },
"etymology": { "etymology": {

View file

@ -5204,7 +5204,7 @@
} }
}, },
"title": { "title": {
"render": "Eingang" "render": "Eingang {ref}"
} }
}, },
"etymology": { "etymology": {

View file

@ -5321,13 +5321,22 @@
"question": "What is the height of this kerb?", "question": "What is the height of this kerb?",
"render": "The kerb height of this door is {kerb:height}" "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": { "width": {
"question": "What is the width of this door/entrance?", "question": "What is the width of this door/entrance?",
"render": "This door has a width of {canonical(width)}" "render": "This door has a width of {canonical(width)}"
} }
}, },
"title": { "title": {
"render": "Entrance" "render": "Entrance {ref}"
} }
}, },
"etymology": { "etymology": {
@ -12133,6 +12142,26 @@
"question": "How much does one have to pay for these toilets?", "question": "How much does one have to pay for these toilets?",
"render": "The fee is {charge}" "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": { "toilet-handwashing": {
"mappings": { "mappings": {
"0": { "0": {
@ -12162,6 +12191,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": { "toilets-changing-table": {
"mappings": { "mappings": {
"0": { "0": {

View file

@ -4903,7 +4903,7 @@
} }
}, },
"title": { "title": {
"render": "Entrada" "render": "Entrada {ref}"
} }
}, },
"etymology": { "etymology": {

View file

@ -3467,7 +3467,7 @@
} }
}, },
"title": { "title": {
"render": "Entrée" "render": "Entrée {ref}"
} }
}, },
"etymology": { "etymology": {

View file

@ -4990,13 +4990,22 @@
"question": "Hoe hoog is de drempel?", "question": "Hoe hoog is de drempel?",
"render": "De drempel bij deze deur is {kerb:height}" "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": { "width": {
"question": "Wat is de breedte van deze deur/toegang?", "question": "Wat is de breedte van deze deur/toegang?",
"render": "Deze deur heeft een breedte van {canonical(width)}" "render": "Deze deur heeft een breedte van {canonical(width)}"
} }
}, },
"title": { "title": {
"render": "Ingang" "render": "Ingang {ref}"
} }
}, },
"etymology": { "etymology": {
@ -9757,6 +9766,26 @@
"question": "Hoeveel moet men betalen om deze toiletten te gebruiken?", "question": "Hoeveel moet men betalen om deze toiletten te gebruiken?",
"render": "De toiletten gebruiken kost {charge}" "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": { "toilet-handwashing": {
"mappings": { "mappings": {
"0": { "0": {
@ -9786,6 +9815,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": { "toilets-changing-table": {
"mappings": { "mappings": {
"0": { "0": {

View file

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

View file

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

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": { "guideposts": {

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", "shortDescription": "Grb import helper tool",
"title": "GRB import helper" "title": "GRB import helper"
}, },

View file

@ -9,16 +9,12 @@ import {
DoesImageExist, DoesImageExist,
PrevalidateTheme, PrevalidateTheme,
ValidateLayer, ValidateLayer,
ValidateThemeEnsemble, ValidateThemeEnsemble
} from "../src/Models/ThemeConfig/Conversion/Validation" } from "../src/Models/ThemeConfig/Conversion/Validation"
import { Translation } from "../src/UI/i18n/Translation" import { Translation } from "../src/UI/i18n/Translation"
import { PrepareLayer } from "../src/Models/ThemeConfig/Conversion/PrepareLayer" import { PrepareLayer } from "../src/Models/ThemeConfig/Conversion/PrepareLayer"
import { PrepareTheme } from "../src/Models/ThemeConfig/Conversion/PrepareTheme" import { PrepareTheme } from "../src/Models/ThemeConfig/Conversion/PrepareTheme"
import { import { Conversion, DesugaringContext, DesugaringStep } from "../src/Models/ThemeConfig/Conversion/Conversion"
Conversion,
DesugaringContext,
DesugaringStep,
} from "../src/Models/ThemeConfig/Conversion/Conversion"
import { Utils } from "../src/Utils" import { Utils } from "../src/Utils"
import Script from "./Script" import Script from "./Script"
import { AllSharedLayers } from "../src/Customizations/AllSharedLayers" import { AllSharedLayers } from "../src/Customizations/AllSharedLayers"
@ -501,7 +497,7 @@ class LayerOverviewUtils extends Script {
priviliged.delete(key) priviliged.delete(key)
}) })
// These two get a free pass // These get a free pass
priviliged.delete("summary") priviliged.delete("summary")
priviliged.delete("last_click") priviliged.delete("last_click")
priviliged.delete("search") 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 { export default interface UserDetails {
name: string name: string
uid: number uid: number
@ -77,7 +87,8 @@ export default interface UserDetails {
account_created: string account_created: string
tracesCount: number tracesCount: number
description?: string description?: string
languages: string[] languages: string[],
active_blocks: number
} }
export type OsmServiceState = "online" | "readonly" | "offline" | "unknown" | "unreachable" export type OsmServiceState = "online" | "readonly" | "offline" | "unknown" | "unreachable"
@ -309,6 +320,7 @@ export class OsmConnection {
account_created: user.account_created, account_created: user.account_created,
tracesCount: user.traces?.count ?? 0, tracesCount: user.traces?.count ?? 0,
unreadMessages: user.messages.received?.unread ?? 0, unreadMessages: user.messages.received?.unread ?? 0,
active_blocks: user.blocks.received.active ?? 0
} }
this.userDetails.set(userdetails) this.userDetails.set(userdetails)
this.loadingStatus.setData("logged-in") 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 * To be called by land.html
*/ */

View file

@ -1,16 +1,6 @@
import { import { Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault } from "./Conversion"
Concat,
Conversion,
DesugaringContext,
DesugaringStep,
Each,
Fuse,
On,
Pass,
SetDefault,
} from "./Conversion"
import { ThemeConfigJson } from "../Json/ThemeConfigJson" import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import { PrepareLayer } from "./PrepareLayer" import { PrepareLayer, RewriteSpecial } from "./PrepareLayer"
import { LayerConfigJson } from "../Json/LayerConfigJson" import { LayerConfigJson } from "../Json/LayerConfigJson"
import { Utils } from "../../../Utils" import { Utils } from "../../../Utils"
import Constants from "../../Constants" import Constants from "../../Constants"
@ -40,7 +30,7 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
const knownLayers = Array.from(state.sharedLayers.keys()) const knownLayers = Array.from(state.sharedLayers.keys())
const withDistance: [string, number][] = knownLayers.map((lname) => [ const withDistance: [string, number][] = knownLayers.map((lname) => [
lname, lname,
Utils.levenshteinDistance(name, lname), Utils.levenshteinDistance(name, lname)
]) ])
withDistance.sort((a, b) => a[1] - b[1]) withDistance.sort((a, b) => a[1] - b[1])
const ids = withDistance.map((n) => n[0]) const ids = withDistance.map((n) => n[0])
@ -130,9 +120,9 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
usedLabels.add(labels[forbiddenLabel]) usedLabels.add(labels[forbiddenLabel])
context.info( context.info(
"Dropping tagRendering " + "Dropping tagRendering " +
tr["id"] + tr["id"] +
" as it has a forbidden label: " + " as it has a forbidden label: " +
labels[forbiddenLabel] labels[forbiddenLabel]
) )
continue continue
} }
@ -150,10 +140,10 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
usedLabels.add(tr["group"]) usedLabels.add(tr["group"])
context.info( context.info(
"Dropping tagRendering " + "Dropping tagRendering " +
tr["id"] + tr["id"] +
" as its group `" + " as its group `" +
tr["group"] + tr["group"] +
"` is a forbidden label" "` is a forbidden label"
) )
continue continue
} }
@ -164,8 +154,8 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
if (unused.length > 0) { if (unused.length > 0) {
context.err( 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: " + "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(", ") + 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" "\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 found.tagRenderings = filtered
@ -205,10 +195,10 @@ export class AddDefaultLayers extends DesugaringStep<ThemeConfigJson> {
if (alreadyLoaded.has(v.id)) { if (alreadyLoaded.has(v.id)) {
context.warn( context.warn(
"Layout " + "Layout " +
context + context +
" already has a layer with name " + " already has a layer with name " +
v.id + v.id +
"; skipping inclusion of this builtin layer" "; skipping inclusion of this builtin layer"
) )
continue continue
} }
@ -352,10 +342,10 @@ class AddDependencyLayersToTheme extends DesugaringStep<ThemeConfigJson> {
.enters("layer dependency") .enters("layer dependency")
.err( .err(
"Layer " + "Layer " +
dependency.neededLayer + dependency.neededLayer +
" is loaded because " + " is loaded because " +
dependency.reason + dependency.reason +
"; so it must specify a `snapName`. This is used in the sentence `move this point to snap it to {snapName}`" "; 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) { if (dep === undefined) {
const message = [ const message = [
"Loading a dependency failed: layer " + "Loading a dependency failed: layer " +
unmetDependency.neededLayer + unmetDependency.neededLayer +
" is not found, neither as layer of " + " is not found, neither as layer of " +
themeId + themeId +
" nor as builtin layer.", " nor as builtin layer.",
reason, reason,
"Loaded layers are: " + alreadyLoaded.map((l) => l.id).join(","), "Loaded layers are: " + alreadyLoaded.map((l) => l.id).join(",")
] ]
throw message.join("\n\t") throw message.join("\n\t")
} }
@ -395,7 +385,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<ThemeConfigJson> {
dep.description = reason dep.description = reason
dependenciesToAdd.unshift({ dependenciesToAdd.unshift({
config: dep, config: dep,
reason, reason
}) })
loadedLayerIds.add(dep.id) loadedLayerIds.add(dep.id)
unmetDependencies = unmetDependencies.filter( unmetDependencies = unmetDependencies.filter(
@ -440,7 +430,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<ThemeConfigJson> {
return { return {
...theme, ...theme,
layers: layers, layers: layers
} }
} }
} }
@ -510,10 +500,10 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<ThemeConfigJson>
context.warn( context.warn(
"The theme " + "The theme " +
json.id + json.id +
" has an inline layer: " + " has an inline layer: " +
layer["id"] + layer["id"] +
". This is discouraged." ". This is discouraged."
) )
} }
return json return json
@ -555,12 +545,12 @@ class PostvalidateTheme extends DesugaringStep<ThemeConfigJson> {
if (minZoomAll < layer.minzoom) { if (minZoomAll < layer.minzoom) {
context.err( context.err(
"There are multiple layers based on " + "There are multiple layers based on " +
basedOn + basedOn +
". The layer with id " + ". The layer with id " +
layer.id + layer.id +
" has a minzoom of " + " has a minzoom of " +
layer.minzoom + 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." ", 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") .enters("layers", config.id, "filter", "sameAs")
.err( .err(
"The layer " + "The layer " +
config.id + config.id +
" follows the filter state of layer " + " follows the filter state of layer " +
sameAs + sameAs +
", but no layer with this name was found.\n\tDid you perhaps mean one of: " + ", but no layer with this name was found.\n\tDid you perhaps mean one of: " +
closeLayers.slice(0, 3).join(", ") closeLayers.slice(0, 3).join(", ")
) )
} }
} }
@ -618,6 +608,13 @@ export class PrepareTheme extends Fuse<ThemeConfigJson> {
new SetDefault("socialImage", "assets/SocialImage.png", true), new SetDefault("socialImage", "assets/SocialImage.png", true),
// We expand all tagrenderings first... // We expand all tagrenderings first...
new On("layers", new Each(new PrepareLayer(state))), 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 // 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+ // Note that it'll cheat with tagRenderings+
new ApplyOverrideAll(), new ApplyOverrideAll(),

View file

@ -3,6 +3,8 @@ import ExtraLinkConfigJson from "./ExtraLinkConfigJson"
import { RasterLayerProperties } from "../../RasterLayerProperties" import { RasterLayerProperties } from "../../RasterLayerProperties"
import { Translatable } from "./Translatable" import { Translatable } from "./Translatable"
import { TagConfigJson } from "./TagConfigJson"
import { TagRenderingConfigJson } from "./TagRenderingConfigJson"
/** /**
* Defines the entire theme. * Defines the entire theme.
@ -468,4 +470,24 @@ export interface ThemeConfigJson {
* group: hidden * group: hidden
*/ */
_usedImages?: string[] _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"} }) * const config = new TagRenderingConfig({"id":"capacity", "render": "Fits {capcity} books",freeform: {"key":"capacity",type:"pnat"} })
* config.constructChangeSpecification("", undefined, undefined, {}) // => undefined * 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 * // 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"}]}) * 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", 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("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")] * 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 { RasterLayerProperties } from "../RasterLayerProperties"
import { Translatable } from "./Json/Translatable" 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 * Minimal information about a theme
@ -93,6 +97,14 @@ export default class ThemeConfig implements ThemeInformation {
public readonly source: ThemeConfigJson public readonly source: ThemeConfigJson
public readonly enableCache: boolean public readonly enableCache: boolean
public readonly popups: Readonly<{
id: string,
dismissible?: boolean,
condition: TagsFilter,
title: TagRenderingConfig,
body: TagRenderingConfig[]
}>[]
constructor( constructor(
json: ThemeConfigJson, json: ThemeConfigJson,
official = true, official = true,
@ -193,11 +205,26 @@ export default class ThemeConfig implements ThemeInformation {
icon: "./assets/svg/pop-out.svg", icon: "./assets/svg/pop-out.svg",
href: "https://{basepath}/{theme}.html?lat={lat}&lon={lon}&z={zoom}&language={language}", href: "https://{basepath}/{theme}.html?lat={lat}&lon={lon}&z={zoom}&language={language}",
newTab: true, newTab: true,
requirements: ["iframe", "no-welcome-message"], requirements: ["iframe", "no-welcome-message"]
}, },
context + ".extraLink" 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.hideFromOverview = json.hideFromOverview ?? false
this.lockLocation = <[[number, number], [number, number]]>json.lockLocation ?? undefined this.lockLocation = <[[number, number], [number, number]]>json.lockLocation ?? undefined
this.enableUserBadge = json.enableUserBadge ?? true 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 // The 'favourite'-layer contains pretty much all images as it bundles all layers, so we exclude it
const jsonNoFavourites = { const jsonNoFavourites = {
...json, ...json,
layers: json.layers.filter((l) => l["id"] !== "favourite"), layers: json.layers.filter((l) => l["id"] !== "favourite")
} }
const usedImages = jsonNoFavourites._usedImages const usedImages = jsonNoFavourites._usedImages
usedImages.sort() usedImages.sort()

View file

@ -12,7 +12,7 @@ export default class WithContextLoader {
this._context = context 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 * The found value is interpreted as a tagrendering and fetched/parsed
* */ * */

View file

@ -6,18 +6,26 @@
export let osmConnection: OsmConnection export let osmConnection: OsmConnection
export let clss: string | undefined = undefined 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) { if (osmConnection === undefined) {
console.error("No osmConnection passed into loginButton") console.error("No osmConnection passed into loginButton")
} }
let isLoggedIn = osmConnection.isLoggedIn let isLoggedIn = osmConnection.isLoggedIn
</script> </script>
{#if !$isLoggedIn} {#if !$isLoggedIn || forceShow}
<button class={clss} on:click={() => osmConnection.AttemptLogin()} style="margin-left: 0"> <button class={clss} on:click={() => osmConnection.AttemptLogin()} style="margin-left: 0">
<ArrowLeftOnRectangle class="m-1 w-12" /> <ArrowLeftOnRectangle class="m-1 w-12" />
<slot> <slot>
<Tr t={Translations.t.general.loginWithOpenStreetMap} /> {#if msg}
{msg}
{:else}
<Tr t={Translations.t.general.loginWithOpenStreetMap} />
{/if}
</slot> </slot>
</button> </button>
{/if} {/if}

View file

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

View file

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

View file

@ -111,12 +111,27 @@ export class SettingsVisualisations {
}, },
{ {
funcName: "login_button", 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", docs: "Show a login button",
needsUrls: [], needsUrls: [],
group: "settings", group: "settings",
constr(state: SpecialVisualizationState): SvelteUIElement { constr(state: SpecialVisualizationState, _, args): SvelteUIElement {
return new SvelteUIElement(LoginButton, { osmConnection: state.osmConnection }) 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 Loading from "./Base/Loading.svelte"
import { WithSearchState } from "../Models/ThemeViewState/WithSearchState" import { WithSearchState } from "../Models/ThemeViewState/WithSearchState"
import TitleHandler from "../Logic/Actors/TitleHandler" import TitleHandler from "../Logic/Actors/TitleHandler"
import Popup from "./Base/Popup.svelte"
import TagRenderingAnswer from "./Popup/TagRendering/TagRenderingAnswer.svelte"
export let state: WithSearchState export let state: WithSearchState
new TitleHandler(state.selectedElement, state) new TitleHandler(state.selectedElement, state)
@ -76,6 +78,7 @@
let mapproperties: MapProperties = state.mapProperties let mapproperties: MapProperties = state.mapProperties
let searchOpened = state.searchState.showSearchDrawer let searchOpened = state.searchState.showSearchDrawer
let metatags = state.userRelatedState.preferencesAsTags
Orientation.singleton.startMeasurements() Orientation.singleton.startMeasurements()
let slideDuration = 150 // ms let slideDuration = 150 // ms
@ -148,7 +151,7 @@
const bottomRight = mlmap.unproject([rect.right, rect.bottom]) const bottomRight = mlmap.unproject([rect.right, rect.bottom])
const bbox = new BBox([ const bbox = new BBox([
[topLeft.lng, topLeft.lat], [topLeft.lng, topLeft.lat],
[bottomRight.lng, bottomRight.lat], [bottomRight.lng, bottomRight.lat]
]) ])
state.visualFeedbackViewportBounds.setData(bbox) state.visualFeedbackViewportBounds.setData(bbox)
} }
@ -500,5 +503,24 @@
{/if} {/if}
{/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} /> <MenuDrawer onlyLink={false} {state} />
</main> </main>