Many UI improvements

This commit is contained in:
Pieter Vander Vennet 2024-06-18 03:33:11 +02:00
parent ef158ec914
commit 1098d71aa6
30 changed files with 5601 additions and 569 deletions

View file

@ -16,7 +16,7 @@
"id": "images", "id": "images",
"description": "This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` and shows the button to upload new images", "description": "This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` and shows the button to upload new images",
"render": { "render": {
"*": "{image_carousel()}{image_upload()}{nearby_images():my-4}" "*": "{image_carousel()}{image_upload()}"
}, },
"classes": "my-4" "classes": "my-4"
}, },
@ -1633,51 +1633,6 @@
"*": "{all_tags()}" "*": "{all_tags()}"
} }
}, },
{
"id": "just_created",
"labels": [
"added_by_default"
],
"description": "This element shows a 'thank you' that the contributor has recently created this element",
"classes": "rounded-xl thanks",
"mappings": [
{
"if": "id~*",
"icon": "./assets/svg/party.svg",
"then": {
"ca": "Acabeu de crear aquest element! Gràcies per compartir aquesta informació amb el mon i ajudar a persones al voltant del món.",
"de": "Sie haben gerade dieses Element erstellt! Vielen Dank, dass Sie diese Informationen mit der Welt teilen und Menschen weltweit helfen.",
"en": "You just created this element! Thanks for sharing this info with the world and helping people worldwide.",
"fr": "Vous venez de créer cet élément ! Merci d'avoir partagé cette information avec le monde et d'aider les autres personnes.",
"nl": "Je hebt dit punt net toegevoegd! Bedankt om deze info met iedereen te delen en om de mensen wereldwijd te helpen.",
"cs": "Tento prvek jste právě vytvořili! Díky za sdílení těchto informací se světem a pomoc lidem po celém světě."
}
}
],
"condition": {
"and": [
"_backend~*",
"_last_edit:passed_time<300",
{
"or": [
"_version_number=",
"_version_number=1"
]
}
]
},
"metacondition": {
"and": [
{
"#": "if _last_edit:contributor:uid is unset, then the point hasn't been uploaded yet",
"or": [
"_last_edit:contributor:uid:={_uid}",
"_last_edit:contributor:uid="
]
}
]
}
},
{ {
"id": "multilevels", "id": "multilevels",
"builtin": "single_level", "builtin": "single_level",
@ -2627,6 +2582,60 @@
} }
] ]
}, },
{
"id": "just_created",
"labels": [
"added_by_default_top"
],
"description": "This element shows a 'thank you' that the contributor has recently created this element",
"classes": "rounded-xl thanks",
"mappings": [
{
"if": "id~*",
"icon": "./assets/svg/party.svg",
"then": {
"ca": "Acabeu de crear aquest element! Gràcies per compartir aquesta informació amb el mon i ajudar a persones al voltant del món.",
"de": "Sie haben gerade dieses Element erstellt! Vielen Dank, dass Sie diese Informationen mit der Welt teilen und Menschen weltweit helfen.",
"en": "You just created this element! Thanks for sharing this info with the world and helping people worldwide.",
"fr": "Vous venez de créer cet élément ! Merci d'avoir partagé cette information avec le monde et d'aider les autres personnes.",
"nl": "Je hebt dit punt net toegevoegd! Bedankt om deze info met iedereen te delen en om de mensen wereldwijd te helpen.",
"cs": "Tento prvek jste právě vytvořili! Díky za sdílení těchto informací se světem a pomoc lidem po celém světě."
}
}
],
"condition": {
"and": [
"_backend~*",
"_last_edit:passed_time<300",
{
"or": [
"_version_number=",
"_version_number=1"
]
}
]
},
"metacondition": {
"and": [
{
"#": "if _last_edit:contributor:uid is unset, then the point hasn't been uploaded yet",
"or": [
"_last_edit:contributor:uid:={_uid}",
"_last_edit:contributor:uid="
]
}
]
}
},
{
"id": "nearby_images",
"labels": [
"added_by_default_conditional"
],
"render": {
"*": "{nearby_images()}"
}
},
{ {
"id": "lod", "id": "lod",
"labels": [ "labels": [
@ -2636,6 +2645,22 @@
"*": "{linked_data_from_website()}" "*": "{linked_data_from_website()}"
} }
}, },
{
"id": "split_button",
"#": "Added by syntactic sugar, no label needed",
"render": {
"*": "{split_button()}"
}
},
{
"id": "favourite_status",
"labels": [
"added_by_default"
],
"render": {
"*": "{favourite_status()}"
}
},
{ {
"id": "share", "id": "share",
"labels": [ "labels": [
@ -2709,7 +2734,7 @@
{ {
"id": "nothing_known", "id": "nothing_known",
"labels": [ "labels": [
"added_by_default" "added_by_default_top"
], ],
"condition": { "condition": {
"and": [ "and": [

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 169.460938 135.585938 C 184.714844 135.585938 197.761719 141.003906 208.59375 151.835938 C 219.425781 162.667969 224.84375 175.714844 224.84375 190.972656 C 224.84375 206.226562 219.425781 219.273438 208.59375 230.105469 C 197.761719 240.9375 184.714844 246.355469 169.460938 246.355469 C 154.203125 246.355469 141.160156 240.9375 130.324219 230.105469 C 119.492188 219.273438 114.074219 206.226562 114.074219 190.972656 C 114.074219 175.714844 119.492188 162.667969 130.324219 151.835938 C 141.160156 141.003906 154.203125 135.585938 169.460938 135.585938 M 322.921875 74.816406 C 336.511719 74.816406 348.113281 79.625 357.730469 89.242188 C 367.34375 98.855469 372.152344 110.457031 372.152344 124.046875 L 372.152344 296.355469 C 372.152344 309.945312 367.34375 321.546875 357.730469 331.164062 C 348.113281 340.777344 336.511719 345.585938 322.921875 345.585938 L 52.152344 345.585938 C 38.5625 345.585938 26.960938 340.777344 17.34375 331.164062 C 7.730469 321.546875 2.921875 309.945312 2.921875 296.355469 L 2.921875 124.046875 C 2.921875 110.457031 7.730469 98.855469 17.34375 89.242188 C 26.960938 79.625 38.5625 74.816406 52.152344 74.816406 L 77.152344 74.816406 L 86.960938 48.664062 C 89.394531 42.382812 93.851562 36.964844 100.324219 32.414062 C 106.800781 27.863281 113.433594 25.585938 120.230469 25.585938 L 218.691406 25.585938 C 225.484375 25.585938 232.121094 27.863281 238.59375 32.414062 C 245.070312 36.964844 249.523438 42.382812 251.960938 48.664062 L 261.765625 74.816406 L 322.921875 74.816406 M 169.460938 277.125 C 193.175781 277.125 213.464844 268.695312 230.324219 251.835938 C 247.183594 234.976562 255.613281 214.6875 255.613281 190.972656 C 255.613281 167.253906 247.183594 146.964844 230.324219 130.105469 C 213.464844 113.246094 193.175781 104.816406 169.460938 104.816406 C 145.742188 104.816406 125.453125 113.246094 108.59375 130.105469 C 91.734375 146.964844 83.304688 167.253906 83.304688 190.972656 C 83.304688 214.6875 91.734375 234.976562 108.59375 251.835938 C 125.453125 268.695312 145.742188 277.125 169.460938 277.125 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(49.411765%,73.725492%,43.529412%);fill-opacity:1;" d="M 374.332031 308.261719 C 374.332031 343.875 345.464844 372.746094 309.851562 372.746094 C 274.238281 372.746094 245.371094 343.875 245.371094 308.261719 C 245.371094 272.652344 274.238281 243.78125 309.851562 243.78125 C 345.464844 243.78125 374.332031 272.652344 374.332031 308.261719 Z M 374.332031 308.261719 "/>
<path style="fill:none;stroke-width:95.518036;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 1154.783124 1044.338782 L 1543.909686 1044.338782 " transform="matrix(0.192308,0,0,0.192308,49.973197,107.396088)"/>
<path style="fill:none;stroke-width:95.518036;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 1349.925311 849.359094 L 1349.925311 1238.505969 " transform="matrix(0.192308,0,0,0.192308,49.973197,107.396088)"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 375 188.21875 C 375 291.375 291.375 375 188.21875 375 C 85.0625 375 1.4375 291.375 1.4375 188.21875 C 1.4375 85.0625 85.0625 1.4375 188.21875 1.4375 C 291.375 1.4375 375 85.0625 375 188.21875 Z M 375 188.21875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 147.335938 143.246094 L 147.335938 240.035156 C 147.335938 241.605469 146.832031 242.894531 145.824219 243.902344 C 144.8125 244.910156 143.527344 245.414062 141.957031 245.414062 L 131.203125 245.414062 C 129.632812 245.414062 128.347656 244.910156 127.339844 243.902344 C 126.328125 242.894531 125.824219 241.605469 125.824219 240.035156 L 125.824219 143.246094 C 125.824219 141.675781 126.328125 140.390625 127.339844 139.378906 C 128.347656 138.371094 129.632812 137.867188 131.203125 137.867188 L 141.957031 137.867188 C 143.527344 137.867188 144.8125 138.371094 145.824219 139.378906 C 146.832031 140.390625 147.335938 141.675781 147.335938 143.246094 Z M 190.351562 143.246094 L 190.351562 240.035156 C 190.351562 241.605469 189.847656 242.894531 188.839844 243.902344 C 187.832031 244.910156 186.542969 245.414062 184.976562 245.414062 L 174.222656 245.414062 C 172.652344 245.414062 171.363281 244.910156 170.355469 243.902344 C 169.347656 242.894531 168.84375 241.605469 168.84375 240.035156 L 168.84375 143.246094 C 168.84375 141.675781 169.347656 140.390625 170.355469 139.378906 C 171.363281 138.371094 172.652344 137.867188 174.222656 137.867188 L 184.976562 137.867188 C 186.542969 137.867188 187.832031 138.371094 188.839844 139.378906 C 189.847656 140.390625 190.351562 141.675781 190.351562 143.246094 Z M 233.371094 143.246094 L 233.371094 240.035156 C 233.371094 241.605469 232.867188 242.894531 231.859375 243.902344 C 230.851562 244.910156 229.5625 245.414062 227.992188 245.414062 L 217.238281 245.414062 C 215.671875 245.414062 214.382812 244.910156 213.375 243.902344 C 212.367188 242.894531 211.863281 241.605469 211.863281 240.035156 L 211.863281 143.246094 C 211.863281 141.675781 212.367188 140.390625 213.375 139.378906 C 214.382812 138.371094 215.671875 137.867188 217.238281 137.867188 L 227.992188 137.867188 C 229.5625 137.867188 230.851562 138.371094 231.859375 139.378906 C 232.867188 140.390625 233.371094 141.675781 233.371094 143.246094 Z M 254.878906 264.90625 L 254.878906 105.605469 L 104.316406 105.605469 L 104.316406 264.90625 C 104.316406 267.371094 104.707031 269.640625 105.492188 271.710938 C 106.277344 273.785156 107.089844 275.296875 107.929688 276.25 C 108.769531 277.199219 109.359375 277.675781 109.695312 277.675781 L 249.503906 277.675781 C 249.839844 277.675781 250.425781 277.199219 251.265625 276.25 C 252.109375 275.296875 252.917969 273.785156 253.703125 271.710938 C 254.488281 269.640625 254.878906 267.371094 254.878906 264.90625 Z M 141.957031 84.09375 L 217.238281 84.09375 L 209.171875 64.433594 C 208.390625 63.425781 207.4375 62.8125 206.316406 62.585938 L 153.046875 62.585938 C 151.929688 62.8125 150.976562 63.425781 150.191406 64.433594 Z M 297.898438 89.472656 L 297.898438 100.226562 C 297.898438 101.796875 297.394531 103.085938 296.386719 104.09375 C 295.378906 105.101562 294.089844 105.605469 292.519531 105.605469 L 276.390625 105.605469 L 276.390625 264.90625 C 276.390625 274.203125 273.757812 282.242188 268.492188 289.019531 C 263.226562 295.796875 256.898438 299.1875 249.503906 299.1875 L 109.695312 299.1875 C 102.300781 299.1875 95.972656 295.910156 90.707031 289.355469 C 85.441406 282.800781 82.808594 274.875 82.808594 265.578125 L 82.808594 105.605469 L 66.675781 105.605469 C 65.109375 105.605469 63.820312 105.101562 62.8125 104.09375 C 61.804688 103.085938 61.296875 101.796875 61.296875 100.226562 L 61.296875 89.472656 C 61.296875 87.90625 61.804688 86.617188 62.8125 85.609375 C 63.820312 84.601562 65.109375 84.09375 66.675781 84.09375 L 118.601562 84.09375 L 130.363281 56.03125 C 132.042969 51.886719 135.066406 48.359375 139.4375 45.445312 C 143.804688 42.535156 148.230469 41.078125 152.710938 41.078125 L 206.484375 41.078125 C 210.964844 41.078125 215.390625 42.535156 219.761719 45.445312 C 224.128906 48.359375 227.152344 51.886719 228.835938 56.03125 L 240.597656 84.09375 L 292.519531 84.09375 C 294.089844 84.09375 295.378906 84.601562 296.386719 85.609375 C 297.394531 86.617188 297.898438 87.90625 297.898438 89.472656 Z M 297.898438 89.472656 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90.588236%,17.254902%,26.666668%);fill-opacity:1;" d="M 326.640625 251.804688 C 326.640625 291.601562 294.378906 323.859375 254.585938 323.859375 C 214.792969 323.859375 182.53125 291.601562 182.53125 251.804688 C 182.53125 212.011719 214.792969 179.753906 254.585938 179.753906 C 294.378906 179.753906 326.640625 212.011719 326.640625 251.804688 Z M 326.640625 251.804688 "/>
<path style="fill:none;stroke-width:6.012842;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 22.552149 293.60302 L 2.927989 273.97886 " transform="matrix(3.127323,0,0,3.127323,214.214326,-636.824371)"/>
<path style="fill:none;stroke-width:6.012842;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(98.823529%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 22.580878 273.88393 L 2.956718 293.508091 " transform="matrix(3.127323,0,0,3.127323,214.214326,-636.824371)"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -129,30 +129,6 @@
" https://github.com/primer/octicons" " https://github.com/primer/octicons"
] ]
}, },
{
"path": "camera-plus.svg",
"license": "CC-BY-SA-3.0",
"authors": [
"Dave Gandy",
"Pieter Vander Vennet"
],
"sources": [
"https://fontawesome.com/",
"https://commons.wikimedia.org/wiki/File:Camera_font_awesome.svg"
]
},
{
"path": "camera-plus.svg",
"license": "CC-BY-SA-3.0",
"authors": [
"Dave Gandy",
"Pieter Vander Vennet"
],
"sources": [
"https://fontawesome.com/",
"https://commons.wikimedia.org/wiki/File:Camera_font_awesome.svg"
]
},
{ {
"path": "center.svg", "path": "center.svg",
"license": "CC0-1.0", "license": "CC0-1.0",
@ -323,14 +299,6 @@
"https://commons.wikimedia.org/wiki/File:Trash_font_awesome.svg\rT" "https://commons.wikimedia.org/wiki/File:Trash_font_awesome.svg\rT"
] ]
}, },
{
"path": "delete_not_allowed.svg",
"license": "CC0-1.0",
"authors": [
"Pieter Vander Vennet"
],
"sources": []
},
{ {
"path": "direction_gradient.svg", "path": "direction_gradient.svg",
"license": "TRIVIAL", "license": "TRIVIAL",

View file

@ -1,2 +0,0 @@
SPDX-FileCopyrightText: SVG Repo
SPDX-License-Identifier: CC0-1.0

View file

@ -1,17 +1,13 @@
{ {
"id": "mapcomplete-changes", "id": "mapcomplete-changes",
"title": { "title": {
"en": "Changes made with MapComplete", "en": "Changes made with MapComplete"
"de": "Änderungen mit MapComplete"
}, },
"shortDescription": { "shortDescription": {
"en": "Shows changes made by MapComplete", "en": "Shows changes made by MapComplete"
"de": "Änderungen von MapComplete anzeigen"
}, },
"description": { "description": {
"en": "This maps shows all the changes made with MapComplete", "en": "This maps shows all the changes made with MapComplete"
"de": "Diese Karte zeigt alle mit MapComplete vorgenommenen Änderungen",
"pl": "Ta mapa pokazuje wszystkie zmiany wprowadzone za pomocą MapComplete"
}, },
"icon": "./assets/svg/logo.svg", "icon": "./assets/svg/logo.svg",
"hideFromOverview": true, "hideFromOverview": true,
@ -22,9 +18,7 @@
{ {
"id": "mapcomplete-changes", "id": "mapcomplete-changes",
"name": { "name": {
"en": "Changeset centers", "en": "Changeset centers"
"de": "Zentrum der Änderungssätze",
"zh_Hant": "變更集中心"
}, },
"minzoom": 0, "minzoom": 0,
"source": { "source": {
@ -34,48 +28,41 @@
}, },
"title": { "title": {
"render": { "render": {
"en": "Changeset for {theme}", "en": "Changeset for {theme}"
"de": "Änderungssatz für {theme}"
} }
}, },
"description": { "description": {
"en": "Shows all MapComplete changes", "en": "Shows all MapComplete changes"
"de": "Alle MapComplete-Änderungen anzeigen"
}, },
"tagRenderings": [ "tagRenderings": [
{ {
"id": "show_changeset_id", "id": "show_changeset_id",
"render": { "render": {
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>", "en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
"de": "Änderungssatz <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
} }
}, },
{ {
"id": "contributor", "id": "contributor",
"question": { "question": {
"en": "What contributor did make this change?", "en": "What contributor did make this change?"
"de": "Welcher Mitwirkende hat diese Änderung vorgenommen?"
}, },
"freeform": { "freeform": {
"key": "user" "key": "user"
}, },
"render": { "render": {
"en": "Change made by <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>", "en": "Change made by <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>"
"de": "Änderung vorgenommen von <a href='https://openstreetmap.org/user/{user}' target='_blank'>{user}</a>"
} }
}, },
{ {
"id": "theme-id", "id": "theme-id",
"question": { "question": {
"en": "What theme was used to make this change?", "en": "What theme was used to make this change?"
"de": "Welches Thema wurde für die Änderung verwendet?"
}, },
"freeform": { "freeform": {
"key": "theme" "key": "theme"
}, },
"render": { "render": {
"en": "Change with theme <a href='https://mapcomplete.org/{theme}'>{theme}</a>", "en": "Change with theme <a href='https://mapcomplete.org/{theme}'>{theme}</a>"
"de": "Geändert mit Thema <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>"
} }
}, },
{ {
@ -84,23 +71,19 @@
"key": "locale" "key": "locale"
}, },
"question": { "question": {
"en": "What locale (language) was this change made in?", "en": "What locale (language) was this change made in?"
"de": "In welcher Benutzersprache wurde die Änderung vorgenommen?"
}, },
"render": { "render": {
"en": "User locale is {locale}", "en": "User locale is {locale}"
"de": "Benutzersprache {locale}"
} }
}, },
{ {
"id": "host", "id": "host",
"render": { "render": {
"en": "Change with with <a href='{host}'>{host}</a>", "en": "Change with with <a href='{host}'>{host}</a>"
"de": "Änderung über <a href='{host}'>{host}</a>"
}, },
"question": { "question": {
"en": "What host (website) was this change made with?", "en": "What host (website) was this change made with?"
"de": "Über welchen Host (Webseite) wurde diese Änderung vorgenommen?"
}, },
"freeform": { "freeform": {
"key": "host" "key": "host"
@ -121,12 +104,10 @@
{ {
"id": "version", "id": "version",
"question": { "question": {
"en": "What version of MapComplete was used to make this change?", "en": "What version of MapComplete was used to make this change?"
"de": "Mit welcher MapComplete Version wurde die Änderung vorgenommen?"
}, },
"render": { "render": {
"en": "Made with {editor}", "en": "Made with {editor}"
"de": "Erstellt mit {editor}"
}, },
"freeform": { "freeform": {
"key": "editor" "key": "editor"
@ -512,9 +493,7 @@
} }
], ],
"question": { "question": {
"en": "Themename contains {search}", "en": "Themename contains {search}"
"de": "Themenname enthält {search}",
"pl": "Nazwa tematu zawiera {search}"
} }
} }
] ]
@ -530,8 +509,7 @@
} }
], ],
"question": { "question": {
"en": "Themename does <b>not</b> contain {search}", "en": "Themename does <b>not</b> contain {search}"
"de": "Themename enthält <b>not</b> {search}"
} }
} }
] ]
@ -547,8 +525,7 @@
} }
], ],
"question": { "question": {
"en": "Made by contributor {search}", "en": "Made by contributor {search}"
"de": "Erstellt vom Mitwirkenden {search}"
} }
} }
] ]
@ -564,8 +541,7 @@
} }
], ],
"question": { "question": {
"en": "<b>Not</b> made by contributor {search}", "en": "<b>Not</b> made by contributor {search}"
"de": "<b>Nicht</b> erstellt von Mitwirkendem {search}"
} }
} }
] ]
@ -582,8 +558,7 @@
} }
], ],
"question": { "question": {
"en": "Made before {search}", "en": "Made before {search}"
"de": "Erstellt vor {search}"
} }
} }
] ]
@ -600,8 +575,7 @@
} }
], ],
"question": { "question": {
"en": "Made after {search}", "en": "Made after {search}"
"de": "Erstellt nach {search}"
} }
} }
] ]
@ -617,8 +591,7 @@
} }
], ],
"question": { "question": {
"en": "User language (iso-code) {search}", "en": "User language (iso-code) {search}"
"de": "Benutzersprache (ISO-Code) {search}"
} }
} }
] ]
@ -634,8 +607,7 @@
} }
], ],
"question": { "question": {
"en": "Made with host {search}", "en": "Made with host {search}"
"de": "Erstellt mit Host {search}"
} }
} }
] ]
@ -646,8 +618,7 @@
{ {
"osmTags": "add-image>0", "osmTags": "add-image>0",
"question": { "question": {
"en": "Changeset added at least one image", "en": "Changeset added at least one image"
"de": "Änderungssatz hat mindestens ein Bild hinzugefügt"
} }
} }
] ]
@ -658,8 +629,7 @@
{ {
"osmTags": "theme!=grb", "osmTags": "theme!=grb",
"question": { "question": {
"en": "Exclude GRB theme", "en": "Exclude GRB theme"
"de": "GRB-Thema ausschließen"
} }
} }
] ]
@ -670,8 +640,7 @@
{ {
"osmTags": "theme!=etymology", "osmTags": "theme!=etymology",
"question": { "question": {
"en": "Exclude etymology theme", "en": "Exclude etymology theme"
"de": "Etymologie-Thema ausschließen"
} }
} }
] ]
@ -686,8 +655,7 @@
{ {
"id": "link_to_more", "id": "link_to_more",
"render": { "render": {
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>", "en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>"
"de": "Weitere Statistiken gibt es <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>hier</a>"
} }
}, },
{ {

370
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "mapcomplete", "name": "mapcomplete",
"version": "0.43.1", "version": "0.43.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "mapcomplete", "name": "mapcomplete",
"version": "0.43.1", "version": "0.43.2",
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"dependencies": { "dependencies": {
"@comunica/core": "^3.0.1", "@comunica/core": "^3.0.1",
@ -40,6 +40,7 @@
"email-validator": "^2.0.4", "email-validator": "^2.0.4",
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"fake-dom": "^1.0.4", "fake-dom": "^1.0.4",
"flowbite-svelte": "^0.46.2",
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
"geojson2svg": "^1.3.3", "geojson2svg": "^1.3.3",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",
@ -73,7 +74,6 @@
"svg-path-parser": "^1.1.0", "svg-path-parser": "^1.1.0",
"tailwind-merge": "^1.13.1", "tailwind-merge": "^1.13.1",
"tailwindcss": "^3.1.8", "tailwindcss": "^3.1.8",
"trap-focus-svelte": "^1.0.2",
"turndown": "^7.1.3", "turndown": "^7.1.3",
"vite-node": "^0.28.3", "vite-node": "^0.28.3",
"vitest": "^0.28.3", "vitest": "^0.28.3",
@ -1489,15 +1489,21 @@
} }
}, },
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {
"version": "7.20.7", "version": "7.24.7",
"license": "MIT", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz",
"integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==",
"dependencies": { "dependencies": {
"regenerator-runtime": "^0.13.11" "regenerator-runtime": "^0.14.0"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/runtime/node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
"node_modules/@babel/template": { "node_modules/@babel/template": {
"version": "7.22.15", "version": "7.22.15",
"dev": true, "dev": true,
@ -4556,6 +4562,28 @@
"node": ">=14" "node": ">=14"
} }
}, },
"node_modules/@floating-ui/core": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz",
"integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==",
"dependencies": {
"@floating-ui/utils": "^0.2.0"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz",
"integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==",
"dependencies": {
"@floating-ui/core": "^1.0.0",
"@floating-ui/utils": "^0.2.0"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz",
"integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw=="
},
"node_modules/@humanwhocodes/config-array": { "node_modules/@humanwhocodes/config-array": {
"version": "0.11.10", "version": "0.11.10",
"dev": true, "dev": true,
@ -4883,6 +4911,15 @@
"url": "https://opencollective.com/parcel" "url": "https://opencollective.com/parcel"
} }
}, },
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rapideditor/country-coder": { "node_modules/@rapideditor/country-coder": {
"version": "5.2.2", "version": "5.2.2",
"resolved": "https://registry.npmjs.org/@rapideditor/country-coder/-/country-coder-5.2.2.tgz", "resolved": "https://registry.npmjs.org/@rapideditor/country-coder/-/country-coder-5.2.2.tgz",
@ -7209,6 +7246,11 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/@yr/monotone-cubic-spline": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
},
"node_modules/abab": { "node_modules/abab": {
"version": "2.0.6", "version": "2.0.6",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
@ -7383,6 +7425,20 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/apexcharts": {
"version": "3.49.1",
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.49.1.tgz",
"integrity": "sha512-MqGtlq/KQuO8j0BBsUJYlRG8VBctKwYdwuBtajHgHTmSgUU3Oai+8oYN/rKCXwXzrUlYA+GiMgotAIbXY2BCGw==",
"dependencies": {
"@yr/monotone-cubic-spline": "^1.0.3",
"svg.draggable.js": "^2.2.2",
"svg.easing.js": "^2.0.0",
"svg.filter.js": "^2.0.2",
"svg.pathmorphing.js": "^0.1.3",
"svg.resize.js": "^1.4.3",
"svg.select.js": "^3.0.1"
}
},
"node_modules/app-root-path": { "node_modules/app-root-path": {
"version": "3.1.0", "version": "3.1.0",
"dev": true, "dev": true,
@ -9819,6 +9875,45 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/flowbite": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/flowbite/-/flowbite-2.3.0.tgz",
"integrity": "sha512-pm3JRo8OIJHGfFYWgaGpPv8E+UdWy0Z3gEAGufw+G/1dusaU/P1zoBLiQpf2/+bYAi+GBQtPVG86KYlV0W+AFQ==",
"dependencies": {
"@popperjs/core": "^2.9.3",
"mini-svg-data-uri": "^1.4.3"
}
},
"node_modules/flowbite-svelte": {
"version": "0.46.2",
"resolved": "https://registry.npmjs.org/flowbite-svelte/-/flowbite-svelte-0.46.2.tgz",
"integrity": "sha512-nOPJ4xBq3T/s3yiow+YyabupWiPqj1TQ7Fv12gLYTHFsjwBOcelWPEFbe1G/yO8a6gm243QE9KG9m+ag/N7KyA==",
"dependencies": {
"@floating-ui/dom": "^1.6.5",
"apexcharts": "^3.49.1",
"flowbite": "^2.3.0",
"tailwind-merge": "^2.3.0"
},
"engines": {
"node": ">=18.0.0",
"pnpm": ">=8.0.0"
},
"peerDependencies": {
"svelte": "^3.55.1 || ^4.0.0"
}
},
"node_modules/flowbite-svelte/node_modules/tailwind-merge": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.3.0.tgz",
"integrity": "sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==",
"dependencies": {
"@babel/runtime": "^7.24.1"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
}
},
"node_modules/fn.name": { "node_modules/fn.name": {
"version": "1.1.0", "version": "1.1.0",
"license": "MIT" "license": "MIT"
@ -11815,6 +11910,14 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"bin": {
"mini-svg-data-uri": "cli.js"
}
},
"node_modules/minimalistic-assert": { "node_modules/minimalistic-assert": {
"version": "1.0.1", "version": "1.0.1",
"license": "ISC" "license": "ISC"
@ -16213,6 +16316,7 @@
}, },
"node_modules/regenerator-runtime": { "node_modules/regenerator-runtime": {
"version": "0.13.11", "version": "0.13.11",
"devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/regenerator-transform": { "node_modules/regenerator-transform": {
@ -17476,6 +17580,89 @@
"node": ">=12.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/svg.draggable.js": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz",
"integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==",
"dependencies": {
"svg.js": "^2.0.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/svg.easing.js": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz",
"integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==",
"dependencies": {
"svg.js": ">=2.3.x"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/svg.filter.js": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz",
"integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==",
"dependencies": {
"svg.js": "^2.2.5"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/svg.js": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz",
"integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA=="
},
"node_modules/svg.pathmorphing.js": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz",
"integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==",
"dependencies": {
"svg.js": "^2.4.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/svg.resize.js": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz",
"integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==",
"dependencies": {
"svg.js": "^2.6.5",
"svg.select.js": "^2.1.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/svg.resize.js/node_modules/svg.select.js": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz",
"integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==",
"dependencies": {
"svg.js": "^2.2.5"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/svg.select.js": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz",
"integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==",
"dependencies": {
"svg.js": "^2.6.5"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/symbol-tree": { "node_modules/symbol-tree": {
"version": "3.2.4", "version": "3.2.4",
"license": "MIT" "license": "MIT"
@ -17786,11 +17973,6 @@
"node": ">=14" "node": ">=14"
} }
}, },
"node_modules/trap-focus-svelte": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/trap-focus-svelte/-/trap-focus-svelte-1.0.2.tgz",
"integrity": "sha512-2I5V22WMxnoVDkx1mvjKjxR0fl3V5ra9vOZCV4y9iXm3AHJgYugQbCO2e6IuF4seBsadS8mtzAwQTzZDVD3oqg=="
},
"node_modules/triple-beam": { "node_modules/triple-beam": {
"version": "1.4.1", "version": "1.4.1",
"license": "MIT", "license": "MIT",
@ -20171,9 +20353,18 @@
} }
}, },
"@babel/runtime": { "@babel/runtime": {
"version": "7.20.7", "version": "7.24.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz",
"integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==",
"requires": { "requires": {
"regenerator-runtime": "^0.13.11" "regenerator-runtime": "^0.14.0"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
}
} }
}, },
"@babel/template": { "@babel/template": {
@ -22829,6 +23020,28 @@
"@fastify/busboy": { "@fastify/busboy": {
"version": "2.1.0" "version": "2.1.0"
}, },
"@floating-ui/core": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz",
"integrity": "sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==",
"requires": {
"@floating-ui/utils": "^0.2.0"
}
},
"@floating-ui/dom": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz",
"integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==",
"requires": {
"@floating-ui/core": "^1.0.0",
"@floating-ui/utils": "^0.2.0"
}
},
"@floating-ui/utils": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz",
"integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw=="
},
"@humanwhocodes/config-array": { "@humanwhocodes/config-array": {
"version": "0.11.10", "version": "0.11.10",
"dev": true, "dev": true,
@ -23039,6 +23252,11 @@
"version": "2.8.2", "version": "2.8.2",
"dev": true "dev": true
}, },
"@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
},
"@rapideditor/country-coder": { "@rapideditor/country-coder": {
"version": "5.2.2", "version": "5.2.2",
"resolved": "https://registry.npmjs.org/@rapideditor/country-coder/-/country-coder-5.2.2.tgz", "resolved": "https://registry.npmjs.org/@rapideditor/country-coder/-/country-coder-5.2.2.tgz",
@ -24636,6 +24854,11 @@
"@xmldom/xmldom": { "@xmldom/xmldom": {
"version": "0.8.3" "version": "0.8.3"
}, },
"@yr/monotone-cubic-spline": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
},
"abab": { "abab": {
"version": "2.0.6", "version": "2.0.6",
"optional": true, "optional": true,
@ -24752,6 +24975,20 @@
"picomatch": "^2.0.4" "picomatch": "^2.0.4"
} }
}, },
"apexcharts": {
"version": "3.49.1",
"resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.49.1.tgz",
"integrity": "sha512-MqGtlq/KQuO8j0BBsUJYlRG8VBctKwYdwuBtajHgHTmSgUU3Oai+8oYN/rKCXwXzrUlYA+GiMgotAIbXY2BCGw==",
"requires": {
"@yr/monotone-cubic-spline": "^1.0.3",
"svg.draggable.js": "^2.2.2",
"svg.easing.js": "^2.0.0",
"svg.filter.js": "^2.0.2",
"svg.pathmorphing.js": "^0.1.3",
"svg.resize.js": "^1.4.3",
"svg.select.js": "^3.0.1"
}
},
"app-root-path": { "app-root-path": {
"version": "3.1.0", "version": "3.1.0",
"dev": true "dev": true
@ -26290,6 +26527,36 @@
"version": "3.2.7", "version": "3.2.7",
"dev": true "dev": true
}, },
"flowbite": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/flowbite/-/flowbite-2.3.0.tgz",
"integrity": "sha512-pm3JRo8OIJHGfFYWgaGpPv8E+UdWy0Z3gEAGufw+G/1dusaU/P1zoBLiQpf2/+bYAi+GBQtPVG86KYlV0W+AFQ==",
"requires": {
"@popperjs/core": "^2.9.3",
"mini-svg-data-uri": "^1.4.3"
}
},
"flowbite-svelte": {
"version": "0.46.2",
"resolved": "https://registry.npmjs.org/flowbite-svelte/-/flowbite-svelte-0.46.2.tgz",
"integrity": "sha512-nOPJ4xBq3T/s3yiow+YyabupWiPqj1TQ7Fv12gLYTHFsjwBOcelWPEFbe1G/yO8a6gm243QE9KG9m+ag/N7KyA==",
"requires": {
"@floating-ui/dom": "^1.6.5",
"apexcharts": "^3.49.1",
"flowbite": "^2.3.0",
"tailwind-merge": "^2.3.0"
},
"dependencies": {
"tailwind-merge": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.3.0.tgz",
"integrity": "sha512-vkYrLpIP+lgR0tQCG6AP7zZXCTLc1Lnv/CCRT3BqJ9CZ3ui2++GPaGb1x/ILsINIMSYqqvrpqjUFsMNLlW99EA==",
"requires": {
"@babel/runtime": "^7.24.1"
}
}
}
},
"fn.name": { "fn.name": {
"version": "1.1.0" "version": "1.1.0"
}, },
@ -27546,6 +27813,11 @@
"version": "1.0.1", "version": "1.0.1",
"dev": true "dev": true
}, },
"mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg=="
},
"minimalistic-assert": { "minimalistic-assert": {
"version": "1.0.1" "version": "1.0.1"
}, },
@ -30384,7 +30656,8 @@
} }
}, },
"regenerator-runtime": { "regenerator-runtime": {
"version": "0.13.11" "version": "0.13.11",
"devOptional": true
}, },
"regenerator-transform": { "regenerator-transform": {
"version": "0.15.1", "version": "0.15.1",
@ -31178,6 +31451,70 @@
"version": "6.0.3", "version": "6.0.3",
"optional": true "optional": true
}, },
"svg.draggable.js": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz",
"integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==",
"requires": {
"svg.js": "^2.0.1"
}
},
"svg.easing.js": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz",
"integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==",
"requires": {
"svg.js": ">=2.3.x"
}
},
"svg.filter.js": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz",
"integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==",
"requires": {
"svg.js": "^2.2.5"
}
},
"svg.js": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz",
"integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA=="
},
"svg.pathmorphing.js": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz",
"integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==",
"requires": {
"svg.js": "^2.4.0"
}
},
"svg.resize.js": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz",
"integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==",
"requires": {
"svg.js": "^2.6.5",
"svg.select.js": "^2.1.2"
},
"dependencies": {
"svg.select.js": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz",
"integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==",
"requires": {
"svg.js": "^2.2.5"
}
}
}
},
"svg.select.js": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz",
"integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==",
"requires": {
"svg.js": "^2.6.5"
}
},
"symbol-tree": { "symbol-tree": {
"version": "3.2.4" "version": "3.2.4"
}, },
@ -31386,11 +31723,6 @@
"punycode": "^2.3.0" "punycode": "^2.3.0"
} }
}, },
"trap-focus-svelte": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/trap-focus-svelte/-/trap-focus-svelte-1.0.2.tgz",
"integrity": "sha512-2I5V22WMxnoVDkx1mvjKjxR0fl3V5ra9vOZCV4y9iXm3AHJgYugQbCO2e6IuF4seBsadS8mtzAwQTzZDVD3oqg=="
},
"triple-beam": { "triple-beam": {
"version": "1.4.1" "version": "1.4.1"
}, },

