umap-project 3.0.4__py3-none-any.whl → 3.0.6__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.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/locale/el/LC_MESSAGES/django.mo +0 -0
- umap/locale/el/LC_MESSAGES/django.po +136 -56
- umap/locale/en/LC_MESSAGES/django.mo +0 -0
- umap/locale/en/LC_MESSAGES/django.po +18 -18
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +136 -56
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.po +143 -63
- umap/locale/nl/LC_MESSAGES/django.mo +0 -0
- umap/locale/nl/LC_MESSAGES/django.po +1 -1
- umap/models.py +1 -0
- umap/settings/base.py +1 -0
- umap/static/umap/css/bar.css +1 -1
- umap/static/umap/css/tooltip.css +13 -0
- umap/static/umap/js/modules/autocomplete.js +7 -8
- umap/static/umap/js/modules/browser.js +89 -94
- umap/static/umap/js/modules/caption.js +6 -4
- umap/static/umap/js/modules/data/features.js +1 -19
- umap/static/umap/js/modules/data/layer.js +100 -61
- umap/static/umap/js/modules/facets.js +1 -1
- umap/static/umap/js/modules/form/fields.js +1 -1
- umap/static/umap/js/modules/help.js +4 -0
- umap/static/umap/js/modules/importer.js +1 -1
- umap/static/umap/js/modules/managers.js +46 -0
- umap/static/umap/js/modules/permissions.js +1 -1
- umap/static/umap/js/modules/rendering/controls.js +251 -0
- umap/static/umap/js/modules/rendering/layers/heat.js +5 -0
- umap/static/umap/js/modules/rendering/map.js +21 -10
- umap/static/umap/js/modules/rendering/ui.js +0 -1
- umap/static/umap/js/modules/rules.js +56 -46
- umap/static/umap/js/modules/schema.js +5 -1
- umap/static/umap/js/modules/share.js +2 -2
- umap/static/umap/js/modules/slideshow.js +1 -1
- umap/static/umap/js/modules/sync/engine.js +23 -9
- umap/static/umap/js/modules/ui/bar.js +2 -2
- umap/static/umap/js/modules/ui/base.js +13 -0
- umap/static/umap/js/modules/umap.js +69 -111
- umap/static/umap/js/umap.controls.js +0 -310
- umap/static/umap/js/umap.core.js +0 -40
- umap/static/umap/locale/am_ET.js +8 -3
- umap/static/umap/locale/am_ET.json +8 -3
- umap/static/umap/locale/ar.js +8 -3
- umap/static/umap/locale/ar.json +8 -3
- umap/static/umap/locale/ast.js +8 -3
- umap/static/umap/locale/ast.json +8 -3
- umap/static/umap/locale/bg.js +8 -3
- umap/static/umap/locale/bg.json +8 -3
- umap/static/umap/locale/br.js +8 -3
- umap/static/umap/locale/br.json +8 -3
- umap/static/umap/locale/ca.js +20 -17
- umap/static/umap/locale/ca.json +20 -17
- umap/static/umap/locale/cs_CZ.js +5 -2
- umap/static/umap/locale/cs_CZ.json +5 -2
- umap/static/umap/locale/da.js +8 -3
- umap/static/umap/locale/da.json +8 -3
- umap/static/umap/locale/de.js +5 -2
- umap/static/umap/locale/de.json +5 -2
- umap/static/umap/locale/el.js +92 -87
- umap/static/umap/locale/el.json +92 -87
- umap/static/umap/locale/en.js +6 -2
- umap/static/umap/locale/en.json +6 -2
- umap/static/umap/locale/en_US.json +8 -3
- umap/static/umap/locale/es.js +18 -15
- umap/static/umap/locale/es.json +18 -15
- umap/static/umap/locale/et.js +8 -3
- umap/static/umap/locale/et.json +8 -3
- umap/static/umap/locale/eu.js +5 -2
- umap/static/umap/locale/eu.json +5 -2
- umap/static/umap/locale/fa_IR.js +5 -2
- umap/static/umap/locale/fa_IR.json +5 -2
- umap/static/umap/locale/fi.js +8 -3
- umap/static/umap/locale/fi.json +8 -3
- umap/static/umap/locale/fr.js +5 -2
- umap/static/umap/locale/fr.json +5 -2
- umap/static/umap/locale/gl.js +5 -2
- umap/static/umap/locale/gl.json +5 -2
- umap/static/umap/locale/he.js +8 -3
- umap/static/umap/locale/he.json +8 -3
- umap/static/umap/locale/hr.js +8 -3
- umap/static/umap/locale/hr.json +8 -3
- umap/static/umap/locale/hu.js +5 -2
- umap/static/umap/locale/hu.json +5 -2
- umap/static/umap/locale/id.js +8 -3
- umap/static/umap/locale/id.json +8 -3
- umap/static/umap/locale/is.js +8 -3
- umap/static/umap/locale/is.json +8 -3
- umap/static/umap/locale/it.js +5 -2
- umap/static/umap/locale/it.json +5 -2
- umap/static/umap/locale/ja.js +8 -3
- umap/static/umap/locale/ja.json +8 -3
- umap/static/umap/locale/ko.js +8 -3
- umap/static/umap/locale/ko.json +8 -3
- umap/static/umap/locale/lt.js +8 -3
- umap/static/umap/locale/lt.json +8 -3
- umap/static/umap/locale/ms.js +8 -3
- umap/static/umap/locale/ms.json +8 -3
- umap/static/umap/locale/nl.js +7 -4
- umap/static/umap/locale/nl.json +7 -4
- umap/static/umap/locale/no.js +8 -3
- umap/static/umap/locale/no.json +8 -3
- umap/static/umap/locale/pl.js +8 -3
- umap/static/umap/locale/pl.json +8 -3
- umap/static/umap/locale/pl_PL.json +8 -3
- umap/static/umap/locale/pt.js +5 -2
- umap/static/umap/locale/pt.json +5 -2
- umap/static/umap/locale/pt_BR.js +8 -3
- umap/static/umap/locale/pt_BR.json +8 -3
- umap/static/umap/locale/pt_PT.js +5 -2
- umap/static/umap/locale/pt_PT.json +5 -2
- umap/static/umap/locale/ro.js +8 -3
- umap/static/umap/locale/ro.json +8 -3
- umap/static/umap/locale/ru.js +8 -3
- umap/static/umap/locale/ru.json +8 -3
- umap/static/umap/locale/sk_SK.js +8 -3
- umap/static/umap/locale/sk_SK.json +8 -3
- umap/static/umap/locale/sl.js +8 -3
- umap/static/umap/locale/sl.json +8 -3
- umap/static/umap/locale/sr.js +8 -3
- umap/static/umap/locale/sr.json +8 -3
- umap/static/umap/locale/sv.js +8 -3
- umap/static/umap/locale/sv.json +8 -3
- umap/static/umap/locale/th_TH.js +8 -3
- umap/static/umap/locale/th_TH.json +8 -3
- umap/static/umap/locale/tr.js +8 -3
- umap/static/umap/locale/tr.json +8 -3
- umap/static/umap/locale/uk_UA.js +8 -3
- umap/static/umap/locale/uk_UA.json +8 -3
- umap/static/umap/locale/vi.js +8 -3
- umap/static/umap/locale/vi.json +8 -3
- umap/static/umap/locale/vi_VN.json +8 -3
- umap/static/umap/locale/zh.js +8 -3
- umap/static/umap/locale/zh.json +8 -3
- umap/static/umap/locale/zh_CN.json +8 -3
- umap/static/umap/locale/zh_TW.Big5.json +8 -3
- umap/static/umap/locale/zh_TW.js +5 -2
- umap/static/umap/locale/zh_TW.json +5 -2
- umap/static/umap/map.css +9 -31
- umap/static/umap/vendors/togeojson/togeojson.es.js +350 -177
- umap/static/umap/vendors/togeojson/togeojson.es.mjs.map +1 -1
- umap/templates/umap/design_system.html +355 -0
- umap/templates/umap/map_init.html +3 -1
- umap/tests/base.py +2 -2
- umap/tests/fixtures/heatmap_data.json +1044 -0
- umap/tests/integration/test_basics.py +9 -1
- umap/tests/integration/test_browser.py +3 -3
- umap/tests/integration/test_conditional_rules.py +2 -2
- umap/tests/integration/test_datalayer.py +0 -1
- umap/tests/integration/test_edit_map.py +7 -7
- umap/tests/integration/test_facets_browser.py +2 -2
- umap/tests/integration/test_heatmap.py +41 -0
- umap/tests/integration/test_import.py +58 -1
- umap/tests/integration/test_map.py +7 -8
- umap/tests/integration/test_optimistic_merge.py +12 -4
- umap/tests/integration/test_querystring.py +1 -1
- umap/tests/integration/test_remote_data.py +79 -0
- umap/tests/integration/test_websocket_sync.py +2 -2
- umap/urls.py +1 -0
- umap/views.py +8 -1
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/METADATA +11 -11
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/RECORD +164 -158
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/WHEEL +0 -0
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/entry_points.txt +0 -0
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/licenses/LICENSE +0 -0
|
@@ -61,13 +61,21 @@ def test_cannot_put_script_tag_in_datalayer_name_or_description(
|
|
|
61
61
|
page.locator(".umap-field-description textarea").fill(
|
|
62
62
|
'<p>before <script>alert("attack")</script> after</p>'
|
|
63
63
|
)
|
|
64
|
-
page.
|
|
64
|
+
page.wait_for_timeout(300) # Wait for debounce
|
|
65
|
+
with page.expect_response(re.compile(".*/datalayer/create/.*")):
|
|
66
|
+
page.get_by_role("button", name="Save").click()
|
|
65
67
|
page.get_by_role("button", name="About").click()
|
|
66
68
|
# Title should contain raw HTML (we are using textContent)
|
|
67
69
|
expect(page.get_by_text('<script>alert("attack")</script>')).to_be_visible()
|
|
68
70
|
# Description should contain escaped HTML
|
|
69
71
|
expect(page.get_by_text("before after")).to_be_visible()
|
|
70
72
|
|
|
73
|
+
# Reload the map
|
|
74
|
+
page.goto(f"{live_server.url}{openmap.get_absolute_url()}")
|
|
75
|
+
page.get_by_role("button", name="About").click()
|
|
76
|
+
expect(page.get_by_text('<script>alert("attack")</script>')).to_be_visible()
|
|
77
|
+
expect(page.get_by_text("before after")).to_be_visible()
|
|
78
|
+
|
|
71
79
|
|
|
72
80
|
def test_login_from_map_page(live_server, page, tilelayer, settings, user, context):
|
|
73
81
|
settings.ENABLE_ACCOUNT_LOGIN = True
|
|
@@ -465,19 +465,19 @@ def test_main_toolbox_toggle_all_layers(live_server, map, page):
|
|
|
465
465
|
expect(page.locator(".datalayer.off")).to_have_count(1)
|
|
466
466
|
|
|
467
467
|
# Click on button
|
|
468
|
-
page.locator(".umap-browser
|
|
468
|
+
page.locator(".umap-browser").get_by_title("Show/hide all layers").click()
|
|
469
469
|
# Should have hidden the two other layers
|
|
470
470
|
expect(page.locator(".datalayer.off")).to_have_count(3)
|
|
471
471
|
expect(markers).to_have_count(0)
|
|
472
472
|
|
|
473
473
|
# Click again
|
|
474
|
-
page.locator(".umap-browser
|
|
474
|
+
page.locator(".umap-browser").get_by_title("Show/hide all layers").click()
|
|
475
475
|
# Should shown all layers
|
|
476
476
|
expect(page.locator(".datalayer.off")).to_have_count(0)
|
|
477
477
|
expect(markers).to_have_count(3)
|
|
478
478
|
|
|
479
479
|
# Click again
|
|
480
|
-
page.locator(".umap-browser
|
|
480
|
+
page.locator(".umap-browser").get_by_title("Show/hide all layers").click()
|
|
481
481
|
# Should hidden again all layers
|
|
482
482
|
expect(page.locator(".datalayer.off")).to_have_count(3)
|
|
483
483
|
expect(markers).to_have_count(0)
|
|
@@ -281,10 +281,10 @@ def test_can_deactive_rule_from_list(live_server, page, openmap):
|
|
|
281
281
|
page.get_by_role("button", name="Edit").click()
|
|
282
282
|
page.get_by_role("button", name="Map advanced properties").click()
|
|
283
283
|
page.get_by_text("Conditional style rules").click()
|
|
284
|
-
page.get_by_role("button", name="
|
|
284
|
+
page.get_by_role("button", name="Toggle rule").click()
|
|
285
285
|
colors = getColors(markers)
|
|
286
286
|
assert colors.count("rgb(240, 248, 255)") == 0
|
|
287
|
-
page.get_by_role("button", name="
|
|
287
|
+
page.get_by_role("button", name="Toggle rule").click()
|
|
288
288
|
colors = getColors(markers)
|
|
289
289
|
assert colors.count("rgb(240, 248, 255)") == 3
|
|
290
290
|
|
|
@@ -175,14 +175,14 @@ def test_sortkey_impacts_datalayerindex(map, live_server, page):
|
|
|
175
175
|
|
|
176
176
|
# By default, features are sorted by name (Third, Second, First)
|
|
177
177
|
page.get_by_role("button", name="Open browser").click()
|
|
178
|
-
page.
|
|
178
|
+
page.locator(".umap-browser .datalayer-name").click()
|
|
179
179
|
|
|
180
180
|
first_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(0)
|
|
181
181
|
second_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(1)
|
|
182
182
|
third_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(2)
|
|
183
|
-
assert "X Third" == first_listed_feature.text_content()
|
|
184
|
-
assert "Y Second" == second_listed_feature.text_content()
|
|
185
|
-
assert "Z First" == third_listed_feature.text_content()
|
|
183
|
+
assert "X Third" == first_listed_feature.text_content().strip()
|
|
184
|
+
assert "Y Second" == second_listed_feature.text_content().strip()
|
|
185
|
+
assert "Z First" == third_listed_feature.text_content().strip()
|
|
186
186
|
|
|
187
187
|
# Change the default sortkey to be "key"
|
|
188
188
|
page.get_by_role("button", name="Edit").click()
|
|
@@ -201,9 +201,9 @@ def test_sortkey_impacts_datalayerindex(map, live_server, page):
|
|
|
201
201
|
first_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(0)
|
|
202
202
|
second_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(1)
|
|
203
203
|
third_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(2)
|
|
204
|
-
assert "Z First" == first_listed_feature.text_content()
|
|
205
|
-
assert "Y Second" == second_listed_feature.text_content()
|
|
206
|
-
assert "X Third" == third_listed_feature.text_content()
|
|
204
|
+
assert "Z First" == first_listed_feature.text_content().strip()
|
|
205
|
+
assert "Y Second" == second_listed_feature.text_content().strip()
|
|
206
|
+
assert "X Third" == third_listed_feature.text_content().strip()
|
|
207
207
|
|
|
208
208
|
|
|
209
209
|
def test_hover_tooltip_setting_should_be_persistent(live_server, map, page):
|
|
@@ -243,7 +243,7 @@ def test_facets_search_are_persistent_when_closing_panel(live_server, page, map)
|
|
|
243
243
|
|
|
244
244
|
# Now let's filter
|
|
245
245
|
odd.click()
|
|
246
|
-
expect(page.locator("summary")).to_have_attribute("data-badge", " ")
|
|
246
|
+
expect(page.locator(".filters summary")).to_have_attribute("data-badge", " ")
|
|
247
247
|
expect(page.locator(".umap-control-browse")).to_have_attribute("data-badge", " ")
|
|
248
248
|
expect(markers).to_have_count(2)
|
|
249
249
|
expect(panel.get_by_text("Point 2")).to_be_hidden()
|
|
@@ -264,7 +264,7 @@ def test_facets_search_are_persistent_when_closing_panel(live_server, page, map)
|
|
|
264
264
|
expect(panel.get_by_text("Point 3")).to_be_visible()
|
|
265
265
|
|
|
266
266
|
# Close panel
|
|
267
|
-
expect(panel.locator("summary")).to_have_attribute("data-badge", " ")
|
|
267
|
+
expect(panel.locator(".filters summary")).to_have_attribute("data-badge", " ")
|
|
268
268
|
expect(page.locator(".umap-control-browse")).to_have_attribute("data-badge", " ")
|
|
269
269
|
panel.get_by_role("button", name="Close").click()
|
|
270
270
|
page.get_by_role("button", name="Open browser").click()
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
from playwright.sync_api import expect
|
|
6
|
+
|
|
7
|
+
from ..base import DataLayerFactory
|
|
8
|
+
|
|
9
|
+
pytestmark = pytest.mark.django_db
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_heatmap(map, live_server, page):
|
|
13
|
+
path = Path(__file__).parent.parent / "fixtures/heatmap_data.json"
|
|
14
|
+
data = json.loads(path.read_text())
|
|
15
|
+
DataLayerFactory(data=data, map=map)
|
|
16
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
|
17
|
+
expect(page.locator("canvas.leaflet-heatmap-layer")).to_be_visible()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_can_create_heatmap_after_import(live_server, page, tilelayer, settings):
|
|
21
|
+
settings.UMAP_ALLOW_ANONYMOUS = True
|
|
22
|
+
page.goto(f"{live_server.url}/en/map/new")
|
|
23
|
+
page.get_by_title("Import data").click()
|
|
24
|
+
file_input = page.locator("input[type='file']")
|
|
25
|
+
with page.expect_file_chooser() as fc_info:
|
|
26
|
+
file_input.click()
|
|
27
|
+
file_chooser = fc_info.value
|
|
28
|
+
path = Path(__file__).parent.parent / "fixtures/heatmap_data.json"
|
|
29
|
+
file_chooser.set_files(path)
|
|
30
|
+
page.get_by_role("button", name="Import data", exact=True).click()
|
|
31
|
+
page.get_by_role("button", name="Manage layers").click()
|
|
32
|
+
page.get_by_role("button", name="Edit", exact=True).click()
|
|
33
|
+
page.get_by_role("combobox").select_option("Heat")
|
|
34
|
+
page.get_by_role("button", name="Save draft").click()
|
|
35
|
+
expect(page.locator("canvas.leaflet-heatmap-layer")).to_be_visible()
|
|
36
|
+
|
|
37
|
+
# Test we can delete it and save
|
|
38
|
+
page.get_by_text("Advanced actions").click()
|
|
39
|
+
page.get_by_role("button", name="Delete").click()
|
|
40
|
+
page.get_by_role("button", name="Save draft").click()
|
|
41
|
+
expect(page.locator("canvas.leaflet-heatmap-layer")).to_be_hidden()
|
|
@@ -435,6 +435,63 @@ def test_import_geometry_collection(live_server, page, tilelayer):
|
|
|
435
435
|
expect(paths).to_have_count(2)
|
|
436
436
|
|
|
437
437
|
|
|
438
|
+
def test_import_geometry_collection_in_feature(live_server, page, tilelayer):
|
|
439
|
+
data = {
|
|
440
|
+
"type": "Feature",
|
|
441
|
+
"properties": {"name": "foobar"},
|
|
442
|
+
"geometry": {
|
|
443
|
+
"type": "GeometryCollection",
|
|
444
|
+
"geometries": [
|
|
445
|
+
{"type": "Point", "coordinates": [-80.6608, 35.0493]},
|
|
446
|
+
{
|
|
447
|
+
"type": "Polygon",
|
|
448
|
+
"coordinates": [
|
|
449
|
+
[
|
|
450
|
+
[-80.6645, 35.0449],
|
|
451
|
+
[-80.6634, 35.0460],
|
|
452
|
+
[-80.6625, 35.0455],
|
|
453
|
+
[-80.6638, 35.0442],
|
|
454
|
+
[-80.6645, 35.0449],
|
|
455
|
+
]
|
|
456
|
+
],
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
"type": "LineString",
|
|
460
|
+
"coordinates": [
|
|
461
|
+
[-80.66237, 35.05950],
|
|
462
|
+
[-80.66269, 35.05926],
|
|
463
|
+
[-80.66284, 35.05893],
|
|
464
|
+
[-80.66308, 35.05833],
|
|
465
|
+
[-80.66385, 35.04387],
|
|
466
|
+
[-80.66303, 35.04371],
|
|
467
|
+
],
|
|
468
|
+
},
|
|
469
|
+
],
|
|
470
|
+
},
|
|
471
|
+
}
|
|
472
|
+
page.goto(f"{live_server.url}/map/new/")
|
|
473
|
+
page.get_by_title("Open browser").click()
|
|
474
|
+
layers = page.locator(".umap-browser .datalayer")
|
|
475
|
+
markers = page.locator(".leaflet-marker-icon")
|
|
476
|
+
paths = page.locator("path")
|
|
477
|
+
expect(markers).to_have_count(0)
|
|
478
|
+
expect(paths).to_have_count(0)
|
|
479
|
+
expect(layers).to_have_count(0)
|
|
480
|
+
button = page.get_by_title("Import data")
|
|
481
|
+
expect(button).to_be_visible()
|
|
482
|
+
button.click()
|
|
483
|
+
textarea = page.locator(".umap-import textarea")
|
|
484
|
+
textarea.fill(json.dumps(data))
|
|
485
|
+
page.locator('select[name="format"]').select_option("geojson")
|
|
486
|
+
page.get_by_role("button", name="Import data", exact=True).click()
|
|
487
|
+
# A layer has been created
|
|
488
|
+
expect(layers).to_have_count(1)
|
|
489
|
+
expect(markers).to_have_count(1)
|
|
490
|
+
expect(paths).to_have_count(2)
|
|
491
|
+
# Geometries are treated as separate features.
|
|
492
|
+
expect(page.get_by_text("foobar")).to_have_count(3)
|
|
493
|
+
|
|
494
|
+
|
|
438
495
|
def test_import_multipolygon(live_server, page, tilelayer):
|
|
439
496
|
data = {
|
|
440
497
|
"type": "Feature",
|
|
@@ -847,7 +904,7 @@ def test_import_from_datasets(page, live_server, tilelayer, settings):
|
|
|
847
904
|
page.get_by_role("button", name="Import data", exact=True).click()
|
|
848
905
|
expect(page.locator(".leaflet-marker-icon")).to_be_visible()
|
|
849
906
|
page.get_by_role("button", name="Open browser").click()
|
|
850
|
-
expect(page.locator("
|
|
907
|
+
expect(page.locator("summary").get_by_text("Good data")).to_be_visible()
|
|
851
908
|
|
|
852
909
|
|
|
853
910
|
def test_import_osm_relation(tilelayer, live_server, page):
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import re
|
|
3
2
|
|
|
4
3
|
import pytest
|
|
@@ -46,7 +45,7 @@ def test_default_view_without_datalayer_should_use_default_center(
|
|
|
46
45
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?onLoadPanel=datalayers")
|
|
47
46
|
# Hash is defined, so map is initialized
|
|
48
47
|
expect(page).to_have_url(re.compile(r".*#7/48\..+/13\..+"))
|
|
49
|
-
layers = page.locator(".umap-browser .datalayer
|
|
48
|
+
layers = page.locator(".umap-browser .datalayer summary")
|
|
50
49
|
expect(layers).to_have_count(1)
|
|
51
50
|
|
|
52
51
|
|
|
@@ -60,7 +59,7 @@ def test_default_view_latest_without_datalayer_should_use_default_center(
|
|
|
60
59
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?onLoadPanel=datalayers")
|
|
61
60
|
# Hash is defined, so map is initialized
|
|
62
61
|
expect(page).to_have_url(re.compile(r".*#7/48\..+/13\..+"))
|
|
63
|
-
layers = page.locator(".umap-browser .datalayer
|
|
62
|
+
layers = page.locator(".umap-browser .datalayer summary")
|
|
64
63
|
expect(layers).to_have_count(1)
|
|
65
64
|
|
|
66
65
|
|
|
@@ -74,7 +73,7 @@ def test_default_view_data_without_datalayer_should_use_default_center(
|
|
|
74
73
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?onLoadPanel=datalayers")
|
|
75
74
|
# Hash is defined, so map is initialized
|
|
76
75
|
expect(page).to_have_url(re.compile(r".*#7/48\..+/13\..+"))
|
|
77
|
-
layers = page.locator(".umap-browser .datalayer
|
|
76
|
+
layers = page.locator(".umap-browser .datalayer summary")
|
|
78
77
|
expect(layers).to_have_count(1)
|
|
79
78
|
|
|
80
79
|
|
|
@@ -84,7 +83,7 @@ def test_default_view_latest_with_marker(map, live_server, datalayer, page):
|
|
|
84
83
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?onLoadPanel=datalayers")
|
|
85
84
|
# Hash is defined, so map is initialized
|
|
86
85
|
expect(page).to_have_url(re.compile(r".*#7/48\..+/14\..+"))
|
|
87
|
-
layers = page.locator(".umap-browser .datalayer
|
|
86
|
+
layers = page.locator(".umap-browser .datalayer summary")
|
|
88
87
|
expect(layers).to_have_count(1)
|
|
89
88
|
expect(page.locator(".leaflet-popup")).to_be_visible()
|
|
90
89
|
|
|
@@ -113,7 +112,7 @@ def test_default_view_latest_with_line(map, live_server, page):
|
|
|
113
112
|
map.save()
|
|
114
113
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?onLoadPanel=datalayers")
|
|
115
114
|
expect(page).to_have_url(re.compile(r".*#8/48\..+/2\..+"))
|
|
116
|
-
layers = page.locator(".umap-browser .datalayer
|
|
115
|
+
layers = page.locator(".umap-browser .datalayer summary")
|
|
117
116
|
expect(layers).to_have_count(1)
|
|
118
117
|
|
|
119
118
|
|
|
@@ -144,7 +143,7 @@ def test_default_view_latest_with_polygon(map, live_server, page):
|
|
|
144
143
|
map.save()
|
|
145
144
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?onLoadPanel=datalayers")
|
|
146
145
|
expect(page).to_have_url(re.compile(r".*#8/48\..+/2\..+"))
|
|
147
|
-
layers = page.locator(".umap-browser .datalayer
|
|
146
|
+
layers = page.locator(".umap-browser .datalayer summary")
|
|
148
147
|
expect(layers).to_have_count(1)
|
|
149
148
|
|
|
150
149
|
|
|
@@ -173,7 +172,7 @@ def test_remote_layer_should_not_be_used_as_datalayer_for_created_features(
|
|
|
173
172
|
toggle = page.get_by_role("button", name="Open browser")
|
|
174
173
|
expect(toggle).to_be_visible()
|
|
175
174
|
toggle.click()
|
|
176
|
-
layers = page.locator(".umap-browser .datalayer
|
|
175
|
+
layers = page.locator(".umap-browser .datalayer summary")
|
|
177
176
|
expect(layers).to_have_count(1)
|
|
178
177
|
map_el = page.locator("#map")
|
|
179
178
|
add_marker = page.get_by_title("Draw a marker")
|
|
@@ -50,6 +50,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
50
50
|
"editMode": "advanced",
|
|
51
51
|
"inCaption": True,
|
|
52
52
|
"id": str(datalayer.pk),
|
|
53
|
+
"rank": 0,
|
|
54
|
+
"remoteData": {},
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
# Now navigate to this map from another tab
|
|
@@ -87,6 +89,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
87
89
|
"inCaption": True,
|
|
88
90
|
"editMode": "advanced",
|
|
89
91
|
"id": str(datalayer.pk),
|
|
92
|
+
"rank": 0,
|
|
93
|
+
"remoteData": {},
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
# Now create another marker in the first tab
|
|
@@ -105,7 +109,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
105
109
|
"inCaption": True,
|
|
106
110
|
"editMode": "advanced",
|
|
107
111
|
"id": str(datalayer.pk),
|
|
108
|
-
"
|
|
112
|
+
"rank": 0,
|
|
113
|
+
"remoteData": {},
|
|
109
114
|
}
|
|
110
115
|
|
|
111
116
|
# And again
|
|
@@ -124,7 +129,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
124
129
|
"inCaption": True,
|
|
125
130
|
"editMode": "advanced",
|
|
126
131
|
"id": str(datalayer.pk),
|
|
127
|
-
"
|
|
132
|
+
"rank": 0,
|
|
133
|
+
"remoteData": {},
|
|
128
134
|
}
|
|
129
135
|
expect(marker_pane_p1).to_have_count(4)
|
|
130
136
|
|
|
@@ -145,7 +151,8 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
145
151
|
"inCaption": True,
|
|
146
152
|
"editMode": "advanced",
|
|
147
153
|
"id": str(datalayer.pk),
|
|
148
|
-
"
|
|
154
|
+
"rank": 0,
|
|
155
|
+
"remoteData": {},
|
|
149
156
|
}
|
|
150
157
|
expect(marker_pane_p2).to_have_count(5)
|
|
151
158
|
|
|
@@ -271,7 +278,8 @@ def test_same_second_edit_doesnt_conflict(context, live_server, tilelayer):
|
|
|
271
278
|
"inCaption": True,
|
|
272
279
|
"editMode": "advanced",
|
|
273
280
|
"id": str(datalayer.pk),
|
|
274
|
-
"
|
|
281
|
+
"rank": 0,
|
|
282
|
+
"remoteData": {},
|
|
275
283
|
}
|
|
276
284
|
|
|
277
285
|
|
|
@@ -63,5 +63,5 @@ def test_zoom_control(map, live_server, datalayer, page):
|
|
|
63
63
|
expect(control).to_be_visible()
|
|
64
64
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?zoomControl=null")
|
|
65
65
|
expect(control).to_be_hidden()
|
|
66
|
-
page.
|
|
66
|
+
page.locator(".umap-control-more").click()
|
|
67
67
|
expect(control).to_be_visible()
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from playwright.sync_api import expect
|
|
2
|
+
|
|
3
|
+
from umap.models import Map
|
|
4
|
+
|
|
5
|
+
from ..base import DataLayerFactory
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_dynamic_remote_data(page, live_server, tilelayer, map):
|
|
9
|
+
data = [
|
|
10
|
+
{
|
|
11
|
+
"type": "FeatureCollection",
|
|
12
|
+
"features": [
|
|
13
|
+
{
|
|
14
|
+
"type": "Feature",
|
|
15
|
+
"properties": {"name": "Point 2"},
|
|
16
|
+
"geometry": {
|
|
17
|
+
"type": "Point",
|
|
18
|
+
"coordinates": [4.3375, 11.2707],
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"type": "FeatureCollection",
|
|
25
|
+
"features": [
|
|
26
|
+
{
|
|
27
|
+
"type": "Feature",
|
|
28
|
+
"properties": {"name": "Point 1"},
|
|
29
|
+
"geometry": {
|
|
30
|
+
"type": "Point",
|
|
31
|
+
"coordinates": [4.3375, 12.2707],
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
def handle(route):
|
|
39
|
+
route.fulfill(json=data.pop())
|
|
40
|
+
|
|
41
|
+
settings = {
|
|
42
|
+
"remoteData": {
|
|
43
|
+
"url": "https://remote.org/data.json",
|
|
44
|
+
"format": "geojson",
|
|
45
|
+
"dynamic": True,
|
|
46
|
+
},
|
|
47
|
+
"showLabel": True,
|
|
48
|
+
}
|
|
49
|
+
DataLayerFactory(map=map, settings=settings)
|
|
50
|
+
map.edit_status = Map.ANONYMOUS
|
|
51
|
+
map.settings["properties"]["zoom"] = 6
|
|
52
|
+
map.settings["geometry"] = {
|
|
53
|
+
"type": "Point",
|
|
54
|
+
"coordinates": [5, 12],
|
|
55
|
+
}
|
|
56
|
+
map.save()
|
|
57
|
+
|
|
58
|
+
# Intercept the route to the proxy
|
|
59
|
+
page.route("https://remote.org/data.json", handle)
|
|
60
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
|
61
|
+
|
|
62
|
+
expect(page.get_by_role("tooltip", name="Point 1")).to_be_visible()
|
|
63
|
+
|
|
64
|
+
# Now drag the map
|
|
65
|
+
map_el = page.locator("#map")
|
|
66
|
+
map_el.drag_to(
|
|
67
|
+
map_el,
|
|
68
|
+
source_position={"x": 100, "y": 100},
|
|
69
|
+
target_position={"x": 110, "y": 110},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
expect(page.get_by_role("tooltip", name="Point 2")).to_be_visible()
|
|
73
|
+
# Needed otherwise it found two (!) tooltip with name "Point 1"…
|
|
74
|
+
page.wait_for_timeout(300)
|
|
75
|
+
expect(page.get_by_role("tooltip", name="Point 1")).to_be_hidden()
|
|
76
|
+
|
|
77
|
+
# Map must not be dirty
|
|
78
|
+
page.get_by_role("button", name="Edit").click()
|
|
79
|
+
expect(page.locator(".edit-undo")).to_be_disabled()
|
|
@@ -397,7 +397,7 @@ def test_should_sync_datalayers(new_page, asgi_live_server, tilelayer):
|
|
|
397
397
|
|
|
398
398
|
# Make sure this new marker is in Layer 2 for peerB
|
|
399
399
|
# Show features for this layer in the brower.
|
|
400
|
-
peerB.
|
|
400
|
+
peerB.locator("summary").filter(has_text="Layer 2").click()
|
|
401
401
|
expect(peerB.locator("li").filter(has_text="Layer 2")).to_be_visible()
|
|
402
402
|
peerB.locator(".panel.left").get_by_role("button", name="Show/hide layer").nth(
|
|
403
403
|
1
|
|
@@ -534,7 +534,7 @@ def test_create_and_sync_map(new_page, asgi_live_server, tilelayer, login, user)
|
|
|
534
534
|
|
|
535
535
|
# Make sure only one layer has been created on peer B
|
|
536
536
|
peerB.get_by_role("button", name="Open browser").click()
|
|
537
|
-
expect(peerB.locator("
|
|
537
|
+
expect(peerB.locator("summary").get_by_text("Layer 1")).to_be_visible()
|
|
538
538
|
peerB.get_by_role("button", name="Close").click()
|
|
539
539
|
|
|
540
540
|
# Save and quit edit mode again
|
umap/urls.py
CHANGED
|
@@ -205,6 +205,7 @@ urlpatterns += i18n_patterns(
|
|
|
205
205
|
)
|
|
206
206
|
urlpatterns += (
|
|
207
207
|
path("stats/", cache_page(60 * 60)(views.stats), name="stats"),
|
|
208
|
+
path("design_system/", views.design_system, name="design_system"),
|
|
208
209
|
path(
|
|
209
210
|
"favicon.ico",
|
|
210
211
|
cache_control(max_age=60 * 60 * 24, immutable=True, public=True)(
|
umap/views.py
CHANGED
|
@@ -668,7 +668,7 @@ class MapDetailMixin(SessionMixin):
|
|
|
668
668
|
geojson["properties"] = {}
|
|
669
669
|
geojson["properties"].update(properties)
|
|
670
670
|
geojson["properties"]["datalayers"] = self.get_datalayers()
|
|
671
|
-
context["map_settings"] = json_dumps(geojson, indent=settings.DEBUG)
|
|
671
|
+
context["map_settings"] = json_dumps(geojson, indent=settings.DEBUG or None)
|
|
672
672
|
self.set_preconnect(geojson["properties"], context)
|
|
673
673
|
return context
|
|
674
674
|
|
|
@@ -1410,6 +1410,13 @@ def stats(request):
|
|
|
1410
1410
|
)
|
|
1411
1411
|
|
|
1412
1412
|
|
|
1413
|
+
class DesignSystem(TemplateView):
|
|
1414
|
+
template_name = "umap/design_system.html"
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
design_system = DesignSystem.as_view()
|
|
1418
|
+
|
|
1419
|
+
|
|
1413
1420
|
@require_GET
|
|
1414
1421
|
@cache_control(max_age=60 * 60 * 24, immutable=True, public=True) # One day.
|
|
1415
1422
|
def webmanifest(request):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: umap-project
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.6
|
|
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,9 +19,9 @@ 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
|
|
23
|
-
Requires-Dist: pillow==11.1
|
|
24
|
-
Requires-Dist: psycopg==3.2.
|
|
22
|
+
Requires-Dist: django==5.2.1
|
|
23
|
+
Requires-Dist: pillow==11.2.1
|
|
24
|
+
Requires-Dist: psycopg==3.2.8
|
|
25
25
|
Requires-Dist: rcssmin==1.2.1
|
|
26
26
|
Requires-Dist: requests==2.32.3
|
|
27
27
|
Requires-Dist: rjsmin==1.2.4
|
|
@@ -31,26 +31,26 @@ Provides-Extra: dev
|
|
|
31
31
|
Requires-Dist: djlint==1.36.4; extra == 'dev'
|
|
32
32
|
Requires-Dist: hatch==1.14.1; extra == 'dev'
|
|
33
33
|
Requires-Dist: isort==6.0.1; extra == 'dev'
|
|
34
|
-
Requires-Dist: mkdocs-material==9.6.
|
|
34
|
+
Requires-Dist: mkdocs-material==9.6.12; extra == 'dev'
|
|
35
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.
|
|
38
|
-
Requires-Dist: ruff==0.11.
|
|
37
|
+
Requires-Dist: pymdown-extensions==10.15; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff==0.11.9; extra == 'dev'
|
|
39
39
|
Requires-Dist: vermin==1.6.0; extra == 'dev'
|
|
40
40
|
Provides-Extra: docker
|
|
41
|
-
Requires-Dist: uvicorn==0.34.
|
|
41
|
+
Requires-Dist: uvicorn==0.34.2; extra == 'docker'
|
|
42
42
|
Provides-Extra: s3
|
|
43
43
|
Requires-Dist: django-storages[s3]==1.14.6; extra == 's3'
|
|
44
44
|
Provides-Extra: sync
|
|
45
|
-
Requires-Dist: pydantic==2.11.
|
|
45
|
+
Requires-Dist: pydantic==2.11.4; extra == 'sync'
|
|
46
46
|
Requires-Dist: redis==5.2.1; extra == 'sync'
|
|
47
47
|
Requires-Dist: websockets==15.0.1; extra == 'sync'
|
|
48
48
|
Provides-Extra: test
|
|
49
49
|
Requires-Dist: daphne==4.1.2; extra == 'test'
|
|
50
50
|
Requires-Dist: factory-boy==3.3.3; extra == 'test'
|
|
51
|
-
Requires-Dist: moto[s3]==5.1.
|
|
51
|
+
Requires-Dist: moto[s3]==5.1.4; extra == 'test'
|
|
52
52
|
Requires-Dist: playwright>=1.39; extra == 'test'
|
|
53
|
-
Requires-Dist: pytest-django==4.
|
|
53
|
+
Requires-Dist: pytest-django==4.11.1; extra == 'test'
|
|
54
54
|
Requires-Dist: pytest-playwright==0.7.0; extra == 'test'
|
|
55
55
|
Requires-Dist: pytest-rerunfailures==15.0; extra == 'test'
|
|
56
56
|
Requires-Dist: pytest-xdist<4,>=3.5.0; extra == 'test'
|