diff --git a/umap/static/umap/css/bar.css b/umap/static/umap/css/bar.css
index 5df3bd87..cf71e2c1 100644
--- a/umap/static/umap/css/bar.css
+++ b/umap/static/umap/css/bar.css
@@ -163,11 +163,13 @@
.umap-main-edit-toolbox h3 {
display: inline;
}
-.umap-caption-bar button {
- margin-inline-start: 10px;
+.umap-caption-bar .umap-map-author {
+ margin-inline-end: 10px;
}
-.umap-caption-bar button + button:before {
+.umap-caption-bar > button + button:after,
+.umap-caption-bar > button + button:before {
content: '|';
+ padding-inline-start: 10px;
padding-inline-end: 10px;
}
.umap-main-edit-toolbox .umap-user:hover {
@@ -196,7 +198,14 @@
z-index: var(--zindex-panels);
}
.umap-caption-bar-enabled .umap-caption-bar {
- display: block;
+ display: flex;
+ align-items: baseline;
+}
+.umap-caption-bar select {
+ margin-top: 0;
+ line-height: initial;
+ height: initial;
+ width: auto;
}
.umap-caption-bar-enabled {
--current-footer-height: var(--footer-height);
diff --git a/umap/static/umap/js/modules/data/layer.js b/umap/static/umap/js/modules/data/layer.js
index f9d1f78f..88ab9667 100644
--- a/umap/static/umap/js/modules/data/layer.js
+++ b/umap/static/umap/js/modules/data/layer.js
@@ -966,12 +966,18 @@ export class DataLayer extends ServerStored {
this.propagateHide()
}
- toggle() {
+ toggle(force) {
// From now on, do not try to how/hidedataChanged
// automatically this layer.
+ let display = force
this._forcedVisibility = true
- if (!this.isVisible()) this.show()
+ if (force === undefined) {
+ if (!this.isVisible()) display = true
+ else display = false
+ }
+ if (display) this.show()
else this.hide()
+ this._umap.bottomBar.redraw()
}
zoomTo() {
@@ -1258,7 +1264,7 @@ export class DataLayer extends ServerStored {
this
)
}
- DomEvent.on(toggle, 'click', this.toggle, this)
+ DomEvent.on(toggle, 'click', () => this.toggle())
DomEvent.on(zoomTo, 'click', this.zoomTo, this)
container.classList.add(this.getHidableClass())
container.classList.toggle('off', !this.isVisible())
diff --git a/umap/static/umap/js/modules/ui/bar.js b/umap/static/umap/js/modules/ui/bar.js
index 3c2ef27d..f38616fa 100644
--- a/umap/static/umap/js/modules/ui/bar.js
+++ b/umap/static/umap/js/modules/ui/bar.js
@@ -167,6 +167,7 @@ const BOTTOM_BAR_TEMPLATE = `
+
`
@@ -189,6 +190,14 @@ export class BottomBar extends WithTemplate {
this._umap.openBrowser('filters')
)
this._slideshow.renderToolbox(this.element)
+ this.elements.layers.addEventListener('change', () => {
+ const select = this.elements.layers
+ const selected = select.options[select.selectedIndex].value
+ if (!selected) return
+ this._umap.eachDataLayer((datalayer) => {
+ datalayer.toggle(datalayer.id === selected)
+ })
+ })
this.redraw()
}
@@ -201,6 +210,27 @@ export class BottomBar extends WithTemplate {
this.elements.caption.hidden = !showMenus
this.elements.browse.hidden = !showMenus
this.elements.filter.hidden = !showMenus || !this._umap.properties.facetKey
+ this.buildDataLayerSwitcher()
+ }
+
+ buildDataLayerSwitcher() {
+ this.elements.layers.innerHTML = ''
+ const datalayers = this._umap.datalayersIndex.filter((d) => d.options.inCaption)
+ if (datalayers.length < 2) {
+ this.elements.layers.hidden = true
+ } else {
+ this.elements.layers.appendChild(Utils.loadTemplate(``))
+ this.elements.layers.hidden = false
+ const visible = datalayers.filter((datalayer) => datalayer.isVisible())
+ for (const datalayer of datalayers) {
+ const selected = visible.length === 1 && datalayer.isVisible() ? 'selected' : ''
+ this.elements.layers.appendChild(
+ Utils.loadTemplate(
+ ``
+ )
+ )
+ }
+ }
}
}
diff --git a/umap/tests/integration/test_edit_datalayer.py b/umap/tests/integration/test_edit_datalayer.py
index 7353d25d..e01c0ace 100644
--- a/umap/tests/integration/test_edit_datalayer.py
+++ b/umap/tests/integration/test_edit_datalayer.py
@@ -182,7 +182,7 @@ def test_can_restore_version(live_server, openmap, page, datalayer):
page.get_by_role("button", name="Manage layers").click()
page.locator(".panel.right").get_by_title("Edit", exact=True).click()
page.get_by_text("Versions").click()
- page.get_by_role("button", name="Restore this version").last.click()
+ page.get_by_title("Restore this version").last.click()
page.get_by_role("button", name="OK").click()
expect(marker).to_have_class(re.compile(".*umap-ball-icon.*"))
diff --git a/umap/tests/integration/test_import.py b/umap/tests/integration/test_import.py
index 095b2da6..9429be55 100644
--- a/umap/tests/integration/test_import.py
+++ b/umap/tests/integration/test_import.py
@@ -86,8 +86,8 @@ def test_umap_import_from_textarea(live_server, tilelayer, page, settings):
expect(page.locator(".umap-main-edit-toolbox .map-name")).to_have_text(
"Imported map"
)
- expect(page.get_by_text("Tunnels")).to_be_visible()
- expect(page.get_by_text("Cities")).to_be_visible()
+ expect(page.locator(".panel.left").get_by_text("Tunnels")).to_be_visible()
+ expect(page.locator(".panel.left").get_by_text("Cities")).to_be_visible()
expect(page.locator(".leaflet-control-minimap")).to_be_visible()
expect(
page.locator('img[src="https://tile.openstreetmap.fr/hot/6/32/21.png"]')
diff --git a/umap/tests/integration/test_websocket_sync.py b/umap/tests/integration/test_websocket_sync.py
index 40db583e..7c3c3f34 100644
--- a/umap/tests/integration/test_websocket_sync.py
+++ b/umap/tests/integration/test_websocket_sync.py
@@ -477,23 +477,23 @@ def test_should_sync_datalayers_delete(new_page, asgi_live_server, tilelayer):
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
peerA.get_by_role("button", name="Open browser").click()
- expect(peerA.get_by_text("datalayer 1")).to_be_visible()
- expect(peerA.get_by_text("datalayer 2")).to_be_visible()
+ expect(peerA.locator(".panel").get_by_text("datalayer 1")).to_be_visible()
+ expect(peerA.locator(".panel").get_by_text("datalayer 2")).to_be_visible()
peerB.get_by_role("button", name="Open browser").click()
- expect(peerB.get_by_text("datalayer 1")).to_be_visible()
- expect(peerB.get_by_text("datalayer 2")).to_be_visible()
+ expect(peerB.locator(".panel").get_by_text("datalayer 1")).to_be_visible()
+ expect(peerB.locator(".panel").get_by_text("datalayer 2")).to_be_visible()
# Delete "datalayer 2" in peerA
peerA.locator(".datalayer").get_by_role("button", name="Delete layer").first.click()
peerA.get_by_role("button", name="OK").click()
- expect(peerA.get_by_text("datalayer 2")).to_be_hidden()
- expect(peerB.get_by_text("datalayer 2")).to_be_hidden()
+ expect(peerA.locator(".panel").get_by_text("datalayer 2")).to_be_hidden()
+ expect(peerB.locator(".panel").get_by_text("datalayer 2")).to_be_hidden()
# Save delete to the server
with peerA.expect_response(re.compile(".*/datalayer/delete/.*")):
peerA.get_by_role("button", name="Save").click()
- expect(peerA.get_by_text("datalayer 2")).to_be_hidden()
- expect(peerB.get_by_text("datalayer 2")).to_be_hidden()
+ expect(peerA.locator(".panel").get_by_text("datalayer 2")).to_be_hidden()
+ expect(peerB.locator(".panel").get_by_text("datalayer 2")).to_be_hidden()
@pytest.mark.xdist_group(name="websockets")