umap-project 2.6.3__py3-none-any.whl → 2.7.0__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.

Files changed (137) hide show
  1. umap/__init__.py +1 -1
  2. umap/admin.py +64 -1
  3. umap/asgi.py +15 -0
  4. umap/context_processors.py +1 -0
  5. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/cs_CZ/LC_MESSAGES/django.po +96 -92
  7. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/de/LC_MESSAGES/django.po +19 -18
  9. umap/locale/en/LC_MESSAGES/django.po +47 -43
  10. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  11. umap/locale/es/LC_MESSAGES/django.po +134 -128
  12. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  13. umap/locale/fr/LC_MESSAGES/django.po +51 -47
  14. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  15. umap/locale/pt/LC_MESSAGES/django.po +64 -60
  16. umap/management/commands/clean_tilelayer.py +152 -0
  17. umap/management/commands/purge_purgatory.py +28 -0
  18. umap/models.py +27 -2
  19. umap/settings/base.py +3 -1
  20. umap/static/umap/base.css +4 -4
  21. umap/static/umap/css/contextmenu.css +6 -1
  22. umap/static/umap/css/icon.css +7 -2
  23. umap/static/umap/css/importers.css +4 -0
  24. umap/static/umap/img/16-white.svg +9 -2
  25. umap/static/umap/img/16.svg +1 -181
  26. umap/static/umap/img/24-white.svg +1 -0
  27. umap/static/umap/img/24.svg +1 -0
  28. umap/static/umap/img/importers/cadastrefr.svg +23 -0
  29. umap/static/umap/img/source/16-white.svg +10 -3
  30. umap/static/umap/img/source/16.svg +753 -197
  31. umap/static/umap/img/source/24-white.svg +3 -2
  32. umap/static/umap/img/source/24.svg +3 -2
  33. umap/static/umap/js/modules/autocomplete.js +7 -3
  34. umap/static/umap/js/modules/browser.js +54 -1
  35. umap/static/umap/js/modules/caption.js +16 -5
  36. umap/static/umap/js/modules/data/features.js +176 -2
  37. umap/static/umap/js/modules/data/layer.js +57 -40
  38. umap/static/umap/js/modules/formatter.js +3 -2
  39. umap/static/umap/js/modules/global.js +2 -0
  40. umap/static/umap/js/modules/importer.js +3 -0
  41. umap/static/umap/js/modules/importers/cadastrefr.js +62 -0
  42. umap/static/umap/js/modules/importers/communesfr.js +15 -3
  43. umap/static/umap/js/modules/permissions.js +123 -93
  44. umap/static/umap/js/modules/rendering/layers/classified.js +2 -0
  45. umap/static/umap/js/modules/rendering/ui.js +60 -213
  46. umap/static/umap/js/modules/share.js +1 -3
  47. umap/static/umap/js/modules/slideshow.js +1 -1
  48. umap/static/umap/js/modules/sync/engine.js +371 -14
  49. umap/static/umap/js/modules/sync/hlc.js +106 -0
  50. umap/static/umap/js/modules/sync/updaters.js +18 -6
  51. umap/static/umap/js/modules/sync/websocket.js +1 -1
  52. umap/static/umap/js/modules/tableeditor.js +1 -1
  53. umap/static/umap/js/modules/ui/base.js +2 -2
  54. umap/static/umap/js/modules/ui/contextmenu.js +51 -18
  55. umap/static/umap/js/modules/urls.js +5 -1
  56. umap/static/umap/js/modules/utils.js +28 -4
  57. umap/static/umap/js/umap.controls.js +73 -52
  58. umap/static/umap/js/umap.core.js +3 -3
  59. umap/static/umap/js/umap.forms.js +3 -1
  60. umap/static/umap/js/umap.js +115 -124
  61. umap/static/umap/locale/br.js +13 -4
  62. umap/static/umap/locale/br.json +13 -4
  63. umap/static/umap/locale/ca.js +28 -15
  64. umap/static/umap/locale/ca.json +28 -15
  65. umap/static/umap/locale/cs_CZ.js +87 -78
  66. umap/static/umap/locale/cs_CZ.json +87 -78
  67. umap/static/umap/locale/de.js +17 -8
  68. umap/static/umap/locale/de.json +17 -8
  69. umap/static/umap/locale/en.js +13 -2
  70. umap/static/umap/locale/en.json +13 -2
  71. umap/static/umap/locale/es.js +330 -319
  72. umap/static/umap/locale/es.json +330 -319
  73. umap/static/umap/locale/eu.js +10 -3
  74. umap/static/umap/locale/eu.json +10 -3
  75. umap/static/umap/locale/fa_IR.js +11 -4
  76. umap/static/umap/locale/fa_IR.json +11 -4
  77. umap/static/umap/locale/fr.js +15 -4
  78. umap/static/umap/locale/fr.json +15 -4
  79. umap/static/umap/locale/hu.js +10 -3
  80. umap/static/umap/locale/hu.json +10 -3
  81. umap/static/umap/locale/pt.js +17 -8
  82. umap/static/umap/locale/pt.json +17 -8
  83. umap/static/umap/locale/pt_PT.js +13 -4
  84. umap/static/umap/locale/pt_PT.json +13 -4
  85. umap/static/umap/locale/zh_TW.js +13 -4
  86. umap/static/umap/locale/zh_TW.json +13 -4
  87. umap/static/umap/map.css +44 -29
  88. umap/static/umap/unittests/hlc.js +165 -0
  89. umap/static/umap/unittests/sync.js +321 -15
  90. umap/static/umap/unittests/utils.js +47 -0
  91. umap/static/umap/vars.css +2 -1
  92. umap/static/umap/vendors/colorbrewer/colorbrewer.js +309 -317
  93. umap/static/umap/vendors/dompurify/purify.es.js +15 -16
  94. umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
  95. umap/static/umap/vendors/georsstogeojson/GeoRSSToGeoJSON.js +111 -80
  96. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js +2 -2
  97. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js.map +1 -1
  98. umap/static/umap/vendors/simple-statistics/simple-statistics.min.js +1 -1
  99. umap/static/umap/vendors/simple-statistics/simple-statistics.min.js.map +1 -1
  100. umap/templates/umap/css.html +0 -2
  101. umap/templates/umap/dashboard_menu.html +4 -2
  102. umap/templates/umap/js.html +0 -5
  103. umap/templates/umap/map_detail.html +2 -2
  104. umap/tests/fixtures/test_upload_data.csv +2 -2
  105. umap/tests/integration/test_anonymous_owned_map.py +1 -0
  106. umap/tests/integration/test_basics.py +1 -1
  107. umap/tests/integration/test_browser.py +69 -7
  108. umap/tests/integration/test_caption.py +3 -3
  109. umap/tests/integration/test_circles_layer.py +12 -0
  110. umap/tests/integration/test_datalayer.py +2 -1
  111. umap/tests/integration/test_draw_polygon.py +17 -9
  112. umap/tests/integration/test_draw_polyline.py +12 -8
  113. umap/tests/integration/test_edit_datalayer.py +5 -8
  114. umap/tests/integration/test_edit_map.py +2 -2
  115. umap/tests/integration/test_edit_marker.py +1 -1
  116. umap/tests/integration/test_facets_browser.py +3 -3
  117. umap/tests/integration/test_import.py +1 -0
  118. umap/tests/integration/test_map.py +1 -0
  119. umap/tests/integration/test_owned_map.py +1 -1
  120. umap/tests/integration/test_view_marker.py +63 -0
  121. umap/tests/integration/test_view_polygon.py +12 -12
  122. umap/tests/integration/test_websocket_sync.py +65 -3
  123. umap/tests/test_clean_tilelayer.py +83 -0
  124. umap/tests/test_datalayer.py +24 -0
  125. umap/tests/test_map_views.py +20 -0
  126. umap/tests/test_purge_purgatory.py +25 -0
  127. umap/tests/test_websocket_server.py +22 -0
  128. umap/urls.py +5 -1
  129. umap/views.py +6 -3
  130. umap/websocket_server.py +130 -27
  131. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/METADATA +18 -14
  132. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/RECORD +135 -127
  133. umap/static/umap/vendors/contextmenu/leaflet.contextmenu.min.css +0 -1
  134. umap/static/umap/vendors/contextmenu/leaflet.contextmenu.min.js +0 -7
  135. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/WHEEL +0 -0
  136. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/entry_points.txt +0 -0
  137. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -10,8 +10,6 @@
