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")