umap-project 2.9.0b0__py3-none-any.whl → 2.9.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- umap/__init__.py +1 -1
- umap/admin.py +15 -2
- umap/locale/br/LC_MESSAGES/django.mo +0 -0
- umap/locale/br/LC_MESSAGES/django.po +111 -67
- umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- umap/locale/cs_CZ/LC_MESSAGES/django.po +112 -67
- umap/locale/el/LC_MESSAGES/django.mo +0 -0
- umap/locale/el/LC_MESSAGES/django.po +132 -87
- umap/locale/en/LC_MESSAGES/django.po +11 -10
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +117 -71
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +11 -10
- umap/locale/gl/LC_MESSAGES/django.mo +0 -0
- umap/locale/gl/LC_MESSAGES/django.po +219 -173
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.po +145 -100
- umap/locale/nl/LC_MESSAGES/django.mo +0 -0
- umap/locale/nl/LC_MESSAGES/django.po +198 -152
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +118 -73
- umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh_TW/LC_MESSAGES/django.po +112 -67
- umap/middleware.py +30 -1
- umap/models.py +20 -10
- umap/settings/base.py +2 -1
- umap/static/umap/base.css +4 -1
- umap/static/umap/css/bar.css +32 -0
- umap/static/umap/css/contextmenu.css +14 -2
- umap/static/umap/css/form.css +5 -10
- umap/static/umap/css/icon.css +39 -3
- umap/static/umap/css/panel.css +18 -1
- umap/static/umap/css/popup.css +0 -1
- umap/static/umap/img/16-white.svg +3 -3
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/24-white.svg +17 -16
- umap/static/umap/img/24.svg +29 -18
- umap/static/umap/img/providers/twitter-oauth2.png +0 -0
- umap/static/umap/img/source/16-white.svg +4 -4
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/img/source/24-white.svg +20 -18
- umap/static/umap/img/source/24.svg +30 -19
- umap/static/umap/js/modules/browser.js +2 -2
- umap/static/umap/js/modules/caption.js +4 -4
- umap/static/umap/js/modules/data/features.js +80 -32
- umap/static/umap/js/modules/data/layer.js +37 -50
- umap/static/umap/js/modules/form/builder.js +23 -22
- umap/static/umap/js/modules/form/fields.js +13 -5
- umap/static/umap/js/modules/formatter.js +6 -2
- umap/static/umap/js/modules/help.js +17 -23
- umap/static/umap/js/modules/importer.js +5 -2
- umap/static/umap/js/modules/permissions.js +6 -2
- umap/static/umap/js/modules/rendering/layers/classified.js +1 -1
- umap/static/umap/js/modules/rendering/map.js +1 -21
- umap/static/umap/js/modules/rendering/ui.js +20 -38
- umap/static/umap/js/modules/rules.js +1 -1
- umap/static/umap/js/modules/saving.js +5 -0
- umap/static/umap/js/modules/schema.js +4 -1
- umap/static/umap/js/modules/sync/engine.js +39 -14
- umap/static/umap/js/modules/sync/updaters.js +7 -6
- umap/static/umap/js/modules/sync/websocket.js +48 -40
- umap/static/umap/js/modules/ui/bar.js +84 -0
- umap/static/umap/js/modules/ui/contextmenu.js +9 -2
- umap/static/umap/js/modules/ui/panel.js +5 -1
- umap/static/umap/js/modules/umap.js +85 -44
- umap/static/umap/js/umap.controls.js +11 -341
- umap/static/umap/locale/am_ET.js +17 -5
- umap/static/umap/locale/am_ET.json +17 -5
- umap/static/umap/locale/ar.js +17 -5
- umap/static/umap/locale/ar.json +17 -5
- umap/static/umap/locale/ast.js +17 -5
- umap/static/umap/locale/ast.json +17 -5
- umap/static/umap/locale/bg.js +17 -5
- umap/static/umap/locale/bg.json +17 -5
- umap/static/umap/locale/br.js +20 -15
- umap/static/umap/locale/br.json +20 -15
- umap/static/umap/locale/ca.js +8 -4
- umap/static/umap/locale/ca.json +8 -4
- umap/static/umap/locale/cs_CZ.js +8 -4
- umap/static/umap/locale/cs_CZ.json +8 -4
- umap/static/umap/locale/da.js +17 -5
- umap/static/umap/locale/da.json +17 -5
- umap/static/umap/locale/de.js +8 -4
- umap/static/umap/locale/de.json +8 -4
- umap/static/umap/locale/el.js +54 -50
- umap/static/umap/locale/el.json +54 -50
- umap/static/umap/locale/en.js +9 -4
- umap/static/umap/locale/en.json +9 -4
- umap/static/umap/locale/en_US.json +17 -5
- umap/static/umap/locale/es.js +13 -9
- umap/static/umap/locale/es.json +13 -9
- umap/static/umap/locale/et.js +17 -5
- umap/static/umap/locale/et.json +17 -5
- umap/static/umap/locale/eu.js +8 -4
- umap/static/umap/locale/eu.json +8 -4
- umap/static/umap/locale/fa_IR.js +8 -4
- umap/static/umap/locale/fa_IR.json +8 -4
- umap/static/umap/locale/fi.js +17 -5
- umap/static/umap/locale/fi.json +17 -5
- umap/static/umap/locale/fr.js +9 -4
- umap/static/umap/locale/fr.json +9 -4
- umap/static/umap/locale/gl.js +13 -9
- umap/static/umap/locale/gl.json +13 -9
- umap/static/umap/locale/he.js +17 -5
- umap/static/umap/locale/he.json +17 -5
- umap/static/umap/locale/hr.js +17 -5
- umap/static/umap/locale/hr.json +17 -5
- umap/static/umap/locale/hu.js +8 -4
- umap/static/umap/locale/hu.json +8 -4
- umap/static/umap/locale/id.js +17 -5
- umap/static/umap/locale/id.json +17 -5
- umap/static/umap/locale/is.js +17 -5
- umap/static/umap/locale/is.json +17 -5
- umap/static/umap/locale/it.js +31 -27
- umap/static/umap/locale/it.json +31 -27
- umap/static/umap/locale/ja.js +17 -5
- umap/static/umap/locale/ja.json +17 -5
- umap/static/umap/locale/ko.js +17 -5
- umap/static/umap/locale/ko.json +17 -5
- umap/static/umap/locale/lt.js +17 -5
- umap/static/umap/locale/lt.json +17 -5
- umap/static/umap/locale/ms.js +8 -4
- umap/static/umap/locale/ms.json +8 -4
- umap/static/umap/locale/nl.js +132 -127
- umap/static/umap/locale/nl.json +132 -127
- umap/static/umap/locale/no.js +17 -5
- umap/static/umap/locale/no.json +17 -5
- umap/static/umap/locale/pl.js +8 -4
- umap/static/umap/locale/pl.json +8 -4
- umap/static/umap/locale/pl_PL.json +17 -5
- umap/static/umap/locale/pt.js +38 -33
- umap/static/umap/locale/pt.json +38 -33
- umap/static/umap/locale/pt_BR.js +17 -5
- umap/static/umap/locale/pt_BR.json +17 -5
- umap/static/umap/locale/pt_PT.js +8 -4
- umap/static/umap/locale/pt_PT.json +8 -4
- umap/static/umap/locale/ro.js +17 -5
- umap/static/umap/locale/ro.json +17 -5
- umap/static/umap/locale/ru.js +17 -5
- umap/static/umap/locale/ru.json +17 -5
- umap/static/umap/locale/sk_SK.js +17 -5
- umap/static/umap/locale/sk_SK.json +17 -5
- umap/static/umap/locale/sl.js +17 -5
- umap/static/umap/locale/sl.json +17 -5
- umap/static/umap/locale/sr.js +17 -5
- umap/static/umap/locale/sr.json +17 -5
- umap/static/umap/locale/sv.js +17 -5
- umap/static/umap/locale/sv.json +17 -5
- umap/static/umap/locale/th_TH.js +8 -4
- umap/static/umap/locale/th_TH.json +8 -4
- umap/static/umap/locale/tr.js +17 -5
- umap/static/umap/locale/tr.json +17 -5
- umap/static/umap/locale/uk_UA.js +17 -5
- umap/static/umap/locale/uk_UA.json +17 -5
- umap/static/umap/locale/vi.js +17 -5
- umap/static/umap/locale/vi.json +17 -5
- umap/static/umap/locale/vi_VN.json +17 -5
- umap/static/umap/locale/zh.js +17 -5
- umap/static/umap/locale/zh.json +17 -5
- umap/static/umap/locale/zh_CN.json +17 -5
- umap/static/umap/locale/zh_TW.Big5.json +17 -5
- umap/static/umap/locale/zh_TW.js +14 -10
- umap/static/umap/locale/zh_TW.json +14 -10
- umap/static/umap/map.css +17 -68
- umap/static/umap/nav.css +4 -0
- umap/static/umap/vars.css +1 -0
- umap/static/umap/vendors/dompurify/purify.es.js +138 -354
- umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
- umap/static/umap/vendors/editable/Leaflet.Editable.js +1 -0
- umap/sync/app.py +19 -13
- umap/sync/payloads.py +8 -1
- umap/templates/auth/user_form.html +2 -2
- umap/templates/umap/content_footer.html +1 -1
- umap/templates/umap/css.html +0 -2
- umap/templates/umap/js.html +0 -1
- umap/templates/umap/messages.html +5 -1
- umap/templates/umap/search_bar.html +1 -0
- umap/tests/integration/test_anonymous_owned_map.py +2 -2
- umap/tests/integration/test_basics.py +2 -5
- umap/tests/integration/test_categorized_layer.py +4 -8
- umap/tests/integration/test_choropleth.py +1 -1
- umap/tests/integration/test_conditional_rules.py +3 -3
- umap/tests/integration/test_draw_polygon.py +11 -19
- umap/tests/integration/test_draw_polyline.py +6 -14
- umap/tests/integration/test_edit_datalayer.py +10 -10
- umap/tests/integration/test_edit_map.py +27 -1
- umap/tests/integration/test_edit_marker.py +5 -5
- umap/tests/integration/test_edit_polygon.py +5 -5
- umap/tests/integration/test_features_id_generation.py +2 -6
- umap/tests/integration/test_import.py +93 -29
- umap/tests/integration/test_owned_map.py +1 -1
- umap/tests/integration/test_save.py +2 -2
- umap/tests/integration/test_tableeditor.py +7 -7
- umap/tests/integration/test_view_marker.py +10 -0
- umap/tests/integration/test_websocket_sync.py +128 -32
- umap/utils.py +4 -1
- umap/views.py +0 -9
- {umap_project-2.9.0b0.dist-info → umap_project-2.9.1.dist-info}/METADATA +13 -13
- {umap_project-2.9.0b0.dist-info → umap_project-2.9.1.dist-info}/RECORD +202 -204
- umap/static/umap/vendors/toolbar/leaflet.toolbar.css +0 -1
- umap/static/umap/vendors/toolbar/leaflet.toolbar.js +0 -1
- {umap_project-2.9.0b0.dist-info → umap_project-2.9.1.dist-info}/WHEEL +0 -0
- {umap_project-2.9.0b0.dist-info → umap_project-2.9.1.dist-info}/entry_points.txt +0 -0
- {umap_project-2.9.0b0.dist-info → umap_project-2.9.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -59,7 +59,7 @@ def test_websocket_connection_can_sync_markers(new_page, asgi_live_server, tilel
|
|
|
59
59
|
peerA.wait_for_timeout(300)
|
|
60
60
|
|
|
61
61
|
peerB.locator(".leaflet-marker-icon").first.click()
|
|
62
|
-
peerB.get_by_role("
|
|
62
|
+
peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
63
63
|
expect(peerB.locator('input[name="name"]')).to_have_value("Synced name")
|
|
64
64
|
|
|
65
65
|
a_first_marker = peerA.locator("div:nth-child(4) > div:nth-child(2)").first
|
|
@@ -107,9 +107,7 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
|
|
|
107
107
|
b_map_el = peerB.locator("#map")
|
|
108
108
|
|
|
109
109
|
# Click on the Draw a polygon button on a new map.
|
|
110
|
-
create_line = peerA.locator(".
|
|
111
|
-
"Draw a polygon"
|
|
112
|
-
)
|
|
110
|
+
create_line = peerA.locator(".umap-edit-bar ").get_by_title("Draw a polygon")
|
|
113
111
|
create_line.click()
|
|
114
112
|
|
|
115
113
|
a_polygons = peerA.locator(".leaflet-overlay-pane path[fill='DarkBlue']")
|
|
@@ -124,11 +122,11 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
|
|
|
124
122
|
map.click(position={"x": 100, "y": 100})
|
|
125
123
|
map.click(position={"x": 100, "y": 100})
|
|
126
124
|
|
|
127
|
-
# It is created on peerA,
|
|
125
|
+
# It is created on peerA, and should be on peerB
|
|
128
126
|
expect(a_polygons).to_have_count(1)
|
|
129
|
-
expect(b_polygons).to_have_count(
|
|
127
|
+
expect(b_polygons).to_have_count(1)
|
|
130
128
|
|
|
131
|
-
# Escaping the edition
|
|
129
|
+
# Escaping the edition should not duplicate
|
|
132
130
|
peerA.keyboard.press("Escape")
|
|
133
131
|
expect(a_polygons).to_have_count(1)
|
|
134
132
|
expect(b_polygons).to_have_count(1)
|
|
@@ -141,7 +139,7 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
|
|
|
141
139
|
assert b_polygon_bbox_t1 == a_polygon_bbox_t1
|
|
142
140
|
|
|
143
141
|
b_polygon.click()
|
|
144
|
-
peerB.get_by_role("
|
|
142
|
+
peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
145
143
|
|
|
146
144
|
edited_vertex = peerB.locator("div:nth-child(6)").first
|
|
147
145
|
edited_vertex.drag_to(b_map_el, target_position={"x": 233, "y": 126})
|
|
@@ -155,7 +153,7 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
|
|
|
155
153
|
|
|
156
154
|
# Move the polygon on peer B and check it moved also on peer A
|
|
157
155
|
b_polygon.click()
|
|
158
|
-
peerB.get_by_role("
|
|
156
|
+
peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
159
157
|
|
|
160
158
|
b_polygon.drag_to(b_map_el, target_position={"x": 400, "y": 400})
|
|
161
159
|
peerB.keyboard.press("Escape")
|
|
@@ -189,14 +187,14 @@ def test_websocket_connection_can_sync_map_properties(
|
|
|
189
187
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
190
188
|
|
|
191
189
|
# Name change is synced
|
|
192
|
-
peerA.get_by_role("
|
|
190
|
+
peerA.get_by_role("button", name="Edit map name and caption").click()
|
|
193
191
|
peerA.locator('input[name="name"]').click()
|
|
194
192
|
peerA.locator('input[name="name"]').fill("it syncs!")
|
|
195
193
|
|
|
196
194
|
expect(peerB.locator(".map-name").last).to_have_text("it syncs!")
|
|
197
195
|
|
|
198
196
|
# Zoom control is synced
|
|
199
|
-
peerB.get_by_role("
|
|
197
|
+
peerB.get_by_role("button", name="Map advanced properties").click()
|
|
200
198
|
peerB.locator("summary").filter(has_text="User interface options").click()
|
|
201
199
|
switch = peerB.locator("div.formbox").filter(
|
|
202
200
|
has_text=re.compile("Display the zoom control")
|
|
@@ -223,14 +221,14 @@ def test_websocket_connection_can_sync_datalayer_properties(
|
|
|
223
221
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
224
222
|
|
|
225
223
|
# Layer addition, name and type are synced
|
|
226
|
-
peerA.get_by_role("
|
|
224
|
+
peerA.get_by_role("button", name="Manage layers").click()
|
|
227
225
|
peerA.get_by_role("button", name="Add a layer").click()
|
|
228
226
|
peerA.locator('input[name="name"]').click()
|
|
229
227
|
peerA.locator('input[name="name"]').fill("synced layer!")
|
|
230
228
|
peerA.get_by_role("combobox").select_option("Choropleth")
|
|
231
229
|
peerA.locator("body").press("Escape")
|
|
232
230
|
|
|
233
|
-
peerB.get_by_role("
|
|
231
|
+
peerB.get_by_role("button", name="Manage layers").click()
|
|
234
232
|
peerB.locator(".panel.right").get_by_role("button", name="Edit").first.click()
|
|
235
233
|
expect(peerB.locator('input[name="name"]')).to_have_value("synced layer!")
|
|
236
234
|
expect(peerB.get_by_role("combobox")).to_have_value("Choropleth")
|
|
@@ -254,9 +252,7 @@ def test_websocket_connection_can_sync_cloned_polygons(
|
|
|
254
252
|
b_map_el = peerB.locator("#map")
|
|
255
253
|
|
|
256
254
|
# Click on the Draw a polygon button on a new map.
|
|
257
|
-
create_line = peerA.locator(".
|
|
258
|
-
"Draw a polygon"
|
|
259
|
-
)
|
|
255
|
+
create_line = peerA.locator(".umap-edit-bar ").get_by_title("Draw a polygon")
|
|
260
256
|
create_line.click()
|
|
261
257
|
|
|
262
258
|
a_polygons = peerA.locator(".leaflet-overlay-pane path[fill='DarkBlue']")
|
|
@@ -324,9 +320,7 @@ def test_websocket_connection_can_sync_late_joining_peer(
|
|
|
324
320
|
peerA.wait_for_timeout(300)
|
|
325
321
|
|
|
326
322
|
# Add a polygon from peer A
|
|
327
|
-
create_polygon = peerA.locator(".
|
|
328
|
-
"Draw a polygon"
|
|
329
|
-
)
|
|
323
|
+
create_polygon = peerA.locator(".umap-edit-bar ").get_by_title("Draw a polygon")
|
|
330
324
|
create_polygon.click()
|
|
331
325
|
|
|
332
326
|
a_map_el.click(position={"x": 200, "y": 200})
|
|
@@ -349,7 +343,7 @@ def test_websocket_connection_can_sync_late_joining_peer(
|
|
|
349
343
|
|
|
350
344
|
# Verify marker properties
|
|
351
345
|
peerB.locator(".leaflet-marker-icon").first.click()
|
|
352
|
-
peerB.get_by_role("
|
|
346
|
+
peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
353
347
|
expect(peerB.locator('input[name="name"]')).to_have_value("First marker")
|
|
354
348
|
|
|
355
349
|
# Verify polygon exists (we've already checked the count)
|
|
@@ -377,7 +371,7 @@ def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer):
|
|
|
377
371
|
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
378
372
|
|
|
379
373
|
# Create a new layer from peerA
|
|
380
|
-
peerA.get_by_role("
|
|
374
|
+
peerA.get_by_role("button", name="Manage layers").click()
|
|
381
375
|
peerA.get_by_role("button", name="Add a layer").click()
|
|
382
376
|
|
|
383
377
|
# Check layer has been sync to peerB
|
|
@@ -385,7 +379,7 @@ def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer):
|
|
|
385
379
|
expect(peerB.get_by_text("Layer 1")).to_be_visible()
|
|
386
380
|
|
|
387
381
|
# Draw a marker in layer 1 from peerA
|
|
388
|
-
peerA.get_by_role("
|
|
382
|
+
peerA.get_by_role("button", name="Draw a marker (Ctrl+M)").click()
|
|
389
383
|
peerA.locator("#map").click()
|
|
390
384
|
|
|
391
385
|
# Check marker is visible from peerB
|
|
@@ -398,20 +392,22 @@ def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer):
|
|
|
398
392
|
assert DataLayer.objects.count() == 1
|
|
399
393
|
|
|
400
394
|
# Create another layer from peerA and draw a marker on it (without saving to server)
|
|
401
|
-
peerA.get_by_role("
|
|
395
|
+
peerA.get_by_role("button", name="Manage layers").click()
|
|
402
396
|
peerA.get_by_role("button", name="Add a layer").click()
|
|
403
|
-
peerA.get_by_role("
|
|
397
|
+
peerA.get_by_role("button", name="Draw a marker (Ctrl+M)").click()
|
|
404
398
|
peerA.locator("#map").click()
|
|
405
399
|
|
|
406
400
|
# Make sure this new marker is in Layer 2 for peerB
|
|
407
|
-
|
|
401
|
+
# Show features for this layer in the brower.
|
|
402
|
+
peerB.get_by_role("heading", name="Layer 2").locator(".datalayer-name").click()
|
|
403
|
+
expect(peerB.locator("li").filter(has_text="Layer 2")).to_be_visible()
|
|
408
404
|
peerB.locator(".panel.left").get_by_role("button", name="Show/hide layer").nth(
|
|
409
405
|
1
|
|
410
406
|
).click()
|
|
411
407
|
expect(peerB.locator(".leaflet-marker-icon")).to_be_visible()
|
|
412
408
|
|
|
413
409
|
# Now draw a marker from peerB
|
|
414
|
-
peerB.get_by_role("
|
|
410
|
+
peerB.get_by_role("button", name="Draw a marker (Ctrl+M)").click()
|
|
415
411
|
peerB.locator("#map").click()
|
|
416
412
|
peerB.locator('input[name="name"]').fill("marker from peerB")
|
|
417
413
|
|
|
@@ -427,9 +423,11 @@ def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer):
|
|
|
427
423
|
1
|
|
428
424
|
).click()
|
|
429
425
|
|
|
430
|
-
#
|
|
431
|
-
|
|
432
|
-
|
|
426
|
+
# Peer A should not be in dirty state
|
|
427
|
+
expect(peerA.locator("body")).not_to_have_class(re.compile(".*umap-is-dirty.*"))
|
|
428
|
+
|
|
429
|
+
# Peer A should only have two markers
|
|
430
|
+
expect(peerA.locator(".leaflet-marker-icon")).to_have_count(2)
|
|
433
431
|
|
|
434
432
|
assert DataLayer.objects.count() == 2
|
|
435
433
|
|
|
@@ -503,15 +501,15 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
|
|
|
503
501
|
# Create a syncable map with peerA
|
|
504
502
|
peerA = login(user, prefix="Page A")
|
|
505
503
|
peerA.goto(f"{asgi_live_server.url}/en/map/new/")
|
|
506
|
-
peerA.get_by_role("
|
|
504
|
+
peerA.get_by_role("button", name="Map advanced properties").click()
|
|
507
505
|
expect(peerA.get_by_text("Real-time collaboration", exact=True)).to_be_hidden()
|
|
508
506
|
with peerA.expect_response(re.compile("./map/create/.*")):
|
|
509
507
|
peerA.get_by_role("button", name="Save Draft").click()
|
|
510
|
-
peerA.get_by_role("
|
|
508
|
+
peerA.get_by_role("button", name="Map advanced properties").click()
|
|
511
509
|
expect(peerA.get_by_text("Real-time collaboration", exact=True)).to_be_visible()
|
|
512
510
|
peerA.get_by_text("Real-time collaboration", exact=True).click()
|
|
513
511
|
peerA.get_by_text("Enable real-time").click()
|
|
514
|
-
peerA.get_by_role("
|
|
512
|
+
peerA.get_by_role("button", name="Update permissions and editors").click()
|
|
515
513
|
peerA.locator('select[name="share_status"]').select_option(str(Map.PUBLIC))
|
|
516
514
|
with peerA.expect_response(re.compile("./update/settings/.*")):
|
|
517
515
|
peerA.get_by_role("button", name="Save").click()
|
|
@@ -537,6 +535,11 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
|
|
|
537
535
|
expect(markersA).to_have_count(1)
|
|
538
536
|
expect(markersB).to_have_count(1)
|
|
539
537
|
|
|
538
|
+
# Make sure only one layer has been created on peer B
|
|
539
|
+
peerB.get_by_role("button", name="Open browser").click()
|
|
540
|
+
expect(peerB.locator("h5").get_by_text("Layer 1")).to_be_visible()
|
|
541
|
+
peerB.get_by_role("button", name="Close").click()
|
|
542
|
+
|
|
540
543
|
# Save and quit edit mode again
|
|
541
544
|
with peerA.expect_response(re.compile("./datalayer/create/.*")):
|
|
542
545
|
peerA.get_by_role("button", name="Save").click()
|
|
@@ -563,3 +566,96 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
|
|
|
563
566
|
peerA.get_by_role("button", name="Edit").click()
|
|
564
567
|
expect(markersA).to_have_count(2)
|
|
565
568
|
expect(markersB).to_have_count(2)
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
@pytest.mark.xdist_group(name="websockets")
|
|
572
|
+
def test_saved_datalayer_are_not_duplicated(new_page, asgi_live_server, tilelayer):
|
|
573
|
+
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
574
|
+
map.settings["properties"]["syncEnabled"] = True
|
|
575
|
+
map.save()
|
|
576
|
+
|
|
577
|
+
# Create one tab
|
|
578
|
+
peerA = new_page("Page A")
|
|
579
|
+
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
580
|
+
# Create a new datalayer
|
|
581
|
+
peerA.get_by_title("Manage layers").click()
|
|
582
|
+
peerA.get_by_title("Add a layer").click()
|
|
583
|
+
peerA.locator("#map").click(position={"x": 220, "y": 220})
|
|
584
|
+
# Save layer to the server, so now the datalayer exist on the server AND
|
|
585
|
+
# is still in the live operations of peer A
|
|
586
|
+
with peerA.expect_response(re.compile(".*/datalayer/create/.*")):
|
|
587
|
+
peerA.get_by_role("button", name="Save").click()
|
|
588
|
+
|
|
589
|
+
# Now load the map from another tab
|
|
590
|
+
peerB = new_page("Page B")
|
|
591
|
+
peerB.goto(peerA.url)
|
|
592
|
+
peerB.get_by_role("button", name="Open browser").click()
|
|
593
|
+
expect(peerB.get_by_text("Layer 1")).to_be_visible()
|
|
594
|
+
peerB.get_by_role("button", name="Edit").click()
|
|
595
|
+
peerA.wait_for_timeout(300) # Let the synchro roll on.
|
|
596
|
+
expect(peerB.get_by_text("Layer 1")).to_be_visible()
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
@pytest.mark.xdist_group(name="websockets")
|
|
600
|
+
def test_should_sync_saved_status(new_page, asgi_live_server, tilelayer):
|
|
601
|
+
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
602
|
+
map.settings["properties"]["syncEnabled"] = True
|
|
603
|
+
map.save()
|
|
604
|
+
|
|
605
|
+
# Create two tabs
|
|
606
|
+
peerA = new_page("Page A")
|
|
607
|
+
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
608
|
+
peerB = new_page("Page B")
|
|
609
|
+
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
610
|
+
|
|
611
|
+
# Create a new marker from peerA
|
|
612
|
+
peerA.get_by_title("Draw a marker").click()
|
|
613
|
+
peerA.locator("#map").click(position={"x": 220, "y": 220})
|
|
614
|
+
|
|
615
|
+
# Peer A should be in dirty state
|
|
616
|
+
expect(peerA.locator("body")).to_have_class(re.compile(".*umap-is-dirty.*"))
|
|
617
|
+
|
|
618
|
+
# Peer B should not be in dirty state
|
|
619
|
+
expect(peerB.locator("body")).not_to_have_class(re.compile(".*umap-is-dirty.*"))
|
|
620
|
+
|
|
621
|
+
# Create a new marker from peerB
|
|
622
|
+
peerB.get_by_title("Draw a marker").click()
|
|
623
|
+
peerB.locator("#map").click(position={"x": 200, "y": 250})
|
|
624
|
+
|
|
625
|
+
# Peer B should be in dirty state
|
|
626
|
+
expect(peerB.locator("body")).to_have_class(re.compile(".*umap-is-dirty.*"))
|
|
627
|
+
|
|
628
|
+
# Peer A should still be in dirty state
|
|
629
|
+
expect(peerA.locator("body")).to_have_class(re.compile(".*umap-is-dirty.*"))
|
|
630
|
+
|
|
631
|
+
# Save layer to the server from peerA
|
|
632
|
+
with peerA.expect_response(re.compile(".*/datalayer/create/.*")):
|
|
633
|
+
peerA.get_by_role("button", name="Save").click()
|
|
634
|
+
|
|
635
|
+
# Peer B should not be in dirty state
|
|
636
|
+
expect(peerB.locator("body")).not_to_have_class(re.compile(".*umap-is-dirty.*"))
|
|
637
|
+
|
|
638
|
+
# Peer A should not be in dirty state
|
|
639
|
+
expect(peerA.locator("body")).not_to_have_class(re.compile(".*umap-is-dirty.*"))
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
@pytest.mark.xdist_group(name="websockets")
|
|
643
|
+
def test_should_sync_line_on_escape(new_page, asgi_live_server, tilelayer):
|
|
644
|
+
map = MapFactory(name="sync", edit_status=Map.ANONYMOUS)
|
|
645
|
+
map.settings["properties"]["syncEnabled"] = True
|
|
646
|
+
map.save()
|
|
647
|
+
|
|
648
|
+
# Create two tabs
|
|
649
|
+
peerA = new_page("Page A")
|
|
650
|
+
peerA.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
651
|
+
peerB = new_page("Page B")
|
|
652
|
+
peerB.goto(f"{asgi_live_server.url}{map.get_absolute_url()}?edit")
|
|
653
|
+
|
|
654
|
+
# Create a new marker from peerA
|
|
655
|
+
peerA.get_by_title("Draw a polyline").click()
|
|
656
|
+
peerA.locator("#map").click(position={"x": 220, "y": 220})
|
|
657
|
+
peerA.locator("#map").click(position={"x": 200, "y": 200})
|
|
658
|
+
peerA.locator("body").press("Escape")
|
|
659
|
+
|
|
660
|
+
expect(peerA.locator("path")).to_have_count(1)
|
|
661
|
+
expect(peerB.locator("path")).to_have_count(1)
|
umap/utils.py
CHANGED
|
@@ -27,7 +27,10 @@ def _urls_for_js():
|
|
|
27
27
|
Return templated URLs prepared for javascript.
|
|
28
28
|
"""
|
|
29
29
|
urls = {}
|
|
30
|
-
|
|
30
|
+
modules = ["umap.urls"]
|
|
31
|
+
if settings.WEBSOCKET_ENABLED:
|
|
32
|
+
modules.append("umap.sync.app")
|
|
33
|
+
for module in modules:
|
|
31
34
|
names = _get_url_names(module)
|
|
32
35
|
urls.update(
|
|
33
36
|
dict(zip(names, [get_uri_template(url, module=module) for url in names]))
|
umap/views.py
CHANGED
|
@@ -1423,14 +1423,5 @@ class LoginPopupEnd(TemplateView):
|
|
|
1423
1423
|
def get(self, *args, **kwargs):
|
|
1424
1424
|
backend = self.request.session[BACKEND_SESSION_KEY]
|
|
1425
1425
|
if backend in settings.DEPRECATED_AUTHENTICATION_BACKENDS:
|
|
1426
|
-
name = backend.split(".")[-1]
|
|
1427
|
-
messages.error(
|
|
1428
|
-
self.request,
|
|
1429
|
-
_(
|
|
1430
|
-
"Using “%(name)s” to authenticate is deprecated. "
|
|
1431
|
-
"Please configure another provider in your profile page."
|
|
1432
|
-
)
|
|
1433
|
-
% {"name": name},
|
|
1434
|
-
)
|
|
1435
1426
|
return HttpResponseRedirect(reverse("user_profile"))
|
|
1436
1427
|
return super().get(*args, **kwargs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: umap-project
|
|
3
|
-
Version: 2.9.
|
|
3
|
+
Version: 2.9.1
|
|
4
4
|
Summary: Create maps with OpenStreetMap layers in a minute and embed them in your site.
|
|
5
5
|
Author-email: Yohan Boniface <yb@enix.org>
|
|
6
6
|
Maintainer-email: David Larlet <david@larlet.fr>
|
|
@@ -19,23 +19,23 @@ Requires-Python: >=3.10
|
|
|
19
19
|
Requires-Dist: django-agnocomplete==2.2.0
|
|
20
20
|
Requires-Dist: django-environ==0.12.0
|
|
21
21
|
Requires-Dist: django-probes==1.7.0
|
|
22
|
-
Requires-Dist: django==5.1.
|
|
22
|
+
Requires-Dist: django==5.1.6
|
|
23
23
|
Requires-Dist: pillow==11.1.0
|
|
24
24
|
Requires-Dist: psycopg==3.2.4
|
|
25
|
-
Requires-Dist: rcssmin==1.2.
|
|
25
|
+
Requires-Dist: rcssmin==1.2.1
|
|
26
26
|
Requires-Dist: requests==2.32.3
|
|
27
|
-
Requires-Dist: rjsmin==1.2.
|
|
27
|
+
Requires-Dist: rjsmin==1.2.4
|
|
28
28
|
Requires-Dist: social-auth-app-django==5.4.2
|
|
29
29
|
Requires-Dist: social-auth-core==4.5.4
|
|
30
30
|
Provides-Extra: dev
|
|
31
31
|
Requires-Dist: djlint==1.36.4; extra == 'dev'
|
|
32
32
|
Requires-Dist: hatch==1.14.0; extra == 'dev'
|
|
33
|
-
Requires-Dist: isort==
|
|
34
|
-
Requires-Dist: mkdocs-material==9.
|
|
35
|
-
Requires-Dist: mkdocs-static-i18n==1.
|
|
33
|
+
Requires-Dist: isort==6.0.1; extra == 'dev'
|
|
34
|
+
Requires-Dist: mkdocs-material==9.6.4; extra == 'dev'
|
|
35
|
+
Requires-Dist: mkdocs-static-i18n==1.3.0; extra == 'dev'
|
|
36
36
|
Requires-Dist: mkdocs==1.6.1; extra == 'dev'
|
|
37
|
-
Requires-Dist: pymdown-extensions==10.14.
|
|
38
|
-
Requires-Dist: ruff==0.9.
|
|
37
|
+
Requires-Dist: pymdown-extensions==10.14.3; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff==0.9.9; extra == 'dev'
|
|
39
39
|
Requires-Dist: vermin==1.6.0; extra == 'dev'
|
|
40
40
|
Provides-Extra: docker
|
|
41
41
|
Requires-Dist: uwsgi==2.0.28; extra == 'docker'
|
|
@@ -46,11 +46,11 @@ Requires-Dist: pydantic==2.10.6; extra == 'sync'
|
|
|
46
46
|
Requires-Dist: redis==5.2.1; extra == 'sync'
|
|
47
47
|
Provides-Extra: test
|
|
48
48
|
Requires-Dist: daphne==4.1.2; extra == 'test'
|
|
49
|
-
Requires-Dist: factory-boy==3.3.
|
|
50
|
-
Requires-Dist: moto[s3]==5.0.
|
|
49
|
+
Requires-Dist: factory-boy==3.3.3; extra == 'test'
|
|
50
|
+
Requires-Dist: moto[s3]==5.0.28; extra == 'test'
|
|
51
51
|
Requires-Dist: playwright>=1.39; extra == 'test'
|
|
52
|
-
Requires-Dist: pytest-django==4.
|
|
53
|
-
Requires-Dist: pytest-playwright==0.
|
|
52
|
+
Requires-Dist: pytest-django==4.10.0; extra == 'test'
|
|
53
|
+
Requires-Dist: pytest-playwright==0.7.0; extra == 'test'
|
|
54
54
|
Requires-Dist: pytest-rerunfailures==15.0; extra == 'test'
|
|
55
55
|
Requires-Dist: pytest-xdist<4,>=3.5.0; extra == 'test'
|
|
56
56
|
Requires-Dist: pytest==8.3.4; extra == 'test'
|