10
10
  href="{% static 'umap/vendors/editinosm/Leaflet.EditInOSM.css' %}" />
11
11
  <link rel="stylesheet"
12
12
  href="{% static 'umap/vendors/minimap/Control.MiniMap.min.css' %}" />
13
- <link rel="stylesheet"
14
- href="{% static 'umap/vendors/contextmenu/leaflet.contextmenu.min.css' %}" />
15
13
  <link rel="stylesheet"
16
14
  href="{% static 'umap/vendors/toolbar/leaflet.toolbar.css' %}" />
17
15
  <link rel="stylesheet"
@@ -7,8 +7,10 @@
7
7
  {% else %}
8
8
  <a href="{% url 'user_dashboard' %}">{% trans "My Maps" %}</a>
9
9
  {% endif %}
10
- <a {% if selected == "profile" %}class="selected"{% endif %}
11
- href="{% url 'user_profile' %}">{% trans "My profile" %}</a>
10
+ {% if UMAP_ALLOW_EDIT_PROFILE %}
11
+ <a {% if selected == "profile" %}class="selected"{% endif %}
12
+ href="{% url 'user_profile' %}">{% trans "My profile" %}</a>
13
+ {% endif %}
12
14
  <a {% if selected == "teams" %}class="selected"{% endif %}
13
15
  href="{% url 'user_teams' %}">{% trans "My teams" %}</a>
14
16
  </h2>
@@ -25,11 +25,7 @@
25
25
  <script src="{% static 'umap/vendors/csv2geojson/csv2geojson.js' %}" defer></script>
26
26
  <script src="{% static 'umap/vendors/osmtogeojson/osmtogeojson.js' %}" defer></script>
27
27
  <script src="{% static 'umap/vendors/loading/Control.Loading.js' %}" defer></script>
