wip: allow DataLayer.clear to be sync and undone

This commit is contained in:
Yohan Boniface 2025-03-23 11:32:51 +01:00
parent 9584b64a8f
commit 4a1d34540d
4 changed files with 44 additions and 14 deletions

View file

@ -269,13 +269,11 @@ export class DataLayer extends ServerStored {
} }
clear() { clear() {
this.layer.clearLayers() this.sync.startBatch()
this._features = {} for (const feature of Object.values(this._features)) {
this._index = Array() feature.del()
if (this._geojson) {
this.backupData()
this._geojson = null
} }
this.sync.commitBatch()
this.dataChanged() this.dataChanged()
} }

View file

@ -43,7 +43,11 @@ export class UndoManager {
copyOperation(stage, redo) { copyOperation(stage, redo) {
const operation = Utils.CopyJSON(stage.operation) const operation = Utils.CopyJSON(stage.operation)
operation.value = redo ? stage.newValue : stage.oldValue const value = redo ? stage.newValue : stage.oldValue
operation.value = value
if (['delete', 'upsert'].includes(operation.verb)) {
operation.verb = value === null || value === undefined ? 'delete' : 'upsert'
}
return operation return operation
} }
@ -73,18 +77,15 @@ export class UndoManager {
switch (operation.verb) { switch (operation.verb) {
case 'update': case 'update':
updater.update(operation) updater.update(operation)
this._syncEngine._send(operation)
break break
case 'delete': case 'delete':
updater.delete(operation)
break
case 'upsert': case 'upsert':
if (operation.value === null || operation.value === undefined) { updater.upsert(operation)
updater.delete(operation)
} else {
updater.upsert(operation)
}
this._syncEngine._send(operation)
break break
} }
this._syncEngine._send(operation)
} }
_getUpdater(subject, metadata) { _getUpdater(subject, metadata) {

View file

@ -18,6 +18,7 @@ DATALAYER_DATA = {
"features": [ "features": [
{ {
"type": "Feature", "type": "Feature",
"id": "ExNTQ",
"geometry": { "geometry": {
"type": "Point", "type": "Point",
"coordinates": [14.68896484375, 48.55297816440071], "coordinates": [14.68896484375, 48.55297816440071],

View file

@ -659,3 +659,33 @@ def test_should_sync_line_on_escape(new_page, asgi_live_server, tilelayer):
expect(peerA.locator("path")).to_have_count(1) expect(peerA.locator("path")).to_have_count(1)
expect(peerB.locator("path")).to_have_count(1) expect(peerB.locator("path")).to_have_count(1)
@pytest.mark.xdist_group(name="websockets")
def test_should_sync_datalayer_clear(
new_page, asgi_live_server, tilelayer, map, datalayer
):
map.settings["properties"]["syncEnabled"] = True
map.edit_status = Map.ANONYMOUS
map.save()
# Create two tabs
peerA = new_page("Page A")
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
peerB = new_page("Page B")
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
expect(peerA.locator(".leaflet-marker-icon")).to_have_count(1)
expect(peerB.locator(".leaflet-marker-icon")).to_have_count(1)
# Clear layer in peer A
peerA.get_by_role("button", name="Manage layers").click()
peerA.get_by_role("button", name="Edit", exact=True).click()
peerA.locator("summary").filter(has_text="Advanced actions").click()
peerA.get_by_role("button", name="Empty").click()
expect(peerA.locator(".leaflet-marker-icon")).to_have_count(0)
expect(peerB.locator(".leaflet-marker-icon")).to_have_count(0)
# Undo in peer A
peerA.get_by_role("button", name="Undo").click()
expect(peerA.locator(".leaflet-marker-icon")).to_have_count(1)
expect(peerB.locator(".leaflet-marker-icon")).to_have_count(1)