Compare commits

..

No commits in common. "48daa0a77fad148125b69e62563cb4a84568b969" and "fc6ea191cc4f45a3cf248f303f60d1eae4cacdf0" have entirely different histories.

13 changed files with 369 additions and 231 deletions

View file

@ -45,7 +45,7 @@
"georsstogeojson": "^0.2.0",
"jsdom": "^24.0.0",
"leaflet": "1.9.4",
"leaflet-editable": "^1.3.1",
"leaflet-editable": "^1.3.0",
"leaflet-editinosm": "0.2.3",
"leaflet-fullscreen": "1.0.2",
"leaflet-hash": "0.2.1",

View file

@ -36,7 +36,7 @@ dependencies = [
"psycopg==3.2.4",
"requests==2.32.3",
"rcssmin==1.2.1",
"rjsmin==1.2.4",
"rjsmin==1.2.3",
"social-auth-core==4.5.4",
"social-auth-app-django==5.4.2",
]

View file

@ -335,15 +335,15 @@ class Feature {
// Variables mode.
if (labelKey) {
if (Utils.hasVar(labelKey)) {
return Utils.greedyTemplate(labelKey, this.extendedProperties()).trim()
return Utils.greedyTemplate(labelKey, this.extendedProperties())
}
keys.unshift(labelKey)
}
for (const key of keys) {
const value = this.properties[key]
if (value) return value.trim()
if (value) return value
}
return this.datalayer.getName().trim()
return this.datalayer.getName()
}
hasPopupFooter() {
@ -640,12 +640,6 @@ class Feature {
window.open(permalink)
},
})
items.push({
label: translate('Layer permalink'),
action: () => {
window.open(this.datalayer.getPermalink())
},
})
}
items.push({
label: translate('Copy as GeoJSON'),

View file

@ -1174,12 +1174,6 @@ export class DataLayer extends ServerStored {
return this.options.name || translate('Untitled layer')
}
getPermalink() {
return `${Utils.getBaseUrl()}?${Utils.buildQueryString({ datalayers: this.id })}${
window.location.hash
}`
}
tableEdit() {
if (!this.isVisible()) return
const editor = new TableEditor(this._umap, this, this._leafletMap)

View file

@ -60,7 +60,8 @@ const FeatureMixin = {
if (event.originalEvent.ctrlKey || event.originalEvent.metaKey) {
this.feature.datalayer.edit(event)
} else {
this.feature.toggleEditing(event)
if (this.feature._toggleEditing) this.feature._toggleEditing(event)
else this.feature.edit(event)
}
} else if (!this._map.editTools?.drawing()) {
this._map._umap.editContextmenu.open(

View file

@ -66,12 +66,7 @@ export class SyncEngine {
this.peerId = Utils.generateId()
}
get isOpen() {
return this.transport?.isOpen
}
async authenticate() {
if (this.isOpen) return
const websocketTokenURI = this._umap.urls.get('map_websocket_auth_token', {
map_id: this._umap.id,
})
@ -203,7 +198,6 @@ export class SyncEngine {
*/
onOperationMessage(payload) {
if (payload.sender === this.peerId) return
debug('received operation', payload)
this._operations.storeRemoteOperations([payload])
this._applyOperation(payload)
}
@ -267,7 +261,7 @@ export class SyncEngine {
* @param {*} operations The list of (encoded operations)
*/
onListOperationsResponse({ sender, message }) {
debug(`received operations list from peer ${sender}`, message.operations)
debug(`received operations from peer ${sender}`, message.operations)
if (message.operations.length === 0) return
@ -508,7 +502,11 @@ export class Operations {
* @return {bool} true if the two operations share the same context.
*/
static haveSameContext(local, remote) {
const shouldCheckKey = local.key !== undefined && remote.key !== undefined
const shouldCheckKey =
local.hasOwnProperty('key') &&
remote.hasOwnProperty('key') &&
typeof local.key !== 'undefined' &&
typeof remote.key !== 'undefined'
return (
Utils.deepEqual(local.subject, remote.subject) &&

View file

@ -54,11 +54,7 @@ export class MapUpdater extends BaseUpdater {
export class DataLayerUpdater extends BaseUpdater {
upsert({ value }) {
// Upsert only happens when a new datalayer is created.
try {
this.getDataLayerFromID(value.id)
} catch {
this._umap.createDataLayer(value, false)
}
const datalayer = this._umap.createDataLayer(value, false)
}
update({ key, metadata, value }) {

View file

@ -76,8 +76,4 @@ export class WebSocketTransport {
this.receiver.closeRequested = true
this.websocket.close()
}
get isOpen() {
return this.websocket?.readyState === WebSocket.OPEN
}
}

View file

@ -699,7 +699,6 @@ U.Editable = L.Editable.extend({
if (!event.layer.feature.hasGeom()) {
event.layer.feature.del()
} else {
event.layer.feature.onCommit()
event.layer.feature.edit()
}
})

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1248,7 +1248,6 @@
// 🍂event editable:vertex:deleted: VertexEvent
// Fired after a vertex has been deleted by user.
this.fireAndForward('editable:vertex:deleted', e)
this.onEdited()
},
onVertexMarkerCtrlClick: function (e) {

View file

@ -535,11 +535,6 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
expect(markersA).to_have_count(1)
expect(markersB).to_have_count(1)
# Make sure only one layer has been created on peer B
peerB.get_by_role("button", name="Open browser").click()
expect(peerB.locator("h5").get_by_text("Layer 1")).to_be_visible()
peerB.get_by_role("button", name="Close").click()
# Save and quit edit mode again
with peerA.expect_response(re.compile("./datalayer/create/.*")):
peerA.get_by_role("button", name="Save").click()
@ -568,34 +563,6 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
expect(markersB).to_have_count(2)
@pytest.mark.xdist_group(name="websockets")
def test_saved_datalayer_are_not_duplicated(new_page, asgi_live_server, tilelayer):
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
map.settings["properties"]["syncEnabled"] = True
map.save()
# Create one tab
peerA = new_page("Page A")
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
# Create a new datalayer
peerA.get_by_title("Manage layers").click()
peerA.get_by_title("Add a layer").click()
peerA.locator("#map").click(position={"x": 220, "y": 220})
# Save layer to the server, so now the datalayer exist on the server AND
# is still in the live operations of peer A
with peerA.expect_response(re.compile(".*/datalayer/create/.*")):
peerA.get_by_role("button", name="Save").click()
# Now load the map from another tab
peerB = new_page("Page B")
peerB.goto(peerA.url)
peerB.get_by_role("button", name="Open browser").click()
expect(peerB.get_by_text("Layer 1")).to_be_visible()
peerB.get_by_role("button", name="Edit").click()
peerA.wait_for_timeout(300) # Let the synchro roll on.
expect(peerB.get_by_text("Layer 1")).to_be_visible()
@pytest.mark.xdist_group(name="websockets")
def test_should_sync_saved_status(new_page, asgi_live_server, tilelayer):
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
@ -637,25 +604,3 @@ def test_should_sync_saved_status(new_page, asgi_live_server, tilelayer):
# Peer A should not be in dirty state
expect(peerA.locator("body")).not_to_have_class(re.compile(".*umap-is-dirty.*"))
@pytest.mark.xdist_group(name="websockets")
def test_should_sync_line_on_escape(new_page, asgi_live_server, tilelayer):
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
map.settings["properties"]["syncEnabled"] = True
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")
# Create a new marker from peerA
peerA.get_by_title("Draw a polyline").click()
peerA.locator("#map").click(position={"x": 220, "y": 220})
peerA.locator("#map").click(position={"x": 200, "y": 200})
peerA.locator("body").press("Escape")
expect(peerA.locator("path")).to_have_count(1)
expect(peerB.locator("path")).to_have_count(1)