28
- <script src="{% static 'umap/vendors/contextmenu/leaflet.contextmenu.min.js' %}"
29
- defer></script>
30
28
  <script src="{% static 'umap/vendors/photon/leaflet.photon.js' %}" defer></script>
31
- <script src="{% static 'umap/vendors/georsstogeojson/GeoRSSToGeoJSON.js' %}"
32
- defer></script>
33
29
  <script src="{% static 'umap/vendors/fullscreen/Leaflet.fullscreen.min.js' %}"
34
30
  defer></script>
35
31
  <script src="{% static 'umap/vendors/toolbar/leaflet.toolbar.js' %}" defer></script>
@@ -40,7 +36,6 @@
40
36
  <script src="{% static 'umap/vendors/iconlayers/iconLayers.js' %}" defer></script>
41
37
  <script src="{% static 'umap/vendors/locatecontrol/L.Control.Locate.min.js' %}"
42
38
  defer></script>
43
- <script src="{% static 'umap/vendors/colorbrewer/colorbrewer.js' %}" defer></script>
44
39
  <script src="{% static 'umap/vendors/simple-statistics/simple-statistics.min.js' %}"
45
40
  defer></script>
46
41
  <script src="{% static 'umap/js/umap.core.js' %}" defer></script>
@@ -17,8 +17,8 @@
17
17
  {% umap_css %}
18
18
  {{ block.super }}
19
19
  {% umap_js locale=locale %}
20
- {% if object.share_status != object.PUBLIC %}
21
- <meta name="robots" content="noindex">
20
+ {% if UMAP_DEMO_SITE or object.share_status != object.PUBLIC %}
21
+ <meta name="robots" content="noindex,nofollow">
22
22
  {% endif %}
23
23
  <link rel="alternate"
24
24
  type="application/json+oembed"
@@ -1,3 +1,3 @@
1
1
  Foo,Latitude,geo_Longitude,title,description
2
- bar,41.34,122.86,a point somewhere,the description of this point
3
- bar,43.34,121.86,a point somewhere else,the description of this other point
2
+ bar,48.5,14.5,a point somewhere,the description of this point
3
+ bar,45.7,14.7,a point somewhere else,the description of this other point
@@ -156,6 +156,7 @@ def test_can_change_perms_after_create(tilelayer, live_server, page):
156
156
  ".datalayer-permissions select[name='edit_status'] option:checked"
157
157
  )
158
158
  expect(option).to_have_text("Inherit")
159
+ expect(page.get_by_label("Secret edit link:")).to_be_visible()
159
160
 
160
161
 
