diff --git a/umap/static/umap/js/modules/data/layer.js b/umap/static/umap/js/modules/data/layer.js index ae1580f6..9cc31283 100644 --- a/umap/static/umap/js/modules/data/layer.js +++ b/umap/static/umap/js/modules/data/layer.js @@ -295,6 +295,7 @@ export class DataLayer { } clear() { + // TODO do not startBatch for remoteData layer this.sync.startBatch() for (const feature of Object.values(this._features)) { feature.del() @@ -637,11 +638,19 @@ export class DataLayer { del(sync = true) { const oldValue = Utils.CopyJSON(this.umapGeoJSON()) - this.erase() + // TODO merge datalayer del and features del in same + // batch + this.clear() if (sync) { this.isDeleted = true this.sync.delete(oldValue) } + this.hide() + this.parentPane.removeChild(this.pane) + this._umap.onDataLayersChanged() + this.layer.onDelete(this._leafletMap) + this.propagateDelete() + this._leaflet_events_bk = this._leaflet_events } empty() { @@ -659,16 +668,6 @@ export class DataLayer { return datalayer } - erase() { - this.hide() - this.parentPane.removeChild(this.pane) - this._umap.onDataLayersChanged() - this.layer.onDelete(this._leafletMap) - this.propagateDelete() - this._leaflet_events_bk = this._leaflet_events - this.clear() - } - redraw() { if (!this.isVisible()) return this.eachFeature((feature) => feature.redraw()) @@ -1121,6 +1120,12 @@ export class DataLayer { } } + prepareOptions() { + const options = Utils.CopyJSON(this.options) + delete options.permissions + return JSON.stringify(options) + } + async save() { if (this.isDeleted) return await this.saveDelete() if (!this.isRemoteLayer() && !this.isLoaded()) return @@ -1129,7 +1134,7 @@ export class DataLayer { formData.append('name', this.options.name) formData.append('display_on_load', !!this.options.displayOnLoad) formData.append('rank', this.options.rank) - formData.append('settings', JSON.stringify(this.options)) + formData.append('settings', this.prepareOptions()) // Filename support is shaky, don't do it for now. const blob = new Blob([JSON.stringify(geojson)], { type: 'application/json' }) formData.append('geojson', blob) diff --git a/umap/static/umap/js/modules/managers.js b/umap/static/umap/js/modules/managers.js new file mode 100644 index 00000000..00a06606 --- /dev/null +++ b/umap/static/umap/js/modules/managers.js @@ -0,0 +1,46 @@ +export class DataLayerManager extends Object { + add(datalayer) { + this[datalayer.id] = datalayer + } + active() { + return Object.values(this) + .filter((datalayer) => !datalayer.isDeleted) + .sort((a, b) => a.options.rank > b.options.rank) + } + reverse() { + return this.active().reverse() + } + count() { + return this.active().length + } + find(func) { + for (const datalayer of this.reverse()) { + if (func.call(datalayer, datalayer)) { + return datalayer + } + } + } + filter(func) { + return this.active().filter(func) + } + visible() { + return this.filter((datalayer) => datalayer.isVisible()) + } + browsable() { + return this.reverse().filter((datalayer) => datalayer.allowBrowse()) + } + prev(datalayer) { + const browsable = this.browsable() + const current = browsable.indexOf(datalayer) + const prev = browsable[current - 1] || browsable[browsable.length - 1] + if (!prev.canBrowse()) return this.prev(prev) + return prev + } + next(datalayer) { + const browsable = this.browsable() + const current = browsable.indexOf(datalayer) + const next = browsable[current + 1] || browsable[0] + if (!next.canBrowse()) return this.next(next) + return next + } +} diff --git a/umap/tests/base.py b/umap/tests/base.py index 59e64a76..7b4aa995 100644 --- a/umap/tests/base.py +++ b/umap/tests/base.py @@ -131,8 +131,8 @@ class DataLayerFactory(factory.django.DjangoModelFactory): data.setdefault("_umap_options", {}) if "name" in data["_umap_options"] and kwargs["name"] == cls.name: kwargs["name"] = data["_umap_options"]["name"] - if "settings" not in kwargs: - kwargs["settings"] = data.get("_umap_options", {}) + kwargs.setdefault("settings", {}) + kwargs["settings"].update(data.get("_umap_options", {})) else: data = DATALAYER_DATA.copy() data["_umap_options"] = { diff --git a/umap/tests/integration/test_optimistic_merge.py b/umap/tests/integration/test_optimistic_merge.py index fc7c0bd0..eb7438e4 100644 --- a/umap/tests/integration/test_optimistic_merge.py +++ b/umap/tests/integration/test_optimistic_merge.py @@ -50,6 +50,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer): "editMode": "advanced", "inCaption": True, "id": str(datalayer.pk), + "rank": 0, + "remoteData": {}, } # Now navigate to this map from another tab @@ -87,6 +89,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer): "inCaption": True, "editMode": "advanced", "id": str(datalayer.pk), + "rank": 0, + "remoteData": {}, } # Now create another marker in the first tab @@ -105,7 +109,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer): "inCaption": True, "editMode": "advanced", "id": str(datalayer.pk), - "permissions": {"edit_status": 1}, + "rank": 0, + "remoteData": {}, } # And again @@ -124,7 +129,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer): "inCaption": True, "editMode": "advanced", "id": str(datalayer.pk), - "permissions": {"edit_status": 1}, + "rank": 0, + "remoteData": {}, } expect(marker_pane_p1).to_have_count(4) @@ -145,7 +151,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer): "inCaption": True, "editMode": "advanced", "id": str(datalayer.pk), - "permissions": {"edit_status": 1}, + "rank": 0, + "remoteData": {}, } expect(marker_pane_p2).to_have_count(5) @@ -271,7 +278,8 @@ def test_same_second_edit_doesnt_conflict(context, live_server, tilelayer): "inCaption": True, "editMode": "advanced", "id": str(datalayer.pk), - "permissions": {"edit_status": 1}, + "rank": 0, + "remoteData": {}, }