diff --git a/umap/static/umap/js/modules/data/layer.js b/umap/static/umap/js/modules/data/layer.js index a6f77a671..d1be28e9f 100644 --- a/umap/static/umap/js/modules/data/layer.js +++ b/umap/static/umap/js/modules/data/layer.js @@ -574,9 +574,12 @@ export class DataLayer extends ServerStored { }) } - _delete() { - this.isDeleted = true + del(sync = true) { this.erase() + if (sync) { + this.isDeleted = true + this.sync.delete() + } } empty() { @@ -819,7 +822,7 @@ export class DataLayer extends ServerStored { ${translate('Delete')} `) deleteButton.addEventListener('click', () => { - this._delete() + this.del() this._umap.editPanel.close() }) advancedButtons.appendChild(deleteButton) @@ -1147,10 +1150,14 @@ export class DataLayer extends ServerStored { if (this.createdOnServer) { await this._umap.server.post(this.getDeleteUrl()) } - delete this._umap.datalayers[stamp(this)] + this.commitDelete() return true } + commitDelete() { + delete this._umap.datalayers[stamp(this)] + } + getName() { return this.options.name || translate('Untitled layer') } @@ -1221,7 +1228,7 @@ export class DataLayer extends ServerStored { this._umap.dialog .confirm(translate('Are you sure you want to delete this layer?')) .then(() => { - this._delete() + this.del() }) }, this diff --git a/umap/static/umap/js/modules/sync/updaters.js b/umap/static/umap/js/modules/sync/updaters.js index 75c4a9f22..5ab97375a 100644 --- a/umap/static/umap/js/modules/sync/updaters.js +++ b/umap/static/umap/js/modules/sync/updaters.js @@ -72,6 +72,14 @@ export class DataLayerUpdater extends BaseUpdater { } datalayer.render([key]) } + + delete({ metadata }) { + const datalayer = this.getDataLayerFromID(metadata.id) + if (datalayer) { + datalayer.del(false) + datalayer.commitDelete() + } + } } export class FeatureUpdater extends BaseUpdater { diff --git a/umap/tests/integration/test_websocket_sync.py b/umap/tests/integration/test_websocket_sync.py index c5e56e893..f4e3d7f80 100644 --- a/umap/tests/integration/test_websocket_sync.py +++ b/umap/tests/integration/test_websocket_sync.py @@ -420,6 +420,72 @@ def test_should_sync_datalayers(new_page, live_server, websocket_server, tilelay assert DataLayer.objects.count() == 2 +@pytest.mark.xdist_group(name="websockets") +def test_should_sync_datalayers_delete( + new_page, live_server, websocket_server, tilelayer +): + map = MapFactory(name="sync", edit_status=Map.ANONYMOUS) + map.settings["properties"]["syncEnabled"] = True + map.save() + data1 = { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "name": "Point 1", + }, + "geometry": {"type": "Point", "coordinates": [0.065918, 48.385442]}, + }, + ], + "_umap_options": { + "name": "datalayer 1", + }, + } + data2 = { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "name": "Point 2", + }, + "geometry": {"type": "Point", "coordinates": [3.55957, 49.767074]}, + }, + ], + "_umap_options": { + "name": "datalayer 2", + }, + } + DataLayerFactory(map=map, data=data1) + DataLayerFactory(map=map, data=data2) + + # Create two tabs + peerA = new_page("Page A") + peerA.goto(f"{live_server.url}{map.get_absolute_url()}?edit") + peerB = new_page("Page B") + peerB.goto(f"{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() + 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() + + # 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() + + # 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() + + @pytest.mark.xdist_group(name="websockets") def test_create_and_sync_map( new_page, live_server, websocket_server, tilelayer, login, user