161
162
  def test_alert_message_after_create(
@@ -94,4 +94,4 @@ def test_login_from_map_page(live_server, page, tilelayer, settings, user, conte
94
94
  # Save should have proceed
95
95
  assert Map.objects.count() == 1
96
96
  # Use name should now appear on the header toolbar
97
- expect(page.get_by_text("My Dashboard (Joe)")).to_be_visible()
97
+ expect(page.get_by_role("button", name="Joe")).to_be_visible()
@@ -81,7 +81,7 @@ def test_data_browser_should_be_open(live_server, page, bootstrap, map):
81
81
 
82
82
 
83
83
  def test_data_browser_should_be_filterable(live_server, page, bootstrap, map):
84
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
84
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#2/19/-2")
85
85
  expect(page.get_by_title("Features in this layer: 3")).to_be_visible()
86
86
  markers = page.locator(".leaflet-marker-icon")
87
87
  paths = page.locator(".leaflet-overlay-pane path")
@@ -115,7 +115,7 @@ def test_filter_uses_layer_setting_if_any(live_server, page, bootstrap, map):
115
115
  datalayer = map.datalayer_set.first()
116
116
  datalayer.settings["labelKey"] = "foo"
117
117
  datalayer.save()
118
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
118
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#2/19/-2")
119
119
  expect(page.get_by_title("Features in this layer: 3")).to_be_visible()
120
120
  markers = page.locator(".leaflet-marker-icon")
121
121
  paths = page.locator(".leaflet-overlay-pane path")
@@ -154,7 +154,7 @@ def test_filter_works_with_variable_in_labelKey(live_server, page, map):
154
154
  data = deepcopy(DATALAYER_DATA)
155
155
  data["_umap_options"]["labelKey"] = "{name} ({bar})"
156
156
  DataLayerFactory(map=map, data=data)
157
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
157
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#2/19/-2")
158
158
  expect(page.get_by_title("Features in this layer: 3")).to_be_visible()
159
159
  markers = page.locator(".leaflet-marker-icon")
160
160
  paths = page.locator(".leaflet-overlay-pane path")
@@ -182,7 +182,7 @@ def test_filter_works_with_missing_name(live_server, page, map):
182
182
  data = deepcopy(DATALAYER_DATA)
183
183
  del data["features"][0]["properties"]["name"]
184
184
  DataLayerFactory(map=map, data=data, name="foobar")
185
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
185
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#2/19/-2")
186
186
  expect(page.get_by_title("Features in this layer: 3")).to_be_visible()
187
187
  markers = page.locator(".leaflet-marker-icon")
188
188
  paths = page.locator(".leaflet-overlay-pane path")
@@ -299,7 +299,7 @@ def test_data_browser_with_variable_in_name(live_server, page, bootstrap, map):
299
299
  # Include a variable
300
300
  map.settings["properties"]["labelKey"] = "{name} ({foo})"
301
301
  map.save()
302
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
302
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#2/19/-2")
303
303
  expect(page.get_by_text("one point in france (point)")).to_be_visible()
304
304
  expect(page.get_by_text("one line in new zeland (line)")).to_be_visible()
305
305
  expect(page.get_by_text("one polygon in greenland (polygon)")).to_be_visible()
@@ -335,7 +335,7 @@ def test_should_sort_features_in_natural_order(live_server, map, page):
335
335
 
336
336
 
337
337
  def test_should_redraw_list_on_feature_delete(live_server, openmap, page, bootstrap):
338
- page.goto(f"{live_server.url}{openmap.get_absolute_url()}")
338
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}#2/19/-2")
339
339
  # Enable edit
340
340
  page.get_by_role("button", name="Edit").click()
341
341
  buttons = page.locator(".umap-browser .datalayer li .icon-delete")
@@ -380,7 +380,7 @@ def test_should_use_color_variable(live_server, map, page):
380
380
 
381
381
 
382
382
  def test_should_allow_to_toggle_datalayer_visibility(live_server, map, page, bootstrap):
383
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
383
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#2/19/-2")
384
384
  markers = page.locator(".leaflet-marker-icon")
385
385
  paths = page.locator(".leaflet-overlay-pane path")
386
386
  expect(markers).to_have_count(1)
@@ -414,3 +414,65 @@ def test_should_have_edit_buttons_in_edit_mode(live_server, openmap, page, boots
414
414
  expect(delete_layer).to_be_visible()
415
415
  expect(edit_feature).to_have_count(3)
416
416
  expect(delete_feature).to_have_count(3)
417
+
418
+
419
+ def test_main_toolbox_toggle_all_layers(live_server, map, page):
420
+ map.settings["properties"]["onLoadPanel"] = "databrowser"
421
+ map.save()
422
+ data = {
423
+ "type": "FeatureCollection",
424
+ "features": [
425
+ {
426
+ "type": "Feature",
427
+ "properties": {"name": "one point"},
428
+ "geometry": {"type": "Point", "coordinates": [3.33, 46.92]},
429
+ },
430
+ ],
431
+ }
432
+ DataLayerFactory(map=map, data=data)
433
+ data = {
434
+ "type": "FeatureCollection",
435
+ "features": [
436
+ {
437
+ "type": "Feature",
438
+ "properties": {"name": "one other point"},
439
+ "geometry": {"type": "Point", "coordinates": [3.34, 46.94]},
440
+ },
441
+ ],
442
+ }
443
+ DataLayerFactory(map=map, data=data)
444
+ data = {
445
+ "type": "FeatureCollection",
446
+ "features": [
447
+ {
448
+ "type": "Feature",
449
+ "properties": {"name": "another point"},
450
+ "geometry": {"type": "Point", "coordinates": [3.35, 46.95]},
451
+ },
452
+ ],
453
+ "_umap_options": {"displayOnLoad": False},
454
+ }
455
+ DataLayerFactory(map=map, data=data, settings={"displayOnLoad": False})
456
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#10/46.93/3.33")
457
+ markers = page.locator(".leaflet-marker-icon")
458
+ expect(markers).to_have_count(2)
459
+ # Only one is off
460
+ expect(page.locator(".datalayer.off")).to_have_count(1)
461
+
462
+ # Click on button
463
+ page.locator(".umap-browser [data-ref=toggle]").click()
464
+ # Should have hidden the two other layers
465
+ expect(page.locator(".datalayer.off")).to_have_count(3)
466
+ expect(markers).to_have_count(0)
467
+
468
+ # Click again
469
+ page.locator(".umap-browser [data-ref=toggle]").click()
470
+ # Should shown all layers
471
+ expect(page.locator(".datalayer.off")).to_have_count(0)
472
+ expect(markers).to_have_count(3)
473
+
474
+ # Click again
475
+ page.locator(".umap-browser [data-ref=toggle]").click()
476
+ # Should hidden again all layers
477
+ expect(page.locator(".datalayer.off")).to_have_count(3)
478
+ expect(markers).to_have_count(0)
@@ -20,11 +20,11 @@ def test_caption(live_server, page, map):
20
20
  panel = page.locator(".panel.left.on")
21
21
  expect(panel).to_have_class(re.compile(".*condensed.*"))
22
22
  expect(panel.locator(".umap-caption")).to_be_visible()
23
- expect(panel.locator(".datalayer-legend").get_by_text(basic.name)).to_be_visible()
23
+ expect(panel.locator(".caption-item").get_by_text(basic.name)).to_be_visible()
24
24
  expect(
25
- panel.locator(".datalayer-legend .off").get_by_text(non_loaded.name)
25
+ panel.locator(".caption-item .off").get_by_text(non_loaded.name)
26
26
  ).to_be_visible()
27
- expect(panel.locator(".datalayer-legend").get_by_text(hidden.name)).to_be_hidden()
27
+ expect(panel.locator(".caption-item").get_by_text(hidden.name)).to_be_hidden()
28
28
 
29
29
 
30
30
  def test_caption_should_display_owner_as_author(live_server, page, map):
@@ -67,3 +67,15 @@ def test_basic_circles_layer(map, live_server, page):
67
67
  .get_attribute("d")
68
68
  .endswith("a2,2 0 1,0 -4,0 ")
69
69
  )
70
+
71
+
72
+ def test_can_draw_new_circles(openmap, live_server, page):
73
+ path = Path(__file__).parent.parent / "fixtures/test_circles_layer.geojson"
74
+ data = json.loads(path.read_text())
75
+ DataLayerFactory(data=data, map=openmap)
76
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit#12/47.2210/-1.5621")
77
+ paths = page.locator("path")
78
+ expect(paths).to_have_count(10)
79
+ page.get_by_title("Draw a marker").click()
80
+ page.locator("#map").click(position={"x": 200, "y": 200})
81
+ expect(paths).to_have_count(11)
@@ -1,4 +1,5 @@
1
1
  import json
2
+ import os
2
3
  import re
3
4
 
4
5
  import pytest
@@ -106,7 +107,7 @@ def test_should_honour_color_variable(live_server, map, page):
106
107
  },