View file

@ -24,7 +24,7 @@
"mvt_layer_server": "https://cache.mapcomplete.org/public.{type}_{layer}/{z}/{x}/{y}.pbf", "mvt_layer_server": "https://cache.mapcomplete.org/public.{type}_{layer}/{z}/{x}/{y}.pbf",
"#summary_server": "Should be the endpoint; appending status.json should work", "#summary_server": "Should be the endpoint; appending status.json should work",
"summary_server": "https://cache.mapcomplete.org/", "summary_server": "https://cache.mapcomplete.org/",
"geoip_server":"https://ipinfo.mapcomplete.org/", "geoip_server": "https://ipinfo.mapcomplete.org/",
"disabled:oauth_credentials": { "disabled:oauth_credentials": {
"##": "DEV", "##": "DEV",
"#": "This client-id is registered by 'MapComplete' on https://master.apis.dev.openstreetmap.org/", "#": "This client-id is registered by 'MapComplete' on https://master.apis.dev.openstreetmap.org/",
@ -162,6 +162,7 @@
"email-validator": "^2.0.4", "email-validator": "^2.0.4",
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"fake-dom": "^1.0.4", "fake-dom": "^1.0.4",
"flowbite-svelte": "^0.46.2",
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
"geojson2svg": "^1.3.3", "geojson2svg": "^1.3.3",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",

File diff suppressed because it is too large Load diff

View file

@ -10,16 +10,12 @@ import {
PrevalidateTheme, PrevalidateTheme,
ValidateLayer, ValidateLayer,
ValidateThemeAndLayers, ValidateThemeAndLayers,
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"
@ -44,7 +40,6 @@ class ParseLayer extends Conversion<
> { > {
private readonly _prepareLayer: PrepareLayer private readonly _prepareLayer: PrepareLayer
private readonly _doesImageExist: DoesImageExist private readonly _doesImageExist: DoesImageExist
private readonly _options: { readonly addExpandedTagRenderingsToContext?: boolean }
constructor(prepareLayer: PrepareLayer, doesImageExist: DoesImageExist) { constructor(prepareLayer: PrepareLayer, doesImageExist: DoesImageExist) {
super("Parsed a layer from file, validates it", [], "ParseLayer") super("Parsed a layer from file, validates it", [], "ParseLayer")
@ -104,7 +99,7 @@ class AddIconSummary extends DesugaringStep<{ raw: LayerConfigJson; parsed: Laye
super("Adds an icon summary for quick reference", ["_layerIcon"], "AddIconSummary") super("Adds an icon summary for quick reference", ["_layerIcon"], "AddIconSummary")
} }
convert(json: { raw: LayerConfigJson; parsed: LayerConfig }, context: ConversionContext) { convert(json: { raw: LayerConfigJson; parsed: LayerConfig }) {
// Add a summary of the icon // Add a summary of the icon
const fixed = json.raw const fixed = json.raw
const layerConfig = json.parsed const layerConfig = json.parsed
@ -148,7 +143,7 @@ class LayerOverviewUtils extends Script {
themeFile: LayoutConfigJson, themeFile: LayoutConfigJson,
includeInlineLayers = true includeInlineLayers = true
): string[] { ): string[] {
const publicLayerIds = [] const publicLayerIds: string[] = []
if (!Array.isArray(themeFile.layers)) { if (!Array.isArray(themeFile.layers)) {
throw ( throw (
"Cannot iterate over 'layers' of " + "Cannot iterate over 'layers' of " +
@ -163,12 +158,12 @@ class LayerOverviewUtils extends Script {
continue continue
} }
if (publicLayer["builtin"] !== undefined) { if (publicLayer["builtin"] !== undefined) {
const bi = publicLayer["builtin"] const bi : string | string[] = publicLayer["builtin"]
if (typeof bi === "string") { if (typeof bi === "string") {
publicLayerIds.push(bi) publicLayerIds.push(bi)
continue } else {
bi.forEach(id => publicLayerIds.push(id))
} }
bi.forEach((id) => publicLayerIds.push(id))
continue continue
} }
if (includeInlineLayers) { if (includeInlineLayers) {
@ -231,7 +226,7 @@ class LayerOverviewUtils extends Script {
icon: theme.icon, icon: theme.icon,
hideFromOverview: theme.hideFromOverview, hideFromOverview: theme.hideFromOverview,
mustHaveLanguage: theme.mustHaveLanguage, mustHaveLanguage: theme.mustHaveLanguage,
keywords: Utils.NoNull(keywords), keywords: Utils.NoNull(keywords)
} }
perId.set(theme.id, data) perId.set(theme.id, data)
} }
@ -280,18 +275,36 @@ class LayerOverviewUtils extends Script {
) )
} }
static asDict(trs: QuestionableTagRenderingConfigJson[]): Map<string, QuestionableTagRenderingConfigJson> {
const d = new Map<string, QuestionableTagRenderingConfigJson>()
for (const tr of trs) {
d.set(tr.id, tr)
}
return d
}
getSharedTagRenderings(
doesImageExist: DoesImageExist
): QuestionableTagRenderingConfigJson[] ;
getSharedTagRenderings( getSharedTagRenderings(
doesImageExist: DoesImageExist, doesImageExist: DoesImageExist,
bootstrapTagRenderings: Map<string, QuestionableTagRenderingConfigJson> = null bootstrapTagRenderings: Map<string, QuestionableTagRenderingConfigJson>,
): Map<string, QuestionableTagRenderingConfigJson> { bootstrapTagRenderingsOrder: string[]
): QuestionableTagRenderingConfigJson[] ;
getSharedTagRenderings(
doesImageExist: DoesImageExist,
bootstrapTagRenderings: Map<string, QuestionableTagRenderingConfigJson> = null,
bootstrapTagRenderingsOrder: string[] = []
): QuestionableTagRenderingConfigJson[] {
const prepareLayer = new PrepareLayer( const prepareLayer = new PrepareLayer(
{ {
tagRenderings: bootstrapTagRenderings, tagRenderings: bootstrapTagRenderings,
tagRenderingOrder: bootstrapTagRenderingsOrder,
sharedLayers: null, sharedLayers: null,
publicLayers: null, publicLayers: null
}, },
{ {
addTagRenderingsToContext: true, addTagRenderingsToContext: true
} }
) )
@ -306,10 +319,10 @@ class LayerOverviewUtils extends Script {
} }
if (dict.size === bootstrapTagRenderings?.size) { if (dict.size === bootstrapTagRenderings?.size) {
return dict return <QuestionableTagRenderingConfigJson[]>sharedQuestions.tagRenderings
} }
return this.getSharedTagRenderings(doesImageExist, dict) return this.getSharedTagRenderings(doesImageExist, dict, sharedQuestions.tagRenderings.map(tr => tr["id"]))
} }
checkAllSvgs() { checkAllSvgs() {
@ -323,7 +336,7 @@ class LayerOverviewUtils extends Script {
"src/assets/SocialImageBanner.svg", "src/assets/SocialImageBanner.svg",
"src/assets/SocialImageRepo.svg", "src/assets/SocialImageRepo.svg",
"src/assets/svg/osm-logo.svg", "src/assets/svg/osm-logo.svg",
"src/assets/templates/*", "src/assets/templates/*"
] ]
for (const path of allSvgs) { for (const path of allSvgs) {
if ( if (
@ -412,7 +425,7 @@ class LayerOverviewUtils extends Script {
writeFileSync( writeFileSync(
"./src/assets/generated/known_layers.json", "./src/assets/generated/known_layers.json",
JSON.stringify({ JSON.stringify({
layers: Array.from(sharedLayers.values()).filter((l) => l.id !== "favourite"), layers: Array.from(sharedLayers.values()).filter((l) => l.id !== "favourite")
}) })
) )
} }
@ -429,11 +442,11 @@ class LayerOverviewUtils extends Script {
// mapcomplete-changes shows an icon for each corresponding mapcomplete-theme // mapcomplete-changes shows an icon for each corresponding mapcomplete-theme
const iconsPerTheme = Array.from(sharedThemes.values()).map((th) => ({ const iconsPerTheme = Array.from(sharedThemes.values()).map((th) => ({
if: "theme=" + th.id, if: "theme=" + th.id,
then: th.icon, then: th.icon
})) }))
const proto: LayoutConfigJson = JSON.parse( const proto: LayoutConfigJson = JSON.parse(
readFileSync("./assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json", { readFileSync("./assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json", {
encoding: "utf8", encoding: "utf8"
}) })
) )
const protolayer = <LayerConfigJson>( const protolayer = <LayerConfigJson>(
@ -449,7 +462,7 @@ class LayerOverviewUtils extends Script {
new DetectDuplicateFilters().convertStrict( new DetectDuplicateFilters().convertStrict(
{ {
layers: ScriptUtils.getLayerFiles().map((f) => f.parsed), layers: ScriptUtils.getLayerFiles().map((f) => f.parsed),
themes: ScriptUtils.getThemeFiles().map((f) => f.parsed), themes: ScriptUtils.getThemeFiles().map((f) => f.parsed)
}, },
ConversionContext.construct([], []) ConversionContext.construct([], [])
) )
@ -464,7 +477,7 @@ class LayerOverviewUtils extends Script {
writeFileSync( writeFileSync(
"./src/assets/generated/known_themes.json", "./src/assets/generated/known_themes.json",
JSON.stringify({ JSON.stringify({
themes: Array.from(sharedThemes.values()), themes: Array.from(sharedThemes.values())
}) })
) )
} }
@ -505,8 +518,9 @@ class LayerOverviewUtils extends Script {
console.log("Shared questions are:", Array.from(sharedTagRenderings.keys()).join(", ")) console.log("Shared questions are:", Array.from(sharedTagRenderings.keys()).join(", "))
console.log(" ---------- VALIDATING BUILTIN LAYERS ---------") console.log(" ---------- VALIDATING BUILTIN LAYERS ---------")
const state: DesugaringContext = { const state: DesugaringContext = {
tagRenderings: sharedTagRenderings, tagRenderings: LayerOverviewUtils.asDict(sharedTagRenderings),
sharedLayers: AllSharedLayers.getSharedLayersConfigs(), tagRenderingOrder: sharedTagRenderings.map(tr => tr.id),
sharedLayers: AllSharedLayers.getSharedLayersConfigs()
} }
const sharedLayers = new Map<string, LayerConfigJson>() const sharedLayers = new Map<string, LayerConfigJson>()
const prepLayer = new PrepareLayer(state) const prepLayer = new PrepareLayer(state)
@ -578,11 +592,11 @@ class LayerOverviewUtils extends Script {
private extractJavascriptCode(themeFile: LayoutConfigJson) { private extractJavascriptCode(themeFile: LayoutConfigJson) {
const allCode = [ const allCode = [
"import {Feature} from 'geojson'", "import {Feature} from 'geojson'",
'import { ExtraFuncType } from "../../../Logic/ExtraFunctions";', "import { ExtraFuncType } from \"../../../Logic/ExtraFunctions\";",
'import { Utils } from "../../../Utils"', "import { Utils } from \"../../../Utils\"",
"export class ThemeMetaTagging {", "export class ThemeMetaTagging {",
" public static readonly themeName = " + JSON.stringify(themeFile.id), " public static readonly themeName = " + JSON.stringify(themeFile.id),
"", ""
] ]
for (const layer of themeFile.layers) { for (const layer of themeFile.layers) {
const l = <LayerConfigJson>layer const l = <LayerConfigJson>layer
@ -646,7 +660,7 @@ class LayerOverviewUtils extends Script {
`/** This code is autogenerated - do not edit. Edit ./assets/layers/${l?.id}/${l?.id}.json instead */`, `/** This code is autogenerated - do not edit. Edit ./assets/layers/${l?.id}/${l?.id}.json instead */`,
"export class ThemeMetaTagging {", "export class ThemeMetaTagging {",
" public static readonly themeName = " + JSON.stringify(l.id), " public static readonly themeName = " + JSON.stringify(l.id),
"", ""
] ]
const code = l.calculatedTags ?? [] const code = l.calculatedTags ?? []
@ -699,12 +713,15 @@ class LayerOverviewUtils extends Script {
themeFiles.map((th) => th.parsed) themeFiles.map((th) => th.parsed)
) )
const trs = this.getSharedTagRenderings(
new DoesImageExist(licensePaths, existsSync)
)
const convertState: DesugaringContext = { const convertState: DesugaringContext = {
sharedLayers, sharedLayers,
tagRenderings: this.getSharedTagRenderings( tagRenderings: LayerOverviewUtils.asDict(trs),
new DoesImageExist(licensePaths, existsSync) tagRenderingOrder: trs.map(tr => tr.id),
), publicLayers
publicLayers,
} }
const knownTagRenderings = new Set<string>() const knownTagRenderings = new Set<string>()
convertState.tagRenderings.forEach((_, key) => knownTagRenderings.add(key)) convertState.tagRenderings.forEach((_, key) => knownTagRenderings.add(key))
@ -758,7 +775,7 @@ class LayerOverviewUtils extends Script {
) )
try { try {
themeFile = new PrepareTheme(convertState, { themeFile = new PrepareTheme(convertState, {
skipDefaultLayers: true, skipDefaultLayers: true
}).convertStrict( }).convertStrict(
themeFile, themeFile,
ConversionContext.construct([themePath], ["PrepareLayer"]) ConversionContext.construct([themePath], ["PrepareLayer"])
@ -776,8 +793,8 @@ class LayerOverviewUtils extends Script {
if (themeFile.icon.endsWith(".svg")) { if (themeFile.icon.endsWith(".svg")) {
try { try {
ScriptUtils.ReadSvgSync(themeFile.icon, (svg) => { ScriptUtils.ReadSvgSync(themeFile.icon, (svg) => {
const width: string = svg.$.width const width: string = svg["$"].width
const height: string = svg.$.height const height: string = svg["$"].height
const err = themeFile.hideFromOverview ? console.warn : console.error const err = themeFile.hideFromOverview ? console.warn : console.error
if (width !== height) { if (width !== height) {
const e = const e =
@ -792,7 +809,7 @@ class LayerOverviewUtils extends Script {
const e: string = [ const e: string = [
`the icon for theme ${themeFile.id} is too small. Please rescale the icon at ${themeFile.icon}`, `the icon for theme ${themeFile.id} is too small. Please rescale the icon at ${themeFile.icon}`,
`Even though an SVG is 'infinitely scaleable', the icon should be dimensioned bigger. One of the build steps of the theme does convert the image to a PNG (to serve as PWA-icon) and having a small dimension will cause blurry images.`, `Even though an SVG is 'infinitely scaleable', the icon should be dimensioned bigger. One of the build steps of the theme does convert the image to a PNG (to serve as PWA-icon) and having a small dimension will cause blurry images.`,
` Width = ${width} height = ${height}; we recommend a size of at least 500px * 500px and to use a square aspect ratio.`, ` Width = ${width} height = ${height}; we recommend a size of at least 500px * 500px and to use a square aspect ratio.`
].join("\n") ].join("\n")
err(e) err(e)
} }
@ -823,7 +840,7 @@ class LayerOverviewUtils extends Script {
new Translation(t.description) new Translation(t.description)
.FirstSentence() .FirstSentence()
.OnEveryLanguage((s) => parse_html(s).textContent).translations, .OnEveryLanguage((s) => parse_html(s).textContent).translations,
mustHaveLanguage: t.mustHaveLanguage?.length > 0, mustHaveLanguage: t.mustHaveLanguage?.length > 0
} }
}) })
) )

View file

@ -243,11 +243,17 @@ class GenerateLayouts extends Script {
asLangSpan(t: Translation, tag = "span"): string { asLangSpan(t: Translation, tag = "span"): string {
const values: string[] = [] const values: string[] = []
let defaultSet = false
for (const lang in t.translations) { for (const lang in t.translations) {
if (lang === "_context") { if (lang === "_context") {
continue continue
} }
values.push(`<${tag} lang="${lang}">${t.translations[lang]}</${tag}>`) let display = ' style="display: none"'
if(!defaultSet){
display = ""
defaultSet = true
}
values.push(`<${tag} lang="${lang}"${display}>${t.translations[lang]}</${tag}>`)
} }
return values.join("\n") return values.join("\n")
} }

View file

@ -5,6 +5,10 @@ import { ConversionContext } from "./ConversionContext"
export interface DesugaringContext { export interface DesugaringContext {
tagRenderings: Map<string, QuestionableTagRenderingConfigJson> tagRenderings: Map<string, QuestionableTagRenderingConfigJson>
/**
* Order of appearance in questions.json
*/
tagRenderingOrder: string[]
sharedLayers: Map<string, LayerConfigJson> sharedLayers: Map<string, LayerConfigJson>
publicLayers?: Set<string> publicLayers?: Set<string>
} }

View file

@ -7,12 +7,12 @@ import {
FirstOf, FirstOf,
Fuse, Fuse,
On, On,
SetDefault, SetDefault
} from "./Conversion" } from "./Conversion"
import { LayerConfigJson } from "../Json/LayerConfigJson" import { LayerConfigJson } from "../Json/LayerConfigJson"
import { import {
MinimalTagRenderingConfigJson, MinimalTagRenderingConfigJson,
TagRenderingConfigJson, TagRenderingConfigJson
} from "../Json/TagRenderingConfigJson" } from "../Json/TagRenderingConfigJson"
import { Utils } from "../../../Utils" import { Utils } from "../../../Utils"
import RewritableConfigJson from "../Json/RewritableConfigJson" import RewritableConfigJson from "../Json/RewritableConfigJson"
@ -85,17 +85,17 @@ class ExpandFilter extends DesugaringStep<LayerConfigJson> {
} }
const options = matchingTr.mappings.map((mapping) => ({ const options = matchingTr.mappings.map((mapping) => ({
question: mapping.then, question: mapping.then,
osmTags: mapping.if, osmTags: mapping.if
})) }))
options.unshift({ options.unshift({
question: { question: {
en: "All types", en: "All types"
}, },
osmTags: undefined, osmTags: undefined
}) })
newFilters.push({ newFilters.push({
id: filter, id: filter,
options, options
}) })
continue continue
} }
@ -151,7 +151,7 @@ class ExpandTagRendering extends Conversion<
| { | {
builtin: string | string[] builtin: string | string[]
override: any override: any
}, },
TagRenderingConfigJson[] TagRenderingConfigJson[]
> { > {
private readonly _state: DesugaringContext private readonly _state: DesugaringContext
@ -357,8 +357,8 @@ class ExpandTagRendering extends Conversion<
return [ return [
<any>{ <any>{
render: tr, render: tr,
id: tr.replace(/[^a-zA-Z0-9]/g, ""), id: tr.replace(/[^a-zA-Z0-9]/g, "")
}, }
] ]
} }
return lookup return lookup
@ -605,8 +605,8 @@ export class AddQuestionBox extends DesugaringStep<LayerConfigJson> {
const question: QuestionableTagRenderingConfigJson = { const question: QuestionableTagRenderingConfigJson = {
id: "leftover-questions", id: "leftover-questions",
render: { render: {
"*": `{questions( ,${Array.from(seen).join(";")})}`, "*": `{questions( ,${Array.from(seen).join(";")})}`
}, }
} }
json.tagRenderings.push(question) json.tagRenderings.push(question)
} }
@ -625,9 +625,13 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
"favourite_state", "favourite_state",
"all_tags", "all_tags",
"qr_code", "qr_code",
"nearby_images",
"linked_open_data"
] ]
private readonly _desugaring: DesugaringContext
private readonly _desugaring: DesugaringContext
private readonly _addedByDefaultAtTop : QuestionableTagRenderingConfigJson[]
private readonly _addedByDefault: QuestionableTagRenderingConfigJson[]
constructor(desugaring: DesugaringContext) { constructor(desugaring: DesugaringContext) {
super( super(
"Add some editing elements, such as the delete button or the move button if they are configured. These used to be handled by the feature info box, but this has been replaced by special visualisation elements", "Add some editing elements, such as the delete button or the move button if they are configured. These used to be handled by the feature info box, but this has been replaced by special visualisation elements",
@ -635,6 +639,21 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
"AddEditingElements" "AddEditingElements"
) )
this._desugaring = desugaring this._desugaring = desugaring
const builtinQuestions = Array.from(this._desugaring.tagRenderings?.values() ?? [])
function getAddedByDefaultIds(key: string): QuestionableTagRenderingConfigJson[] {
const addByDefault = builtinQuestions.filter(tr => tr.labels?.indexOf(key) >= 0)
const ids = new Set(addByDefault.map(tr => tr.id))
const idsInOrder = desugaring.tagRenderingOrder.filter(id => ids.has(id))
return Utils.NoNull(idsInOrder.map(id => desugaring.tagRenderings.get(id)))
}
this._addedByDefaultAtTop = getAddedByDefaultIds("added_by_default_top")
this._addedByDefault = getAddedByDefaultIds("added_by_default")
} }
convert(json: LayerConfigJson, _: ConversionContext): LayerConfigJson { convert(json: LayerConfigJson, _: ConversionContext): LayerConfigJson {
@ -662,78 +681,40 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
/***** ADD TO TOP ****/ /***** ADD TO TOP ****/
if ( json.tagRenderings.unshift(...this._addedByDefaultAtTop.filter(tr => !allIds.has(tr.id)))
this._desugaring.tagRenderings.has("just_created") &&
!json.tagRenderings.some((tr) => tr === "just_created" || tr["id"] === "just_created")
) {
json.tagRenderings.unshift(this._desugaring.tagRenderings.get("just_created"))
}
if (!allIds.has("nothing_known")) {
const indexFirstQuestion = json.tagRenderings.findIndex(tr => tr["question"] !== undefined)
json.tagRenderings.splice(indexFirstQuestion,
0,
this._desugaring.tagRenderings.get("nothing_known"))
console.log("aDDING",this._desugaring.tagRenderings.get("nothing_known"))
}
/***** ADD TO BOTTOM ****/ /***** ADD TO BOTTOM ****/
if (!allIds.has("lod")) {
json.tagRenderings.push(this._desugaring.tagRenderings.get("lod"))
}
if (!usedSpecialFunctions.has("minimap")) { if (!usedSpecialFunctions.has("minimap")) {
json.tagRenderings.push(this._desugaring.tagRenderings.get("minimap")) json.tagRenderings.push(this._desugaring.tagRenderings.get("minimap"))
} }
if(usedSpecialFunctions.has("image_upload") &&
!usedSpecialFunctions.has("nearby_images")){
json.tagRenderings.push(this._desugaring.tagRenderings.get("nearby_images"))
}
if (json.allowSplit && !usedSpecialFunctions.has("split_button")) { if (json.allowSplit && !usedSpecialFunctions.has("split_button")) {
json.tagRenderings.push({ json.tagRenderings.push(this._desugaring.tagRenderings.get("split_button"))
id: "split-button",
render: { "*": "{split_button()}" },
})
delete json.allowSplit delete json.allowSplit
} }
if (json.allowMove && !usedSpecialFunctions.has("move_button")) { if (json.allowMove && !usedSpecialFunctions.has("move_button")) {
json.tagRenderings.push({ json.tagRenderings.push({
id: "move-button", id: "move-button",
render: { "*": "{move_button()}" }, render: { "*": "{move_button()}" }
}) })
} }
if (json.deletion && !usedSpecialFunctions.has("delete_button")) { if (json.deletion && !usedSpecialFunctions.has("delete_button")) {
json.tagRenderings.push({ json.tagRenderings.push({
id: "delete-button", id: "delete-button",
render: { "*": "{delete_button()}" }, render: { "*": "{delete_button()}" }
}) })
} }
if (!usedSpecialFunctions.has("favourite_status")) {
json.tagRenderings.push({
id: "favourite_status",
render: { "*": "{favourite_status()}" },
})
}
if (!allIds.has("share")) {
json.tagRenderings.push(this._desugaring.tagRenderings.get("share"))
}
if (!allIds.has("qr_code")) {
json.tagRenderings.push(this._desugaring.tagRenderings.get("qr_code"))
}
if (
json.source !== "special" &&
json.source !== "special:library" &&
json.tagRenderings &&
this._desugaring.tagRenderings.has("last_edit") &&
!json.tagRenderings.some((tr) => tr["id"] === "last_edit")
) {
json.tagRenderings.push(this._desugaring.tagRenderings.get("last_edit"))
}
json.tagRenderings.push(...this._addedByDefault.filter(tr => !allIds.has(tr.id)))
if (!usedSpecialFunctions.has("all_tags")) { if (!usedSpecialFunctions.has("all_tags")) {
const trc: QuestionableTagRenderingConfigJson = { const trc: QuestionableTagRenderingConfigJson = {
@ -744,9 +725,9 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
or: [ or: [
"__featureSwitchIsDebugging=true", "__featureSwitchIsDebugging=true",
"mapcomplete-show_tags=full", "mapcomplete-show_tags=full",
"mapcomplete-show_debug=yes", "mapcomplete-show_debug=yes"
], ]
}, }
} }
json.tagRenderings?.push(trc) json.tagRenderings?.push(trc)
} }
@ -937,7 +918,7 @@ export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> {
const before = Translations.T(input.before) const before = Translations.T(input.before)
const after = Translations.T(input.after) const after = Translations.T(input.after)
const clss: string = input.class !== undefined ? ":"+input.class : "" const clss: string = input.class !== undefined ? ":" + input.class : ""
for (const ln of Object.keys(before?.translations ?? {})) { for (const ln of Object.keys(before?.translations ?? {})) {
@ -952,7 +933,7 @@ export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> {
.map((nm) => RewriteSpecial.escapeStr(special[nm] ?? "")) .map((nm) => RewriteSpecial.escapeStr(special[nm] ?? ""))
.join(",") .join(",")
return { return {
"*": `{${type}(${args})${clss}}`, "*": `{${type}(${args})${clss}}`
} }
} }
@ -1064,7 +1045,7 @@ class ExpandIconBadges extends DesugaringStep<PointRenderingConfigJson> {
iconBadges.push( iconBadges.push(
...expanded.map((resolved) => ({ ...expanded.map((resolved) => ({
if: iconBadge.if, if: iconBadge.if,
then: <MinimalTagRenderingConfigJson>resolved, then: <MinimalTagRenderingConfigJson>resolved
})) }))
) )
} }
@ -1237,7 +1218,7 @@ export class AutoTitleIcon extends DesugaringStep<LayerConfigJson> {
} }
return <TagRenderingConfigJson>{ return <TagRenderingConfigJson>{
id: "title_icon_auto_" + tr.id, id: "title_icon_auto_" + tr.id,
mappings, mappings
} }
} }
@ -1307,7 +1288,7 @@ export class PrepareLayer extends Fuse<LayerConfigJson> {
(layer) => (layer) =>
new Concat( new Concat(
new ExpandTagRendering(state, layer, { new ExpandTagRendering(state, layer, {
addToContext: options?.addTagRenderingsToContext ?? false, addToContext: options?.addTagRenderingsToContext ?? false
}) })
) )
), ),

View file

@ -76,7 +76,7 @@
</div> </div>
{:else} {:else}
<div <div
class="selected-element-view flex h-full w-full flex-col gap-y-2 overflow-y-auto p-1 px-4" class="selected-element-view flex h-full w-full flex-col gap-y-1 overflow-y-auto p-1 px-4"
tabindex="-1" tabindex="-1"
> >
{#each $knownTagRenderings as config (config.id)} {#each $knownTagRenderings as config (config.id)}

View file

@ -114,7 +114,7 @@
<Tr t={t.allIncluded.Subs({ source: sourceUrl })} /> <Tr t={t.allIncluded.Subs({ source: sourceUrl })} />
</div> </div>
{:else} {:else}
<div class="low-interaction border-interactive p-1"> <div class="low-interaction p-1">
{#if !readonly} {#if !readonly}
<Tr t={t.loadedFrom.Subs({ url: sourceUrl, source: sourceUrl })} /> <Tr t={t.loadedFrom.Subs({ url: sourceUrl, source: sourceUrl })} />
{/if} {/if}

View file

@ -12,6 +12,7 @@
import type { OsmTags } from "../../Models/OsmFeature" import type { OsmTags } from "../../Models/OsmFeature"
import Translations from "../i18n/Translations" import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte" import Tr from "../Base/Tr.svelte"
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
export let externalData: Store< export let externalData: Store<
| { success: { content: Record<string, string> } } | { success: { content: Record<string, string> } }
@ -25,6 +26,8 @@
export let feature: Feature export let feature: Feature
export let readonly = false export let readonly = false
export let sourceUrl: Store<string> export let sourceUrl: Store<string>
export let collapsed : boolean
</script> </script>
{#if !$sourceUrl} {#if !$sourceUrl}
@ -32,11 +35,12 @@
{:else if $externalData === undefined} {:else if $externalData === undefined}
<Loading /> <Loading />
{:else if $externalData["error"] !== undefined} {:else if $externalData["error"] !== undefined}
<div class="alert flex"> <div class="subtle italic low-interaction p-2 px-4 rounded">
<Tr t={Translations.t.general.error} /> <Tr t={Translations.t.external.error} />
{$externalData["error"]}
</div> </div>
{:else if $externalData["success"] !== undefined} {:else if $externalData["success"] !== undefined}
<AccordionSingle>
<span slot="header">Structured data from the website</span>
<ComparisonTable <ComparisonTable
externalProperties={$externalData["success"]} externalProperties={$externalData["success"]}
{state} {state}
@ -46,4 +50,5 @@
{readonly} {readonly}
sourceUrl={$sourceUrl} sourceUrl={$sourceUrl}
/> />
</AccordionSingle>
{/if} {/if}

View file

@ -0,0 +1,17 @@
<script lang="ts">
import { Accordion, AccordionItem } from "flowbite-svelte"
export let expanded = false
</script>
<Accordion>
<AccordionItem open={expanded} paddingDefault="p-0" inactiveClass="text-black">
<span slot="header" class="text-base p-2 ">
<slot name="header" />
</span>
<div class="low-interaction p-2 rounded-b">
<slot />
</div>
</AccordionItem>
</Accordion>

View file

@ -30,7 +30,7 @@
lon, lon,
lat, lat,
allowSpherical: new UIEventSource<boolean>(false), allowSpherical: new UIEventSource<boolean>(false),
blacklist: AllImageProviders.LoadImagesFor(tags), blacklist: AllImageProviders.LoadImagesFor(tags)
}, },
state.indexedFeatures state.indexedFeatures
) )
@ -39,18 +39,18 @@
let allDone = imagesProvider.allDone let allDone = imagesProvider.allDone
</script> </script>
<div class="interactive border-interactive rounded-2xl p-2">
<div class="flex justify-between"> <div class="flex justify-between">
<h4> <h4>
<Tr t={Translations.t.image.nearby.title} /> <Tr t={Translations.t.image.nearby.title} />
</h4> </h4>
<slot name="corner" /> <slot name="corner" />
</div> </div>
{#if !$allDone} {#if !$allDone}
<Loading /> <Loading />
{:else if $images.length === 0} {:else if $images.length === 0}
<Tr t={Translations.t.image.nearby.noNearbyImages} cls="alert" /> <Tr t={Translations.t.image.nearby.noNearbyImages} cls="alert" />
{:else} {:else}
<div class="flex w-full space-x-1 overflow-x-auto" style="scroll-snap-type: x proximity"> <div class="flex w-full space-x-1 overflow-x-auto" style="scroll-snap-type: x proximity">
{#each $images as image (image.pictureUrl)} {#each $images as image (image.pictureUrl)}
<span class="w-fit shrink-0" style="scroll-snap-align: start"> <span class="w-fit shrink-0" style="scroll-snap-align: start">
@ -58,5 +58,4 @@
</span> </span>
{/each} {/each}
</div> </div>
{/if} {/if}
</div>

View file

@ -11,6 +11,8 @@
import Camera_plus from "../../assets/svg/Camera_plus.svelte" import Camera_plus from "../../assets/svg/Camera_plus.svelte"
import LoginToggle from "../Base/LoginToggle.svelte" import LoginToggle from "../Base/LoginToggle.svelte"
import { ariaLabel } from "../../Utils/ariaLabel" import { ariaLabel } from "../../Utils/ariaLabel"
import { Accordion, AccordionItem } from "flowbite-svelte"
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
export let tags: UIEventSource<OsmTags> export let tags: UIEventSource<OsmTags>
export let state: SpecialVisualizationState export let state: SpecialVisualizationState
@ -25,31 +27,10 @@
let expanded = false let expanded = false
</script> </script>
<div class="my-4"> <AccordionSingle>
{#if expanded} <span slot="header" class="text-base p-2">
<NearbyImages {tags} {state} {lon} {lat} {feature} {linkable} {layer}>
<button
slot="corner"
class="no-image-background h-6 w-6 cursor-pointer border-none p-0"
use:ariaLabel={t.close}
on:click={() => {
expanded = false
}}
>
<XCircleIcon />
</button>
</NearbyImages>
{:else}
<button
class="flex w-full items-center"
style="margin-left: 0; margin-right: 0"
on:click={() => {
expanded = true
}}
aria-expanded={expanded}
>
<Camera_plus class="mr-2 block h-8 w-8 p-1" />
<Tr t={t.seeNearby} /> <Tr t={t.seeNearby} />
</button> </span>
{/if} <NearbyImages {tags} {state} {lon} {lat} {feature} {linkable} {layer} />
</div> </AccordionSingle>

View file

@ -11,9 +11,9 @@
import Tr from "../Base/Tr.svelte" import Tr from "../Base/Tr.svelte"
import UploadingImageCounter from "./UploadingImageCounter.svelte" import UploadingImageCounter from "./UploadingImageCounter.svelte"
import FileSelector from "../Base/FileSelector.svelte" import FileSelector from "../Base/FileSelector.svelte"
import Camera_plus from "../../assets/svg/Camera_plus.svelte"
import LoginButton from "../Base/LoginButton.svelte" import LoginButton from "../Base/LoginButton.svelte"
import { Translation } from "../i18n/Translation" import { Translation } from "../i18n/Translation"
import Camera from "@babeard/svelte-heroicons/solid/Camera"
export let state: SpecialVisualizationState export let state: SpecialVisualizationState
@ -73,7 +73,7 @@
{#if image !== undefined} {#if image !== undefined}
<img src={image} aria-hidden="true" /> <img src={image} aria-hidden="true" />
{:else} {:else}
<Camera_plus class="block h-12 w-12 p-1 text-4xl" aria-hidden="true" /> <Camera class="h-12 w-12 p-1" aria-hidden="true" />
{/if} {/if}
{#if labelText} {#if labelText}
{labelText} {labelText}

View file

@ -18,6 +18,9 @@
import Loading from "../../Base/Loading.svelte" import Loading from "../../Base/Loading.svelte"
import { DeleteFlowState } from "./DeleteFlowState" import { DeleteFlowState } from "./DeleteFlowState"
import { twJoin } from "tailwind-merge" import { twJoin } from "tailwind-merge"
import AccordionSingle from "../../Flowbite/AccordionSingle.svelte"
import Trash from "@babeard/svelte-heroicons/mini/Trash"
import Invalid from "../../../assets/svg/Invalid.svelte"
export let state: SpecialVisualizationState export let state: SpecialVisualizationState
export let deleteConfig: DeleteConfig export let deleteConfig: DeleteConfig
@ -35,7 +38,7 @@
const canBeDeletedReason = deleteAbility.canBeDeletedReason const canBeDeletedReason = deleteAbility.canBeDeletedReason
const hasSoftDeletion = deleteConfig.softDeletionTags !== undefined const hasSoftDeletion = deleteConfig.softDeletionTags !== undefined
let currentState: "start" | "confirm" | "applying" | "deleted" = "start" let currentState: "confirm" | "applying" | "deleted" = "confirm"
$: { $: {
deleteAbility.CheckDeleteability(true) deleteAbility.CheckDeleteability(true)
} }
@ -63,7 +66,7 @@
deleteConfig.softDeletionTags, deleteConfig.softDeletionTags,
{ {
theme: state?.layout?.id ?? "unknown", theme: state?.layout?.id ?? "unknown",
specialMotivation: deleteReason, specialMotivation: deleteReason
}, },
canBeDeleted.data canBeDeleted.data
) )
@ -71,7 +74,7 @@
// no _delete_reason is given, which implies that this is _not_ a deletion but merely a retagging via a nonDeleteMapping // no _delete_reason is given, which implies that this is _not_ a deletion but merely a retagging via a nonDeleteMapping
actionToTake = new ChangeTagAction(featureId, selectedTags, tags.data, { actionToTake = new ChangeTagAction(featureId, selectedTags, tags.data, {
theme: state?.layout?.id ?? "unkown", theme: state?.layout?.id ?? "unkown",
changeType: "special-delete", changeType: "special-delete"
}) })
} }
@ -84,23 +87,32 @@
<LoginToggle ignoreLoading={true} {state}> <LoginToggle ignoreLoading={true} {state}>
{#if $canBeDeleted === false && !hasSoftDeletion} {#if $canBeDeleted === false && !hasSoftDeletion}
<div class="low-interaction flex flex-col"> <div class="low-interaction rounded text-sm flex p-2 italic subtle gap-x-1">
<Tr t={$canBeDeletedReason} /> <div class="relative h-fit">
<Tr cls="subtle" t={t.useSomethingElse} /> <Trash class="w-8 h-8 pb-1" />
<Invalid class="absolute bottom-0 right-0 w-5 h-5"/>
</div> </div>
{:else if currentState === "start"} <div class="flex flex-col">
<button
class="w-full" <Tr t={t.cannotBeDeleted} />
on:click={() => { <Tr t={$canBeDeletedReason} />
currentState = "confirm" <Tr t={t.useSomethingElse} />
}} </div>
> </div>
{:else}
<AccordionSingle>
<span slot="header" class="flex">
<TrashIcon class="h-6 w-6" /> <TrashIcon class="h-6 w-6" />
<Tr t={t.delete} /> <Tr t={t.delete} />
</button> </span>
{:else if currentState === "confirm"} <span>
{#if currentState === "confirm"}
<TagRenderingQuestion <TagRenderingQuestion
bind:selectedTags bind:selectedTags
clss=""
{tags} {tags}
config={deleteConfig.constructTagRendering()} config={deleteConfig.constructTagRendering()}
{state} {state}
@ -123,11 +135,9 @@
/> />
<Tr t={t.delete} /> <Tr t={t.delete} />
</button> </button>
<button slot="cancel" class="items-center" on:click={() => (currentState = "start")}>
<Tr t={t.cancel} />
</button>
<div slot="under-buttons">
<div slot="under-buttons" class="italic subtle">
{#if selectedTags !== undefined} {#if selectedTags !== undefined}
{#if canBeDeleted && isHardDelete} {#if canBeDeleted && isHardDelete}
<!-- This is a hard delete - explain that this is a hard delete...--> <!-- This is a hard delete - explain that this is a hard delete...-->
@ -149,4 +159,9 @@
<Tr t={t.isDeleted} /> <Tr t={t.isDeleted} />
</div> </div>
{/if} {/if}
</span>
</AccordionSingle>
{/if}
</LoginToggle> </LoginToggle>

View file

@ -26,7 +26,7 @@
<LoginToggle ignoreLoading={true} {state}> <LoginToggle ignoreLoading={true} {state}>
{#if $isFavourite} {#if $isFavourite}
<div class="flex h-fit items-start"> <div class="flex h-fit items-start">
<button on:click={() => markFavourite(false)}> <button class="w-full" on:click={() => markFavourite(false)}>
<HeartSolidIcon class="mr-2 w-16 shrink-0" on:click={() => markFavourite(false)} /> <HeartSolidIcon class="mr-2 w-16 shrink-0" on:click={() => markFavourite(false)} />
<div class="flex flex-col items-start"> <div class="flex flex-col items-start">
<Tr t={t.button.unmark} /> <Tr t={t.button.unmark} />
@ -36,7 +36,7 @@
</div> </div>
<Tr cls="font-bold thanks m-2 p-2 block" t={t.button.isFavourite} /> <Tr cls="font-bold thanks m-2 p-2 block" t={t.button.isFavourite} />
{:else} {:else}
<button on:click={() => markFavourite(true)}> <button class="w-full" on:click={() => markFavourite(true)}>
<HeartOutlineIcon class="mr-2 w-16 shrink-0" on:click={() => markFavourite(true)} /> <HeartOutlineIcon class="mr-2 w-16 shrink-0" on:click={() => markFavourite(true)} />
<div class="flex w-full flex-col items-start"> <div class="flex w-full flex-col items-start">

View file

@ -19,16 +19,21 @@
import If from "../Base/If.svelte" import If from "../Base/If.svelte"
import Constants from "../../Models/Constants" import Constants from "../../Models/Constants"
import LoginToggle from "../Base/LoginToggle.svelte" import LoginToggle from "../Base/LoginToggle.svelte"
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
import BackButton from "../Base/BackButton.svelte"
import ChevronLeft from "@babeard/svelte-heroicons/solid/ChevronLeft"
import ThemeViewState from "../../Models/ThemeViewState"
export let state: SpecialVisualizationState export let state: ThemeViewState
export let layer: LayerConfig export let layer: LayerConfig
export let featureToMove: Feature<Point> export let featureToMove: Feature<Point>
let id: string = featureToMove.properties.id let id: string = featureToMove.properties.id
let currentStep: "start" | "reason" | "pick_location" | "moved" = "start" let currentStep: "reason" | "pick_location" | "moved" = "reason"
const t = Translations.t.move const t = Translations.t.move
const reason = new UIEventSource<MoveReason>(undefined) let reason = new UIEventSource<MoveReason>(undefined)
let [lon, lat] = GeoOperations.centerpointCoordinates(featureToMove) let [lon, lat] = GeoOperations.centerpointCoordinates(featureToMove)
let newLocation = new UIEventSource<{ lon: number; lat: number }>(undefined) let newLocation = new UIEventSource<{ lon: number; lat: number }>(undefined)
@ -42,11 +47,14 @@
location: new UIEventSource({ lon, lat }), location: new UIEventSource({ lon, lat }),
minzoom: new UIEventSource($reason.minZoom), minzoom: new UIEventSource($reason.minZoom),
rasterLayer: state.mapProperties.rasterLayer, rasterLayer: state.mapProperties.rasterLayer,
zoom: new UIEventSource($reason?.startZoom ?? 16), zoom: new UIEventSource($reason?.startZoom ?? 16)
} }
} }
let moveWizardState = new MoveWizardState(id, layer.allowMove, state) let moveWizardState = new MoveWizardState(id, layer.allowMove, state)
if(moveWizardState.reasons.length === 1){
reason.setData(moveWizardState.reasons[0])
}
let notAllowed = moveWizardState.moveDisallowedReason let notAllowed = moveWizardState.moveDisallowedReason
let currentMapProperties: MapProperties = undefined let currentMapProperties: MapProperties = undefined
</script> </script>
@ -61,33 +69,21 @@
<Tr t={$notAllowed} /> <Tr t={$notAllowed} />
</div> </div>
</div> </div>
{:else if currentStep === "start"} {:else}
<AccordionSingle>
<span slot="header" class="flex">
{#if moveWizardState.reasons.length === 1} {#if moveWizardState.reasons.length === 1}
<button
class="w-full"
on:click={() => {
reason.setData(moveWizardState.reasons[0])
currentStep = "pick_location"
}}
>
<ToSvelte <ToSvelte
construct={moveWizardState.reasons[0].icon.SetStyle("height: 1.5rem; width: 1.5rem;")} construct={moveWizardState.reasons[0].icon.SetStyle("height: 1.5rem; width: 1.5rem;")}
/> />
<Tr t={Translations.T(moveWizardState.reasons[0].invitingText)} /> <Tr t={Translations.T(moveWizardState.reasons[0].invitingText)} />
</button>
{:else} {:else}
<button
class="w-full"
on:click={() => {
currentStep = "reason"
}}
>
<Move class="h-6 w-6" /> <Move class="h-6 w-6" />
<Tr t={t.inviteToMove.generic} /> <Tr t={t.inviteToMove.generic} />
</button>
{/if} {/if}
{:else if currentStep === "reason"} </span>
<div class="interactive border-interactive flex flex-col p-2"> <span class="flex flex-col p-2">
{#if currentStep === "reason" && moveWizardState.reasons.length > 1}
<Tr cls="text-lg font-bold" t={t.whyMove} /> <Tr cls="text-lg font-bold" t={t.whyMove} />
{#each moveWizardState.reasons as reasonSpec} {#each moveWizardState.reasons as reasonSpec}
<button <button
@ -100,11 +96,7 @@
<Tr t={Translations.T(reasonSpec.text)} /> <Tr t={Translations.T(reasonSpec.text)} />
</button> </button>
{/each} {/each}
</div> {:else if currentStep === "pick_location" || currentStep === "reason"}
{:else if currentStep === "pick_location"}
<div class="border-interactive interactive flex flex-col p-2">
<Tr cls="text-lg font-bold" t={t.moveTitle} />
<div class="relative h-64 w-full"> <div class="relative h-64 w-full">
<LocationInput <LocationInput
mapProperties={(currentMapProperties = initMapProperties())} mapProperties={(currentMapProperties = initMapProperties())}
@ -136,21 +128,16 @@
<Tr t={t.confirmMove} /> <Tr t={t.confirmMove} />
</button> </button>
<div slot="else" class="alert"> <div slot="else" class="alert w-full">
<Tr t={t.zoomInFurther} /> <Tr t={t.zoomInFurther} />
</div> </div>
</If> </If>
{#if moveWizardState.reasons.length > 1}
<button <button class="w-full" on:click={() => {currentStep = "reason"}}>
class="w-full" <ChevronLeft class="w-6 h-6" />
on:click={() => {
currentStep = "start"
}}
>
<XCircleIcon class="mr-2 h-6 w-6" />
<Tr t={t.cancel} /> <Tr t={t.cancel} />
</button> </button>
</div> {/if}
</div> </div>
{:else if currentStep === "moved"} {:else if currentStep === "moved"}
<div class="flex flex-col"> <div class="flex flex-col">
@ -165,5 +152,8 @@
</button> </button>
</div> </div>
{/if} {/if}
</span>
</AccordionSingle>
{/if}
{/if} {/if}
</LoginToggle> </LoginToggle>

View file

@ -44,6 +44,8 @@
export let allowDeleteOfFreeform: boolean = false export let allowDeleteOfFreeform: boolean = false
export let clss = "interactive border-interactive"
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined) let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined)
let unit: Unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key)) let unit: Unit = layer?.units?.find((unit) => unit.appliesToKeys.has(config.freeform?.key))
@ -308,9 +310,9 @@
</script> </script>
{#if question !== undefined} {#if question !== undefined}
<div class="relative"> <div class={clss} >
<form <form
class="interactive border-interactive relative flex flex-col overflow-y-auto px-2" class="relative flex flex-col overflow-y-auto px-2"
style="max-height: 75vh" style="max-height: 75vh"
on:submit|preventDefault={() => { on:submit|preventDefault={() => {
/*onSave(); This submit is not needed and triggers to early, causing bugs: see #1808*/ /*onSave(); This submit is not needed and triggers to early, causing bugs: see #1808*/
@ -318,7 +320,7 @@
> >
<fieldset> <fieldset>
<legend> <legend>
<div class="interactive sticky top-0 justify-between pt-1 font-bold" style="z-index: 11"> <div class="sticky top-0 justify-between pt-1 font-bold" style="z-index: 11">
<SpecialTranslation t={question} {tags} {state} {layer} feature={selectedElement} /> <SpecialTranslation t={question} {tags} {state} {layer} feature={selectedElement} />
</div> </div>
@ -477,7 +479,7 @@
</div> </div>
{/if} {/if}
<div <div
class="interactive sticky bottom-0 flex flex-wrap-reverse items-stretch justify-end sm:flex-nowrap" class="sticky bottom-0 flex flex-wrap-reverse items-stretch justify-end sm:flex-nowrap"
style="z-index: 11" style="z-index: 11"
> >
<!-- TagRenderingQuestion-buttons --> <!-- TagRenderingQuestion-buttons -->

View file

@ -22,6 +22,7 @@ function filterLangs(maindiv) {
continue continue
} }
if (childLang.value === lang) { if (childLang.value === lang) {
child.style.display = ""
continue continue
} }
child.parentElement.removeChild(child) child.parentElement.removeChild(child)

View file

@ -1776,6 +1776,11 @@ export default class SpecialVisualizations {
{ {
name: "mode", name: "mode",
doc: "If `display`, only show the data in tabular and readonly form, ignoring already existing tags. This is used to explicitly show all the tags. If unset or anything else, allow to apply/import on OSM" doc: "If `display`, only show the data in tabular and readonly form, ignoring already existing tags. This is used to explicitly show all the tags. If unset or anything else, allow to apply/import on OSM"
},
{
name: "collapsed",
defaultValue: "yes",
doc: "If the containing accordion should be closed"
} }
], ],
needsUrls: [Constants.linkedDataProxy, "http://www.schema.org"], needsUrls: [Constants.linkedDataProxy, "http://www.schema.org"],
@ -1789,6 +1794,7 @@ export default class SpecialVisualizations {
const key = argument[0] ?? "website" const key = argument[0] ?? "website"
const useProxy = argument[1] !== "no" const useProxy = argument[1] !== "no"
const readonly = argument[3] === "readonly" const readonly = argument[3] === "readonly"
const isClosed = (arguments[4] ?? "yes") === "yes"
const url = tags const url = tags
.mapD((tags) => { .mapD((tags) => {

View file

@ -17,6 +17,9 @@
* For a custom styling, set 'customCss' in your layoutConfig and overwrite some of these. * For a custom styling, set 'customCss' in your layoutConfig and overwrite some of these.
*/ */
/* No support for dark mode yet, we disable it to prevent some elements to suddenly toggle */
color-scheme: only light;
/* Main color of the application: the background and text colours */ /* Main color of the application: the background and text colours */
--background-color: white; --background-color: white;
/* Main text colour. Also styles some elements, such as the 'close popup'-button or 'back-arrow' (in mobile) */ /* Main text colour. Also styles some elements, such as the 'close popup'-button or 'back-arrow' (in mobile) */
@ -112,7 +115,7 @@ h1 {
h2 { h2 {
font-size: x-large; font-size: x-large;
margin-top: 0.5em; margin-top: 0.5em;
margin-bottom: 0.3em; margin-bottom: 0; /*Disable margin bottom to play nicely with accordeons from flowbite*/
font-weight: bold; font-weight: bold;
} }
@ -201,6 +204,10 @@ button, .button {
} }
.group > button {
padding-right: 1rem !important; /*Flowbite workaround */
}
button.w-full { button.w-full {
margin-left: 0; margin-left: 0;
} }

View file

@ -52,10 +52,13 @@ async function main() {
]) ])
console.log("The available layers on server are", Array.from(availableLayers)) console.log("The available layers on server are", Array.from(availableLayers))
const state = new ThemeViewState(layout, availableLayers) const state = new ThemeViewState(layout, availableLayers)
const target = document.getElementById("maindiv")
const childs = Array.from(target.children)
new ThemeViewGUI({ new ThemeViewGUI({
target: document.getElementById("maindiv"), target,
props: { state }, props: { state },
}) })
childs.forEach(ch => target.removeChild(ch))
Array.from(document.getElementsByClassName("delete-on-load")).forEach((el) => { Array.from(document.getElementsByClassName("delete-on-load")).forEach((el) => {
el.parentElement.removeChild(el) el.parentElement.removeChild(el)
}) })

View file

@ -46,10 +46,13 @@ async function main() {
MetaTagging.setThemeMetatagging(new ThemeMetaTagging()) MetaTagging.setThemeMetatagging(new ThemeMetaTagging())
// LAYOUT.ADD_LAYERS // LAYOUT.ADD_LAYERS
const state = new ThemeViewState(new LayoutConfig(<any> layout), availableLayers) const state = new ThemeViewState(new LayoutConfig(<any> layout), availableLayers)
const target = document.getElementById("maindiv")
const childs = Array.from(target.children)
new ThemeViewGUI({ new ThemeViewGUI({
target: document.getElementById("maindiv"), target,
props: {state} props: { state },
}) })
childs.forEach(ch => target.removeChild(ch))
Array.from(document.getElementsByClassName("delete-on-load")).forEach(el => { Array.from(document.getElementsByClassName("delete-on-load")).forEach(el => {
el.parentElement.removeChild(el) el.parentElement.removeChild(el)
}) })

View file

@ -13,6 +13,8 @@
<link href="./css/wikipedia.css" rel="stylesheet"/> <link href="./css/wikipedia.css" rel="stylesheet"/>
<meta content="website" property="og:type"> <meta content="website" property="og:type">
<meta name="darkreader-lock"> <meta name="darkreader-lock">
<!-- We don't support dark mode (yet); disable it to prevent bugs -->
<meta name="color-scheme" content="light only">
<link rel="preconnect" href="https://api.maptiler.com"> <link rel="preconnect" href="https://api.maptiler.com">
<link rel="dns-prefetch" href="https://api.maptiler.com"> <link rel="dns-prefetch" href="https://api.maptiler.com">