107
108
  }
108
109
  DataLayerFactory(map=map, data=data)
109
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
110
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#6/47.5/2.5")
110
111
  expect(page.locator(".leaflet-overlay-pane path[fill='tomato']"))
111
112
  markers = page.locator(".leaflet-marker-icon .icon_container")
112
113
  expect(markers).to_have_css("background-color", "rgb(240, 248, 255)")
@@ -161,8 +161,10 @@ def test_can_draw_multi(live_server, page, tilelayer):
161
161
  page.keyboard.press("Escape")
162
162
  expect(multi_button).to_be_hidden()
163
163
  polygons.first.click(button="right", position={"x": 10, "y": 10})
164
- expect(page.get_by_role("link", name="Transform to lines")).to_be_hidden()
165
- expect(page.get_by_role("link", name="Remove shape from the multi")).to_be_visible()
164
+ expect(page.get_by_role("button", name="Transform to lines")).to_be_hidden()
165
+ expect(
166
+ page.get_by_role("button", name="Remove shape from the multi")
167
+ ).to_be_visible()
166
168
 
167
169
 
168
170
  def test_can_draw_hole(page, live_server, tilelayer):
@@ -196,7 +198,7 @@ def test_can_draw_hole(page, live_server, tilelayer):
196
198
  expect(vertices).to_have_count(8)
197
199
  # Click on the polygon but not in the hole
198
200
  polygons.first.click(button="right", position={"x": 10, "y": 10})
199
- expect(page.get_by_role("link", name="Transform to lines")).to_be_hidden()
201
+ expect(page.get_by_role("button", name="Transform to lines")).to_be_hidden()
200
202
 
201
203
 
202
204
  def test_can_transfer_shape_from_simple_polygon(live_server, page, tilelayer):
@@ -228,7 +230,7 @@ def test_can_transfer_shape_from_simple_polygon(live_server, page, tilelayer):
228
230
  # Now that polygon 2 is selected, right click on first one
229
231
  # and transfer shape
230
232
  polygons.first.click(position={"x": 20, "y": 20}, button="right")
231
- page.get_by_role("link", name="Transfer shape to edited feature").click()
233
+ page.get_by_role("button", name="Transfer shape to edited feature").click()
232
234
  expect(polygons).to_have_count(1)
233
235
 
234
236
 
@@ -246,7 +248,9 @@ def test_can_extract_shape(live_server, page, tilelayer, settings):
246
248
  # Click again to finish
247
249
  map.click(position={"x": 100, "y": 100})
248
250
  expect(polygons).to_have_count(1)
249
- extract_button = page.get_by_role("link", name="Extract shape to separate feature")
251
+ extract_button = page.get_by_role(
252
+ "button", name="Extract shape to separate feature"
253
+ )
250
254
  expect(extract_button).to_be_hidden()
251
255
  page.get_by_title("Add a polygon to the current multi").click()
252
256
  map.click(position={"x": 250, "y": 200})
@@ -326,7 +330,9 @@ def test_cannot_transfer_shape_to_line(live_server, page, tilelayer):
326
330
  # Click again to finish
327
331
  map.click(position={"x": 100, "y": 100})
328
332
  expect(polygons).to_have_count(1)
329
- extract_button = page.get_by_role("link", name="Extract shape to separate feature")
333
+ extract_button = page.get_by_role(
334
+ "button", name="Extract shape to separate feature"
335
+ )
330
336
  polygons.first.click(position={"x": 20, "y": 20}, button="right")
331
337
  expect(extract_button).to_be_hidden()
332
338
  page.get_by_title("Draw a polyline").click()
@@ -352,7 +358,9 @@ def test_cannot_transfer_shape_to_marker(live_server, page, tilelayer):
352
358
  # Click again to finish
353
359
  map.click(position={"x": 100, "y": 100})
354
360
  expect(polygons).to_have_count(1)
355
- extract_button = page.get_by_role("link", name="Extract shape to separate feature")
361
+ extract_button = page.get_by_role(
362
+ "button", name="Extract shape to separate feature"
363
+ )
356
364
  polygons.first.click(position={"x": 20, "y": 20}, button="right")
357
365
  expect(extract_button).to_be_hidden()
358
366
  page.get_by_title("Draw a marker").click()
@@ -377,7 +385,7 @@ def test_can_clone_polygon(live_server, page, tilelayer, settings):
377
385
  map.click(position={"x": 100, "y": 100})
378
386
  expect(polygons).to_have_count(1)
379
387
  polygons.first.click(button="right")
380
- page.get_by_role("link", name="Clone this feature").click()
388
+ page.get_by_role("button", name="Clone this feature").click()
381
389
  expect(polygons).to_have_count(2)
382
390
  data = save_and_get_json(page)
383
391
  assert len(data["features"]) == 2
@@ -402,7 +410,7 @@ def test_can_transform_polygon_to_line(live_server, page, tilelayer, settings):
402
410
  expect(polygons).to_have_count(1)
403
411
  expect(paths).to_have_count(1)
404
412
  polygons.first.click(button="right")
405
- page.get_by_role("link", name="Transform to lines").click()
413
+ page.get_by_role("button", name="Transform to lines").click()
406
414
  # No more polygons (will fill), but one path, it must be a line
407
415
  expect(polygons).to_have_count(0)
408
416
  expect(paths).to_have_count(1)
@@ -157,8 +157,10 @@ def test_can_draw_multi(live_server, page, tilelayer):
157
157
  page.keyboard.press("Escape")
158
158
  expect(add_shape).to_be_hidden()
159
159
  lines.first.click(button="right", position={"x": 10, "y": 1})
160
- expect(page.get_by_role("link", name="Transform to polygon")).to_be_hidden()
161
- expect(page.get_by_role("link", name="Remove shape from the multi")).to_be_visible()
160
+ expect(page.get_by_role("button", name="Transform to polygon")).to_be_hidden()
161
+ expect(
162
+ page.get_by_role("button", name="Remove shape from the multi")
163
+ ).to_be_visible()
162
164
 
163
165
 
164
166
  def test_can_transfer_shape_from_simple_polyline(live_server, page, tilelayer):
@@ -188,7 +190,7 @@ def test_can_transfer_shape_from_simple_polyline(live_server, page, tilelayer):
188
190
  # Now that line 2 is selected, right click on first one
189
191
  # and transfer shape
190
192
  lines.first.click(position={"x": 10, "y": 1}, button="right")
191
- page.get_by_role("link", name="Transfer shape to edited feature").click()
193
+ page.get_by_role("button", name="Transfer shape to edited feature").click()
192
194
  expect(lines).to_have_count(1)
193
195
 
194
196
 
@@ -227,7 +229,7 @@ def test_can_transfer_shape_from_multi(live_server, page, tilelayer, settings):
227
229
  # Now that line 2 is selected, right click on first one
228
230
  # and transfer shape
229
231
  lines.first.click(position={"x": 10, "y": 1}, button="right")
230
- page.get_by_role("link", name="Transfer shape to edited feature").click()
232
+ page.get_by_role("button", name="Transfer shape to edited feature").click()
231
233
  expect(lines).to_have_count(2)
232
234
  data = save_and_get_json(page)
233
235
  assert data["features"][0]["geometry"] == {
@@ -259,7 +261,9 @@ def test_can_extract_shape(live_server, page, tilelayer):
259
261
  # Click again to finish
260
262
  map.click(position={"x": 100, "y": 200})
261
263
  expect(lines).to_have_count(1)
262
- extract_button = page.get_by_role("link", name="Extract shape to separate feature")
264
+ extract_button = page.get_by_role(
265
+ "button", name="Extract shape to separate feature"
266
+ )
263
267
  expect(extract_button).to_be_hidden()
264
268
  page.get_by_title("Add a line to the current multi").click()
265
269
  map.click(position={"x": 250, "y": 250})
@@ -287,7 +291,7 @@ def test_can_clone_polyline(live_server, page, tilelayer, settings):
287
291
  map.click(position={"x": 100, "y": 200})
288
292
  expect(lines).to_have_count(1)
289
293
  lines.first.click(position={"x": 10, "y": 1}, button="right")
290
- page.get_by_role("link", name="Clone this feature").click()
294
+ page.get_by_role("button", name="Clone this feature").click()
291
295
  expect(lines).to_have_count(2)
292
296
  data = save_and_get_json(page)
293
297
  assert len(data["features"]) == 2
@@ -313,7 +317,7 @@ def test_can_transform_polyline_to_polygon(live_server, page, tilelayer, setting
313
317
  expect(paths).to_have_count(1)
314
318
  expect(polygons).to_have_count(0)
315
319
  paths.first.click(position={"x": 10, "y": 1}, button="right")
316
- page.get_by_role("link", name="Transform to polygon").click()
320
+ page.get_by_role("button", name="Transform to polygon").click()
317
321
  expect(polygons).to_have_count(1)
318
322
  expect(paths).to_have_count(1)
319
323
  data = save_and_get_json(page)
@@ -374,7 +378,7 @@ def test_can_merge_lines(live_server, page, tilelayer, settings):
374
378
 
375
379
  # Right click and merge nodes
376
380
  map.click(button="right", position={"x": 100, "y": 200})
377
- map.get_by_role("link", name="Merge lines").click()
381
+ page.get_by_role("button", name="Merge lines").click()
378
382
  data = save_and_get_json(page)
379
383
  assert len(data["features"]) == 1
380
384
  assert data["features"][0]["geometry"]["type"] == "LineString"
@@ -60,12 +60,10 @@ def test_cancel_deleting_datalayer_should_restore(
60
60
  expect(layers).to_have_count(1)
61
61
  expect(markers).to_have_count(1)
62
62
  page.get_by_role("link", name="Manage layers").click()
63
- page.once("dialog", lambda dialog: dialog.accept())
64
63
  page.locator(".panel.right").get_by_title("Delete layer").click()
64
+ page.get_by_role("button", name="OK").click()
65
65
  expect(markers).to_have_count(0)
66
- page.get_by_role("button", name="Open browser").click()
67
66
  expect(page.get_by_text("test datalayer")).to_be_hidden()
68
- page.once("dialog", lambda dialog: dialog.accept())
69
67
  page.get_by_role("button", name="Cancel edits").click()
70
68
  page.locator("dialog").get_by_role("button", name="OK").click()
71
69
  expect(markers).to_have_count(1)
@@ -88,7 +86,6 @@ def test_can_clone_datalayer(live_server, openmap, login, datalayer, page):
88
86
 
89
87
 
90
88
  def test_can_change_icon_class(live_server, openmap, page):
91
- # Faster than doing a login
92
89
  data = {
93
90
  "type": "FeatureCollection",
94
91
  "features": [
@@ -100,7 +97,7 @@ def test_can_change_icon_class(live_server, openmap, page):
100
97
  ],
101
98
  }
102
99
  DataLayerFactory(map=openmap, data=data)
103
- page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
100
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit#6/45.3/1")
104
101
  expect(page.locator(".umap-div-icon")).to_be_visible()
105
102
  page.get_by_role("link", name="Manage layers").click()
106
103
  expect(page.locator(".umap-circle-icon")).to_be_hidden()
@@ -174,8 +171,8 @@ def test_can_restore_version(live_server, openmap, page, datalayer):
174
171
  page.get_by_role("link", name="Manage layers").click()
175
172
  page.locator(".panel.right").get_by_title("Edit", exact=True).click()
176
173
  page.get_by_text("Versions").click()
177
- page.once("dialog", lambda dialog: dialog.accept())
178
174
  page.get_by_role("button", name="Restore this version").last.click()
175
+ page.get_by_role("button", name="OK").click()
179
176
  expect(marker).to_have_class(re.compile(".*umap-ball-icon.*"))
180
177
 
181
178
 
@@ -196,8 +193,8 @@ def test_deleting_datalayer_should_remove_from_browser_and_layers_list(
196
193
  page.get_by_role("link", name="Manage layers").click()
197
194
  expect(panel.get_by_text("test datalayer")).to_be_visible()
198
195
  expect(edit_panel.get_by_text("test datalayer")).to_be_visible()
199
- page.once("dialog", lambda dialog: dialog.accept())
200
196
  page.locator(".panel.right").get_by_title("Delete layer").click()
197
+ page.get_by_role("button", name="OK").click()
201
198
  expect(panel.get_by_text("test datalayer")).to_be_hidden()
202
199
  expect(edit_panel.get_by_text("test datalayer")).to_be_hidden()
203
200
 
@@ -210,6 +207,6 @@ def test_deleting_datalayer_should_remove_from_caption(
210
207
  page.get_by_role("button", name="About").click()
211
208
  page.get_by_role("link", name="Manage layers").click()
212
209
  expect(panel.get_by_text("test datalayer")).to_be_visible()
213
- page.once("dialog", lambda dialog: dialog.accept())
214
210
  page.locator(".panel.right").get_by_title("Delete layer").click()
211
+ page.get_by_role("button", name="OK").click()
215
212
  expect(panel.get_by_text("test datalayer")).to_be_hidden()
@@ -23,7 +23,7 @@ def test_can_edit_name(page, live_server, tilelayer):
23
23
 
24
24
  def test_can_edit_name_on_click_on_toolbar(page, live_server, tilelayer):
25
25
  page.goto(f"{live_server.url}/en/map/new/")
26
- page.locator(".map-name").click()
26
+ page.locator(".umap-main-edit-toolbox .map-name").click()
27
27
  name_input = page.locator('.map-metadata input[name="name"]')
28
28
  expect(name_input).to_be_visible()
29
29
 
@@ -40,7 +40,7 @@ def test_map_name_impacts_ui(live_server, page, tilelayer):
40
40
 
41
41
  name_input.fill("something else")
42
42
 
43
- expect(page.get_by_role("button", name="something else").nth(1)).to_be_visible()
43
+ expect(page.get_by_role("button", name="something else").first).to_be_visible()
44
44
 
45
45
 
46
46
  def test_zoomcontrol_impacts_ui(live_server, page, tilelayer):
@@ -40,7 +40,7 @@ def test_can_edit_on_shift_click(live_server, openmap, page, datalayer):
40
40
 
41
41
 
42
42
  def test_marker_style_should_have_precedence(live_server, openmap, page, bootstrap):
43
- page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
43
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit#6/48.5/19")
44
44
 
45
45
  # Change colour at layer level
46
46
  page.get_by_role("link", name="Manage layers").click()
@@ -175,7 +175,7 @@ def test_date_facet_search(live_server, page, map):
175
175
  map.save()
176
176
  DataLayerFactory(map=map, data=DATALAYER_DATA1)
177
177
  DataLayerFactory(map=map, data=DATALAYER_DATA2)
178
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
178
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#6/47.5/-1.5")
179
179
  markers = page.locator(".leaflet-marker-icon")
180
180
  expect(markers).to_have_count(4)
181
181
  expect(page.get_by_text("Date Filter")).to_be_visible()
@@ -196,7 +196,7 @@ def test_choice_with_empty_value(live_server, page, map):
196
196
  del data["features"][1]["properties"]["mytype"]
197
197
  DataLayerFactory(map=map, data=data)
198
198
  DataLayerFactory(map=map, data=DATALAYER_DATA2)
199
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
199
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#6/47.5/-1.5")
200
200
  expect(page.get_by_text("<empty value>")).to_be_visible()
201
201
  markers = page.locator(".leaflet-marker-icon")
202
202
  expect(markers).to_have_count(4)
@@ -212,7 +212,7 @@ def test_number_with_zero_value(live_server, page, map):
212
212
  data["features"][0]["properties"]["mynumber"] = 0
213
213
  DataLayerFactory(map=map, data=data)
214
214
  DataLayerFactory(map=map, data=DATALAYER_DATA2)
215
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
215
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#6/47.5/-1.5")
216
216
  expect(page.get_by_label("Min")).to_have_value("0")
217
217
  expect(page.get_by_label("Max")).to_have_value("14")
218
218
  page.get_by_label("Min").fill("1")
@@ -1,4 +1,5 @@
1
1
  import json
2
+ import os
2
3
  import platform
3
4
  import re
4
5
  from pathlib import Path
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import re
2
3
 
3
4
  import pytest
@@ -234,8 +234,8 @@ def test_can_delete_datalayer(live_server, map, login, datalayer):
234
234
  expect(layers).to_have_count(1)
235
235
  expect(markers).to_have_count(1)
236
236
  page.get_by_role("link", name="Manage layers").click()
237
- page.once("dialog", lambda dialog: dialog.accept())
238
237
  page.locator(".panel.right").get_by_title("Delete layer").click()
238
+ page.get_by_role("button", name="OK").click()
239
239
  with page.expect_response(re.compile(r".*/datalayer/delete/.*")):
240
240
  page.get_by_role("button", name="Save").click()
241
241
  expect(markers).to_have_count(0)
@@ -106,3 +106,66 @@ def test_extended_properties_in_popup(live_server, map, page, bootstrap):
106
106
  expect(page.get_by_text("Alt: 241")).to_be_visible()
107
107
  expect(page.get_by_text("Zoom: 7")).to_be_visible()
108
108
  expect(page.get_by_text("Layer: test datalayer")).to_be_visible()
109
+
110
+
111
+ def test_only_visible_markers_are_added_to_dom(live_server, map, page):
112
+ data = {
113
+ "type": "FeatureCollection",
114
+ "features": [
115
+ {
116
+ "type": "Feature",
117
+ "properties": {
118
+ "name": "marker 1",
119
+ "description": "added to dom",
120
+ },
121
+ "geometry": {
122
+ "type": "Point",
123
+ "coordinates": [14.6, 48.5],
124
+ },
125
+ },
126
+ {
127
+ "type": "Feature",
128
+ "properties": {
129
+ "name": "marker 2",
130
+ "description": "not added to dom at load",
131
+ },
132
+ "geometry": {
133
+ "type": "Point",
134
+ "coordinates": [12.6, 44.5],
135
+ },
136
+ },
137
+ ],
138
+ }
139
+ DataLayerFactory(map=map, data=data)
140
+ map.settings["properties"]["showLabel"] = True
141
+ map.save()
142
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
143
+ markers = page.locator(".leaflet-marker-icon")
144
+ tooltips = page.locator(".leaflet-tooltip")
145
+ expect(markers).to_have_count(1)
146
+ expect(tooltips).to_have_count(1)
147
+
148
+ # Zoom in/out to show the other marker
149
+ page.get_by_label("Zoom out").click()
150
+ expect(markers).to_have_count(2)
151
+ expect(tooltips).to_have_count(2)
152
+ page.get_by_label("Zoom in").click()
153
+ expect(markers).to_have_count(1)
154
+ expect(tooltips).to_have_count(1)
155
+
156
+ # Drag map to show/hide the marker
157
+ map_el = page.locator("#map")
158
+ map_el.drag_to(
159
+ map_el,
160
+ source_position={"x": 100, "y": 600},
161
+ target_position={"x": 100, "y": 200},
162
+ )
163
+ expect(markers).to_have_count(2)
164
+ expect(tooltips).to_have_count(2)
165
+ map_el.drag_to(
166
+ map_el,
167
+ source_position={"x": 100, "y": 600},
168
+ target_position={"x": 100, "y": 200},
169
+ )
170
+ expect(markers).to_have_count(1)
171
+ expect(tooltips).to_have_count(1)