umap-project 2.1.3__py3-none-any.whl → 2.2.0b0__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 (196) hide show
  1. umap/__init__.py +1 -1
  2. umap/context_processors.py +1 -0
  3. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/en/LC_MESSAGES/django.po +32 -32
  5. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  8. umap/migrations/0020_alter_tilelayer_url_template.py +19 -0
  9. umap/migrations/0021_remove_map_description.py +16 -0
  10. umap/models.py +8 -6
  11. umap/settings/base.py +1 -0
  12. umap/static/umap/base.css +29 -151
  13. umap/static/umap/content.css +7 -25
  14. umap/static/umap/css/icon.css +112 -0
  15. umap/static/umap/css/panel.css +140 -0
  16. umap/static/umap/img/16-white.svg +5 -1
  17. umap/static/umap/img/16.svg +7 -4
  18. umap/static/umap/img/24-white.svg +3 -1
  19. umap/static/umap/img/24.svg +3 -4
  20. umap/static/umap/img/source/16-white.svg +176 -940
  21. umap/static/umap/img/source/16.svg +8 -5
  22. umap/static/umap/img/source/24-white.svg +5 -3
  23. umap/static/umap/img/source/24.svg +6 -7
  24. umap/static/umap/js/modules/browser.js +82 -73
  25. umap/static/umap/js/modules/dompurify.js +12 -0
  26. umap/static/umap/js/modules/facets.js +148 -0
  27. umap/static/umap/js/modules/global.js +9 -1
  28. umap/static/umap/js/modules/i18n.js +7 -0
  29. umap/static/umap/js/modules/orderable.js +84 -0
  30. umap/static/umap/js/modules/panel.js +76 -0
  31. umap/static/umap/js/modules/request.js +0 -1
  32. umap/static/umap/js/modules/schema.js +324 -223
  33. umap/static/umap/js/modules/urls.js +1 -16
  34. umap/static/umap/js/modules/utils.js +340 -0
  35. umap/static/umap/js/umap.controls.js +183 -330
  36. umap/static/umap/js/umap.core.js +60 -364
  37. umap/static/umap/js/umap.datalayer.permissions.js +1 -1
  38. umap/static/umap/js/umap.features.js +60 -40
  39. umap/static/umap/js/umap.forms.js +111 -25
  40. umap/static/umap/js/umap.icon.js +11 -4
  41. umap/static/umap/js/umap.importer.js +24 -17
  42. umap/static/umap/js/umap.js +170 -145
  43. umap/static/umap/js/umap.layer.js +71 -40
  44. umap/static/umap/js/umap.permissions.js +9 -11
  45. umap/static/umap/js/umap.popup.js +10 -21
  46. umap/static/umap/js/umap.share.js +11 -8
  47. umap/static/umap/js/umap.tableeditor.js +4 -6
  48. umap/static/umap/js/umap.ui.js +0 -51
  49. umap/static/umap/locale/am_ET.js +242 -227
  50. umap/static/umap/locale/am_ET.json +18 -7
  51. umap/static/umap/locale/ar.js +242 -227
  52. umap/static/umap/locale/ar.json +18 -7
  53. umap/static/umap/locale/ast.js +242 -227
  54. umap/static/umap/locale/ast.json +18 -7
  55. umap/static/umap/locale/bg.js +242 -227
  56. umap/static/umap/locale/bg.json +18 -7
  57. umap/static/umap/locale/br.js +252 -237
  58. umap/static/umap/locale/br.json +22 -11
  59. umap/static/umap/locale/ca.js +242 -227
  60. umap/static/umap/locale/ca.json +18 -7
  61. umap/static/umap/locale/cs_CZ.js +242 -227
  62. umap/static/umap/locale/cs_CZ.json +18 -7
  63. umap/static/umap/locale/da.js +242 -227
  64. umap/static/umap/locale/da.json +18 -7
  65. umap/static/umap/locale/de.js +242 -227
  66. umap/static/umap/locale/de.json +18 -7
  67. umap/static/umap/locale/el.js +242 -227
  68. umap/static/umap/locale/el.json +18 -7
  69. umap/static/umap/locale/en.js +242 -234
  70. umap/static/umap/locale/en.json +19 -8
  71. umap/static/umap/locale/en_US.json +18 -7
  72. umap/static/umap/locale/es.js +242 -227
  73. umap/static/umap/locale/es.json +18 -7
  74. umap/static/umap/locale/et.js +242 -227
  75. umap/static/umap/locale/et.json +18 -7
  76. umap/static/umap/locale/eu.js +227 -199
  77. umap/static/umap/locale/eu.json +1 -1
  78. umap/static/umap/locale/fa_IR.js +242 -227
  79. umap/static/umap/locale/fa_IR.json +18 -7
  80. umap/static/umap/locale/fi.js +242 -227
  81. umap/static/umap/locale/fi.json +18 -7
  82. umap/static/umap/locale/fr.js +242 -234
  83. umap/static/umap/locale/fr.json +18 -7
  84. umap/static/umap/locale/gl.js +242 -227
  85. umap/static/umap/locale/gl.json +18 -7
  86. umap/static/umap/locale/he.js +242 -227
  87. umap/static/umap/locale/he.json +18 -7
  88. umap/static/umap/locale/hr.js +242 -227
  89. umap/static/umap/locale/hr.json +18 -7
  90. umap/static/umap/locale/hu.js +242 -234
  91. umap/static/umap/locale/hu.json +18 -7
  92. umap/static/umap/locale/id.js +242 -227
  93. umap/static/umap/locale/id.json +18 -7
  94. umap/static/umap/locale/is.js +242 -227
  95. umap/static/umap/locale/is.json +18 -7
  96. umap/static/umap/locale/it.js +242 -234
  97. umap/static/umap/locale/it.json +18 -7
  98. umap/static/umap/locale/ja.js +242 -227
  99. umap/static/umap/locale/ja.json +18 -7
  100. umap/static/umap/locale/ko.js +242 -227
  101. umap/static/umap/locale/ko.json +18 -7
  102. umap/static/umap/locale/lt.js +242 -227
  103. umap/static/umap/locale/lt.json +18 -7
  104. umap/static/umap/locale/ms.js +242 -234
  105. umap/static/umap/locale/ms.json +19 -8
  106. umap/static/umap/locale/nl.js +245 -230
  107. umap/static/umap/locale/nl.json +18 -7
  108. umap/static/umap/locale/no.js +242 -227
  109. umap/static/umap/locale/no.json +18 -7
  110. umap/static/umap/locale/pl.js +242 -227
  111. umap/static/umap/locale/pl.json +18 -7
  112. umap/static/umap/locale/pl_PL.json +18 -7
  113. umap/static/umap/locale/pt.js +242 -227
  114. umap/static/umap/locale/pt.json +18 -7
  115. umap/static/umap/locale/pt_BR.js +242 -227
  116. umap/static/umap/locale/pt_BR.json +18 -7
  117. umap/static/umap/locale/pt_PT.js +242 -227
  118. umap/static/umap/locale/pt_PT.json +18 -7
  119. umap/static/umap/locale/ro.js +242 -227
  120. umap/static/umap/locale/ro.json +18 -7
  121. umap/static/umap/locale/ru.js +242 -227
  122. umap/static/umap/locale/ru.json +18 -7
  123. umap/static/umap/locale/si.js +1 -1
  124. umap/static/umap/locale/si.json +1 -1
  125. umap/static/umap/locale/sk_SK.js +242 -227
  126. umap/static/umap/locale/sk_SK.json +18 -7
  127. umap/static/umap/locale/sl.js +242 -227
  128. umap/static/umap/locale/sl.json +18 -7
  129. umap/static/umap/locale/sr.js +242 -227
  130. umap/static/umap/locale/sr.json +18 -7
  131. umap/static/umap/locale/sv.js +242 -227
  132. umap/static/umap/locale/sv.json +18 -7
  133. umap/static/umap/locale/th_TH.js +242 -227
  134. umap/static/umap/locale/th_TH.json +18 -7
  135. umap/static/umap/locale/tr.js +242 -227
  136. umap/static/umap/locale/tr.json +18 -7
  137. umap/static/umap/locale/uk_UA.js +242 -227
  138. umap/static/umap/locale/uk_UA.json +18 -7
  139. umap/static/umap/locale/vi.js +242 -227
  140. umap/static/umap/locale/vi.json +18 -7
  141. umap/static/umap/locale/vi_VN.json +18 -7
  142. umap/static/umap/locale/zh.js +242 -227
  143. umap/static/umap/locale/zh.json +18 -7
  144. umap/static/umap/locale/zh_CN.json +18 -7
  145. umap/static/umap/locale/zh_TW.Big5.json +18 -7
  146. umap/static/umap/locale/zh_TW.js +242 -234
  147. umap/static/umap/locale/zh_TW.json +18 -7
  148. umap/static/umap/map.css +114 -265
  149. umap/static/umap/test/DataLayer.js +463 -0
  150. umap/static/umap/test/Feature.js +0 -226
  151. umap/static/umap/test/TableEditor.js +104 -0
  152. umap/static/umap/test/Util.js +0 -521
  153. umap/static/umap/test/index.html +0 -1
  154. umap/static/umap/unittests/URLs.js +1 -1
  155. umap/static/umap/unittests/utils.js +610 -0
  156. umap/static/umap/vars.css +9 -0
  157. umap/static/umap/vendors/dompurify/purify.es.mjs +1525 -0
  158. umap/static/umap/vendors/iconlayers/iconLayers.js +1 -1
  159. umap/templates/umap/css.html +2 -0
  160. umap/templates/umap/js.html +0 -1
  161. umap/templates/umap/map_detail.html +4 -0
  162. umap/templates/umap/map_table.html +12 -10
  163. umap/templatetags/umap_tags.py +5 -0
  164. umap/tests/integration/conftest.py +12 -1
  165. umap/tests/integration/test_anonymous_owned_map.py +6 -5
  166. umap/tests/integration/test_browser.py +12 -25
  167. umap/tests/integration/test_choropleth.py +1 -1
  168. umap/tests/integration/test_dashboard.py +10 -0
  169. umap/tests/integration/test_datalayer.py +8 -6
  170. umap/tests/integration/test_edit_datalayer.py +24 -19
  171. umap/tests/integration/test_edit_map.py +182 -2
  172. umap/tests/integration/test_edit_marker.py +120 -0
  173. umap/tests/integration/test_edit_polygon.py +122 -0
  174. umap/tests/integration/test_facets_browser.py +104 -14
  175. umap/tests/integration/test_import.py +70 -20
  176. umap/tests/integration/test_map.py +19 -17
  177. umap/tests/integration/test_map_list.py +28 -0
  178. umap/tests/integration/test_owned_map.py +10 -10
  179. umap/tests/integration/test_picto.py +5 -5
  180. umap/tests/integration/test_querystring.py +9 -15
  181. umap/tests/integration/test_slideshow.py +0 -5
  182. umap/tests/integration/test_statics.py +3 -2
  183. umap/tests/integration/test_tableeditor.py +1 -5
  184. umap/tests/integration/test_view_marker.py +64 -0
  185. umap/tests/integration/test_view_polygon.py +59 -0
  186. umap/tests/integration/test_view_polyline.py +51 -0
  187. umap/tests/test_map_views.py +13 -0
  188. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/METADATA +8 -8
  189. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/RECORD +194 -178
  190. umap/static/umap/vendors/dompurify/purify.min.js +0 -3
  191. umap/static/umap/vendors/dompurify/purify.min.js.map +0 -1
  192. /umap/tests/integration/{test_polygon.py → test_draw_polygon.py} +0 -0
  193. /umap/tests/integration/{test_polyline.py → test_draw_polyline.py} +0 -0
  194. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/WHEEL +0 -0
  195. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/entry_points.txt +0 -0
  196. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/licenses/LICENSE +0 -0
@@ -307,4 +307,4 @@
307
307
  iconLayers.Constructor = IconLayers;
308
308
 
309
309
  return iconLayers;
310
- });
310
+ });
@@ -23,8 +23,10 @@
23
23
  href="{% static 'umap/vendors/iconlayers/iconLayers.css' %}" />
24
24
  <link rel="stylesheet" href="{% static 'umap/vars.css' %}" />
25
25
  <link rel="stylesheet" href="{% static 'umap/font.css' %}" />
26
+ <link rel="stylesheet" href="{% static 'umap/css/icon.css' %}" />
26
27
  <link rel="stylesheet" href="{% static 'umap/base.css' %}" />
27
28
  <link rel="stylesheet" href="{% static 'umap/content.css' %}" />
28
29
  <link rel="stylesheet" href="{% static 'umap/nav.css' %}" />
29
30
  <link rel="stylesheet" href="{% static 'umap/map.css' %}" />
31
+ <link rel="stylesheet" href="{% static 'umap/css/panel.css' %}" />
30
32
  <link rel="stylesheet" href="{% static 'umap/theme.css' %}" />
@@ -42,7 +42,6 @@
42
42
  <script src="{% static 'umap/vendors/tokml/tokml.js' %}" defer></script>
43
43
  <script src="{% static 'umap/vendors/locatecontrol/L.Control.Locate.min.js' %}"
44
44
  defer></script>
45
- <script src="{% static 'umap/vendors/dompurify/purify.min.js' %}" defer></script>
46
45
  <script src="{% static 'umap/vendors/colorbrewer/colorbrewer.js' %}" defer></script>
47
46
  <script src="{% static 'umap/vendors/simple-statistics/simple-statistics.min.js' %}"
48
47
  defer></script>
@@ -18,6 +18,10 @@
18
18
  type="application/json+oembed"
19
19
  href="{{ oembed_absolute_uri }}?url={{ quoted_absolute_uri }}&format=json"
20
20
  title="{{ map.name }} oEmbed URL" />
21
+ <meta property="og:url" content="{{ SITE_URL }}{{ map.get_absolute_url }}" />
22
+ <meta property="og:title" content="{{ map.name }}" />
23
+ <meta property="og:description" content="{{ map.description }}" />
24
+ <meta property="og:site_name" content="{{ SITE_NAME }}" />
21
25
  {% endblock extra_head %}
22
26
  {% block content %}
23
27
  {% block map_init %}
@@ -68,16 +68,18 @@
68
68
  <span class="sr-only">{% translate "Clone" %}</span>
69
69
  </button>
70
70
  </form>
71
- <form action="{% url 'map_delete' map_inst.pk %}"
72
- method="post"
73
- class="map-delete">
74
- {% csrf_token %}
75
- <input type="hidden" name="next" value="{% url 'user_dashboard' %}">
76
- <button class="map-icon" type="submit" title="{% translate "Delete" %}">
77
- <span class="icon-dashboard icon-delete"></span>
78
- <span class="sr-only">{% translate "Delete" %}</span>
79
- </button>
80
- </form>
71
+ {% if map_inst|can_delete_map:request %}
72
+ <form action="{% url 'map_delete' map_inst.pk %}"
73
+ method="post"
74
+ class="map-delete">
75
+ {% csrf_token %}
76
+ <input type="hidden" name="next" value="{% url 'user_dashboard' %}">
77
+ <button class="map-icon" type="submit" title="{% translate "Delete" %}">
78
+ <span class="icon-dashboard icon-delete"></span>
79
+ <span class="sr-only">{% translate "Delete" %}</span>
80
+ </button>
81
+ </form>
82
+ {% endif %}
81
83
  </td>
82
84
  </tr>
83
85
  {% endwith %}
@@ -43,6 +43,11 @@ def tilelayer_preview(tilelayer):
43
43
  return output
44
44
 
45
45
 
46
+ @register.filter
47
+ def can_delete_map(map, request):
48
+ return map.can_delete(request.user, request)
49
+
50
+
46
51
  @register.filter
47
52
  def notag(s):
48
53
  return s.replace("<", "&lt;")
@@ -1,9 +1,20 @@
1
+ import os
2
+
1
3
  import pytest
2
4
 
3
5
 
4
6
  @pytest.fixture(autouse=True)
5
7
  def set_timeout(context):
6
- context.set_default_timeout(5000)
8
+ context.set_default_timeout(int(os.environ.get("PLAYWRIGHT_TIMEOUT", 7500)))
9
+ context.set_default_navigation_timeout(
10
+ int(os.environ.get("PLAYWRIGHT_TIMEOUT", 7500))
11
+ )
12
+
13
+
14
+ @pytest.fixture(autouse=True)
15
+ def mock_osm_tiles(page):
16
+ if not bool(os.environ.get("PLAYWRIGHT_USE_TILES", False)):
17
+ page.route("*/**/osmfr/**", lambda route: route.fulfill())
7
18
 
8
19
 
9
20
  @pytest.fixture
@@ -34,7 +34,7 @@ def test_map_load_with_owner(anonymap, live_server, owner_session):
34
34
  expect(save).to_be_visible()
35
35
  add_marker = owner_session.get_by_title("Draw a marker")
36
36
  expect(add_marker).to_be_visible()
37
- edit_settings = owner_session.get_by_title("Edit map properties")
37
+ edit_settings = owner_session.get_by_title("Map advanced properties")
38
38
  expect(edit_settings).to_be_visible()
39
39
  edit_permissions = owner_session.get_by_title("Update permissions and editors")
40
40
  expect(edit_permissions).to_be_visible()
@@ -65,7 +65,7 @@ def test_map_load_with_anonymous_but_editable_layer(
65
65
  expect(save).to_be_visible()
66
66
  add_marker = page.get_by_title("Draw a marker")
67
67
  expect(add_marker).to_be_visible()
68
- edit_settings = page.get_by_title("Edit map properties")
68
+ edit_settings = page.get_by_title("Map advanced properties")
69
69
  expect(edit_settings).to_be_hidden()
70
70
  edit_permissions = page.get_by_title("Update permissions and editors")
71
71
  expect(edit_permissions).to_be_hidden()
@@ -114,12 +114,13 @@ def test_anonymous_can_add_marker_on_editable_layer(
114
114
  marker = page.locator(".leaflet-marker-icon")
115
115
  map_el = page.locator("#map")
116
116
  expect(marker).to_have_count(2)
117
- expect(map_el).not_to_have_class(re.compile("umap-ui"))
117
+ panel = page.locator(".panel.right.on")
118
+ expect(panel).to_be_hidden()
118
119
  add_marker.click()
119
120
  map_el.click(position={"x": 100, "y": 100})
120
121
  expect(marker).to_have_count(3)
121
122
  # Edit panel is open
122
- expect(map_el).to_have_class(re.compile("umap-ui"))
123
+ expect(panel).to_be_visible()
123
124
  datalayer_select = page.locator("select[name='datalayer']")
124
125
  expect(datalayer_select).to_be_visible()
125
126
  options = page.locator("select[name='datalayer'] option")
@@ -132,7 +133,7 @@ def test_can_change_perms_after_create(tilelayer, live_server, page):
132
133
  page.goto(f"{live_server.url}/en/map/new")
133
134
  # Create a layer
134
135
  page.get_by_title("Manage layers").click()
135
- page.get_by_role("button", name="Add a layer").click()
136
+ page.get_by_title("Add a layer").click()
136
137
  page.locator("input[name=name]").fill("Layer 1")
137
138
  save = page.get_by_role("button", name="Save")
138
139
  expect(save).to_be_visible()
@@ -63,7 +63,7 @@ def bootstrap(map, live_server):
63
63
 
64
64
  def test_data_browser_should_be_open(live_server, page, bootstrap, map):
65
65
  page.goto(f"{live_server.url}{map.get_absolute_url()}")
66
- el = page.locator(".umap-browse-data")
66
+ el = page.locator(".umap-browser")
67
67
  expect(el).to_be_visible()
68
68
  expect(page.get_by_text("one point in france")).to_be_visible()
69
69
  expect(page.get_by_text("one line in new zeland")).to_be_visible()
@@ -81,7 +81,7 @@ def test_data_browser_should_be_filterable(live_server, page, bootstrap, map):
81
81
  expect(filter_).to_be_visible()
82
82
  filter_.type("poly")
83
83
  expect(page.get_by_title("Features in this layer: 1/3")).to_be_visible()
84
- expect(page.get_by_title("Features in this layer: 1/3")).to_have_text("1/3")
84
+ expect(page.get_by_title("Features in this layer: 1/3")).to_have_text("(1/3)")
85
85
  expect(page.get_by_text("one point in france")).to_be_hidden()
86
86
  expect(page.get_by_text("one line in new zeland")).to_be_hidden()
87
87
  expect(page.get_by_text("one polygon in greenland")).to_be_visible()
@@ -159,20 +159,19 @@ def test_data_browser_bbox_filter_should_be_persistent(
159
159
  el = page.get_by_text("Current map view")
160
160
  expect(el).to_be_visible()
161
161
  el.click()
162
- browser = page.locator("#umap-ui-container")
162
+ browser = page.locator(".panel.left.on")
163
163
  expect(browser.get_by_text("one point in france")).to_be_visible()
164
164
  expect(browser.get_by_text("one line in new zeland")).to_be_hidden()
165
165
  expect(browser.get_by_text("one polygon in greenland")).to_be_hidden()
166
166
  # Close and reopen the browser to make sure this settings is persistent
167
- close = browser.get_by_text("Close")
167
+ close = browser.get_by_title("Close")
168
168
  close.click()
169
169
  expect(browser).to_be_hidden()
170
170
  sleep(0.5)
171
171
  expect(browser.get_by_text("one point in france")).to_be_hidden()
172
172
  expect(browser.get_by_text("one line in new zeland")).to_be_hidden()
173
173
  expect(browser.get_by_text("one polygon in greenland")).to_be_hidden()
174
- page.get_by_title("See data layers").click()
175
- page.get_by_role("button", name="Browse data").click()
174
+ page.get_by_title("See layers").click()
176
175
  expect(browser.get_by_text("one point in france")).to_be_visible()
177
176
  expect(browser.get_by_text("one line in new zeland")).to_be_hidden()
178
177
  expect(browser.get_by_text("one polygon in greenland")).to_be_hidden()
@@ -185,7 +184,7 @@ def test_data_browser_bbox_filtered_is_clickable(live_server, page, bootstrap, m
185
184
  el = page.get_by_text("Current map view")
186
185
  expect(el).to_be_visible()
187
186
  el.click()
188
- browser = page.locator("#umap-ui-container")
187
+ browser = page.locator(".panel.left.on")
189
188
  expect(browser.get_by_text("one point in france")).to_be_visible()
190
189
  expect(browser.get_by_text("one line in new zeland")).to_be_hidden()
191
190
  expect(browser.get_by_text("one polygon in greenland")).to_be_hidden()
@@ -217,18 +216,6 @@ def test_data_browser_with_variable_in_name(live_server, page, bootstrap, map):
217
216
  expect(page.get_by_text("one polygon in greenland (polygon)")).to_be_visible()
218
217
 
219
218
 
220
- def test_can_open_databrowser_from_layers_list(live_server, map, page, bootstrap):
221
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
222
- page.get_by_title("See data layers").click()
223
- page.get_by_role("button", name="Browse data").click()
224
- browser = page.locator(".umap-browse-data")
225
- expect(browser).to_be_visible()
226
- expect(browser.get_by_text("test datalayer")).to_be_visible()
227
- expect(browser.get_by_text("one point in france")).to_be_visible()
228
- expect(browser.get_by_text("one line in new zeland")).to_be_visible()
229
- expect(browser.get_by_text("one polygon in greenland")).to_be_visible()
230
-
231
-
232
219
  def test_should_sort_features_in_natural_order(live_server, map, page):
233
220
  map.settings["properties"]["onLoadPanel"] = "databrowser"
234
221
  map.save()
@@ -238,7 +225,7 @@ def test_should_sort_features_in_natural_order(live_server, map, page):
238
225
  datalayer_data["features"][2]["properties"]["name"] = "100. a line"
239
226
  DataLayerFactory(map=map, data=datalayer_data)
240
227
  page.goto(f"{live_server.url}{map.get_absolute_url()}")
241
- features = page.locator(".umap-browse-data li")
228
+ features = page.locator(".umap-browser .datalayer li")
242
229
  expect(features).to_have_count(3)
243
230
  expect(features.nth(0)).to_have_text("1. a poly")
244
231
  expect(features.nth(1)).to_have_text("9. a marker")
@@ -249,7 +236,7 @@ def test_should_redraw_list_on_feature_delete(live_server, openmap, page, bootst
249
236
  page.goto(f"{live_server.url}{openmap.get_absolute_url()}")
250
237
  # Enable edit
251
238
  page.get_by_role("button", name="Edit").click()
252
- buttons = page.locator(".umap-browse-data li .feature-delete")
239
+ buttons = page.locator(".umap-browser .datalayer li .icon-delete")
253
240
  expect(buttons).to_have_count(3)
254
241
  page.on("dialog", lambda dialog: dialog.accept())
255
242
  buttons.nth(0).click()
@@ -265,7 +252,7 @@ def test_should_show_header_for_display_on_load_false(
265
252
  datalayer.settings["name"] = "This layer is not loaded"
266
253
  datalayer.save()
267
254
  page.goto(f"{live_server.url}{map.get_absolute_url()}")
268
- browser = page.locator(".umap-browse-data")
255
+ browser = page.locator(".umap-browser")
269
256
  expect(browser).to_be_visible()
270
257
  expect(browser.get_by_text("This layer is not loaded")).to_be_visible()
271
258
 
@@ -279,7 +266,7 @@ def test_should_use_color_variable(live_server, map, page):
279
266
  datalayer_data["features"][2]["properties"]["mycolor"] = "DarkGreen"
280
267
  DataLayerFactory(map=map, data=datalayer_data)
281
268
  page.goto(f"{live_server.url}{map.get_absolute_url()}")
282
- features = page.locator(".umap-browse-data li .feature-color")
269
+ features = page.locator(".umap-browser .datalayer li .feature-color")
283
270
  expect(features).to_have_count(3)
284
271
  # DarkGreen
285
272
  expect(features.nth(0)).to_have_css("background-color", "rgb(0, 100, 0)")
@@ -295,7 +282,7 @@ def test_should_allow_to_toggle_datalayer_visibility(live_server, map, page, boo
295
282
  paths = page.locator(".leaflet-overlay-pane path")
296
283
  expect(markers).to_have_count(1)
297
284
  expect(paths).to_have_count(2)
298
- toggle = page.locator("#umap-ui-container").get_by_title("Show/hide layer")
285
+ toggle = page.locator(".umap-browser").get_by_title("Show/hide layer")
299
286
  toggle.click()
300
287
  expect(markers).to_have_count(0)
301
288
  expect(paths).to_have_count(0)
@@ -303,7 +290,7 @@ def test_should_allow_to_toggle_datalayer_visibility(live_server, map, page, boo
303
290
 
304
291
  def test_should_have_edit_buttons_in_edit_mode(live_server, openmap, page, bootstrap):
305
292
  page.goto(f"{live_server.url}{openmap.get_absolute_url()}")
306
- browser = page.locator("#umap-ui-container")
293
+ browser = page.locator(".umap-browser")
307
294
  edit_layer = browser.get_by_title("Edit", exact=True)
308
295
  in_table = browser.get_by_title("Edit properties in a table")
309
296
  delete_layer = browser.get_by_title("Delete layer")
@@ -49,7 +49,7 @@ def test_basic_choropleth_map_with_custom_brewer(openmap, live_server, page):
49
49
  # Now change brewer from UI
50
50
  page.get_by_role("button", name="Edit").click()
51
51
  page.get_by_role("link", name="Manage layers").click()
52
- page.locator("#umap-ui-container").get_by_title("Edit", exact=True).click()
52
+ page.locator(".panel").get_by_title("Edit", exact=True).click()
53
53
  page.get_by_role("heading", name="Choropleth: settings").click()
54
54
  page.locator('select[name="brewer"]').select_option("Greens")
55
55
 
@@ -36,3 +36,13 @@ def test_dashboard_map_preview(map, live_server, datalayer, login):
36
36
  expect(dialog).to_be_visible()
37
37
  # Let's check we have a marker on it, so we can guess the map loaded correctly
38
38
  expect(dialog.locator(".leaflet-marker-icon")).to_be_visible()
39
+
40
+
41
+ def test_no_delete_button_for_editors(map, live_server, datalayer, login, user):
42
+ map.name = "Map I cannot delete"
43
+ map.editors.add(user)
44
+ map.save()
45
+ page = login(user)
46
+ page.goto(f"{live_server.url}/en/me")
47
+ expect(page.get_by_text("Map I cannot delete")).to_be_visible()
48
+ expect(page.get_by_title("Delete")).to_be_hidden()
@@ -20,14 +20,14 @@ def set_options(datalayer, **options):
20
20
 
21
21
  def test_honour_displayOnLoad_false(map, live_server, datalayer, page):
22
22
  set_options(datalayer, displayOnLoad=False)
23
- page.goto(f"{live_server.url}{map.get_absolute_url()}")
23
+ page.goto(f"{live_server.url}{map.get_absolute_url()}?onLoadPanel=datalayers")
24
24
  expect(page.locator(".leaflet-marker-icon")).to_be_hidden()
25
- layers = page.locator(".umap-browse-datalayers li")
25
+ layers = page.locator(".umap-browser .datalayer")
26
26
  markers = page.locator(".leaflet-marker-icon")
27
- layers_off = page.locator(".umap-browse-datalayers li.off")
27
+ layers_off = page.locator(".umap-browser .datalayer.off")
28
28
  expect(layers).to_have_count(1)
29
29
  expect(layers_off).to_have_count(1)
30
- page.get_by_role("button", name="See data layers").click()
30
+ page.get_by_role("button", name="See layers").click()
31
31
  page.get_by_label("Zoom in").click()
32
32
  expect(markers).to_be_hidden()
33
33
  page.get_by_title("Show/hide layer").click()
@@ -109,10 +109,12 @@ def test_should_honour_color_variable(live_server, map, page):
109
109
 
110
110
 
111
111
  def test_datalayers_in_query_string(live_server, datalayer, map, page):
112
+ map.settings["properties"]["onLoadPanel"] = "datalayers"
113
+ map.save()
112
114
  with_old_id = DataLayerFactory(old_id=134, map=map, name="with old id")
113
115
  set_options(with_old_id, name="with old id")
114
- visible = page.locator(".leaflet-control-browse li:not(.off) span")
115
- hidden = page.locator(".leaflet-control-browse li.off span")
116
+ visible = page.locator(".umap-browser .datalayer:not(.off) .datalayer-name")
117
+ hidden = page.locator(".umap-browser .datalayer.off .datalayer-name")
116
118
  page.goto(f"{live_server.url}{map.get_absolute_url()}")
117
119
  expect(visible).to_have_count(2)
118
120
  expect(hidden).to_have_count(0)
@@ -1,3 +1,4 @@
1
+ import platform
1
2
  import re
2
3
 
3
4
  from playwright.sync_api import expect
@@ -11,16 +12,13 @@ def test_should_have_fieldset_for_layer_type_properties(page, live_server, tilel
11
12
  page.goto(f"{live_server.url}/en/map/new/")
12
13
 
13
14
  # Open DataLayers list
14
- button = page.get_by_title("Manage Layers")
15
- expect(button).to_be_visible()
16
- button.click()
15
+ page.get_by_title("Manage layers").click()
17
16
 
18
17
  # Create a layer
19
- page.get_by_title("Manage layers").click()
20
- page.get_by_role("button", name="Add a layer").click()
18
+ page.get_by_title("Add a layer").click()
21
19
  page.locator("input[name=name]").fill("Layer 1")
22
20
 
23
- select = page.locator("#umap-ui-container .umap-field-type select")
21
+ select = page.locator(".panel.on .umap-field-type select")
24
22
  expect(select).to_be_visible()
25
23
 
26
24
  choropleth_header = page.get_by_text("Choropleth: settings")
@@ -56,32 +54,32 @@ def test_cancel_deleting_datalayer_should_restore(
56
54
  live_server, openmap, datalayer, page
57
55
  ):
58
56
  page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
59
- layers = page.locator(".umap-browse-datalayers li")
57
+ page.get_by_title("See layers").click()
58
+ layers = page.locator(".umap-browser .datalayer")
60
59
  markers = page.locator(".leaflet-marker-icon")
61
60
  expect(layers).to_have_count(1)
62
61
  expect(markers).to_have_count(1)
63
62
  page.get_by_role("link", name="Manage layers").click()
64
63
  page.once("dialog", lambda dialog: dialog.accept())
65
- page.locator("#umap-ui-container").get_by_title("Delete layer").click()
64
+ page.locator(".panel.right").get_by_title("Delete layer").click()
66
65
  expect(markers).to_have_count(0)
67
- page.get_by_role("button", name="See data layers").click()
66
+ page.get_by_role("button", name="See layers").click()
68
67
  expect(page.get_by_text("test datalayer")).to_be_hidden()
69
68
  page.once("dialog", lambda dialog: dialog.accept())
70
69
  page.get_by_role("button", name="Cancel edits").click()
71
70
  expect(markers).to_have_count(1)
72
- expect(
73
- page.locator(".leaflet-control-browse").get_by_text("test datalayer")
74
- ).to_be_visible()
71
+ expect(page.locator(".umap-browser").get_by_text("test datalayer")).to_be_visible()
75
72
 
76
73
 
77
74
  def test_can_clone_datalayer(live_server, openmap, login, datalayer, page):
78
75
  page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
79
- layers = page.locator(".umap-browse-datalayers li")
76
+ page.get_by_title("See layers").click()
77
+ layers = page.locator(".umap-browser .datalayer")
80
78
  markers = page.locator(".leaflet-marker-icon")
81
79
  expect(layers).to_have_count(1)
82
80
  expect(markers).to_have_count(1)
83
81
  page.get_by_role("link", name="Manage layers").click()
84
- page.locator("#umap-ui-container").get_by_title("Edit", exact=True).click()
82
+ page.locator(".panel.right").get_by_title("Edit", exact=True).click()
85
83
  page.get_by_role("heading", name="Advanced actions").click()
86
84
  page.get_by_role("button", name="Clone").click()
87
85
  expect(layers).to_have_count(2)
@@ -105,7 +103,7 @@ def test_can_change_icon_class(live_server, openmap, page):
105
103
  expect(page.locator(".umap-div-icon")).to_be_visible()
106
104
  page.get_by_role("link", name="Manage layers").click()
107
105
  expect(page.locator(".umap-circle-icon")).to_be_hidden()
108
- page.locator("#umap-ui-container").get_by_title("Edit", exact=True).click()
106
+ page.locator(".panel.right").get_by_title("Edit", exact=True).click()
109
107
  page.get_by_role("heading", name="Shape properties").click()
110
108
  page.locator(".umap-field-iconClass a.define").click()
111
109
  page.get_by_text("Circle").click()
@@ -118,12 +116,12 @@ def test_can_change_name(live_server, openmap, page, datalayer):
118
116
  f"{live_server.url}{openmap.get_absolute_url()}?edit&datalayersControl=expanded"
119
117
  )
120
118
  page.get_by_role("link", name="Manage layers").click()
121
- page.locator("#umap-ui-container").get_by_title("Edit", exact=True).click()
119
+ page.locator(".panel.right").get_by_title("Edit", exact=True).click()
122
120
  expect(page.locator(".umap-is-dirty")).to_be_hidden()
123
121
  page.locator('input[name="name"]').click()
124
122
  page.locator('input[name="name"]').press("Control+a")
125
123
  page.locator('input[name="name"]').fill("new name")
126
- expect(page.locator(".leaflet-control-browse li span")).to_contain_text("new name")
124
+ expect(page.locator(".umap-browser .datalayer")).to_contain_text("new name")
127
125
  expect(page.locator(".umap-is-dirty")).to_be_visible()
128
126
  with page.expect_response(re.compile(".*/datalayer/update/.*")):
129
127
  page.get_by_role("button", name="Save").click()
@@ -149,7 +147,7 @@ def test_can_create_new_datalayer(live_server, openmap, page, datalayer):
149
147
  expect(page.locator(".umap-is-dirty")).to_be_hidden()
150
148
  # Edit again, it should not create a new datalayer
151
149
  page.get_by_role("link", name="Manage layers").click()
152
- page.locator("#umap-ui-container").get_by_title("Edit", exact=True).first.click()
150
+ page.locator(".panel.right").get_by_title("Edit", exact=True).first.click()
153
151
  page.locator('input[name="name"]').click()
154
152
  page.locator('input[name="name"]').fill("my new layer with a new name")
155
153
  expect(page.get_by_text("my new layer with a new name")).to_be_visible()
@@ -173,8 +171,15 @@ def test_can_restore_version(live_server, openmap, page, datalayer):
173
171
  page.get_by_role("button", name="Save").click()
174
172
  expect(marker).to_have_class(re.compile(".*umap-div-icon.*"))
175
173
  page.get_by_role("link", name="Manage layers").click()
176
- page.locator("#umap-ui-container").get_by_title("Edit", exact=True).click()
174
+ page.locator(".panel.right").get_by_title("Edit", exact=True).click()
177
175
  page.get_by_role("heading", name="Versions").click()
178
176
  page.once("dialog", lambda dialog: dialog.accept())
179
177
  page.get_by_role("button", name="Restore this version").last.click()
180
178
  expect(marker).to_have_class(re.compile(".*umap-ball-icon.*"))
179
+
180
+
181
+ def test_can_edit_layer_on_ctrl_shift_click(live_server, openmap, page, datalayer):
182
+ modifier = "Meta" if platform.system() == "Darwin" else "Control"
183
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
184
+ page.locator(".leaflet-marker-icon").click(modifiers=[modifier, "Shift"])
185
+ expect(page.get_by_role("heading", name="Layer properties")).to_be_visible()
@@ -1,15 +1,195 @@
1
+ import re
2
+
1
3
  from playwright.sync_api import expect
2
4
 
5
+ from umap.models import DataLayer, Map
6
+
7
+ from ..base import DataLayerFactory
8
+
3
9
 
4
10
  def test_can_edit_name(page, live_server, tilelayer):
5
11
  page.goto(f"{live_server.url}/en/map/new/")
6
12
 
7
- page.get_by_title("Edit map properties").click()
13
+ page.get_by_title("Edit map name and caption").click()
8
14
  name_input = page.locator('.map-metadata input[name="name"]')
9
15
  expect(name_input).to_be_visible()
10
16
  name_input.click()
11
17
  name_input.press("Control+a")
12
18
  name_input.fill("New map name")
13
- expect(page.locator(".umap-main-edit-toolbox .map-name")).to_have_text(
19
+ expect(page.locator(".umap-main-edit-toolbox .map-name").nth(0)).to_have_text(
14
20
  "New map name"
15
21
  )
22
+
23
+
24
+ def test_map_name_impacts_ui(live_server, page, tilelayer):
25
+ page.goto(f"{live_server.url}/en/map/new/")
26
+
27
+ gear_icon = page.get_by_title("Edit map name and caption")
28
+ expect(gear_icon).to_be_visible()
29
+ gear_icon.click()
30
+
31
+ name_input = page.locator("form").locator('input[name="name"]').first
32
+ expect(name_input).to_be_visible()
33
+
34
+ name_input.fill("something else")
35
+
36
+ expect(page.get_by_role("button", name="something else").nth(1)).to_be_visible()
37
+
38
+
39
+ def test_zoomcontrol_impacts_ui(live_server, page, tilelayer):
40
+ page.goto(f"{live_server.url}/en/map/new/")
41
+
42
+ gear_icon = page.get_by_title("Map advanced properties")
43
+ expect(gear_icon).to_be_visible()
44
+ gear_icon.click()
45
+
46
+ # Should be visible by default
47
+ zoom_in = page.get_by_label("Zoom in")
48
+ zoom_out = page.get_by_label("Zoom out")
49
+
50
+ expect(zoom_in).to_be_visible()
51
+ expect(zoom_out).to_be_visible()
52
+
53
+ # Hide them
54
+ page.get_by_role("heading", name="User interface options").click()
55
+ hide_zoom_controls = (
56
+ page.locator("div")
57
+ .filter(has_text=re.compile(r"^Display the zoom control"))
58
+ .locator("label")
59
+ .nth(2)
60
+ )
61
+ hide_zoom_controls.click()
62
+
63
+ expect(zoom_in).to_be_hidden()
64
+ expect(zoom_out).to_be_hidden()
65
+
66
+
67
+ def test_map_color_impacts_data(live_server, page, tilelayer):
68
+ page.goto(f"{live_server.url}/en/map/new/")
69
+
70
+ gear_icon = page.get_by_title("Map advanced properties")
71
+ expect(gear_icon).to_be_visible()
72
+ gear_icon.click()
73
+
74
+ # Click on the Draw a marker button on a new map.
75
+ create_marker_p1 = page.get_by_title("Draw a marker")
76
+ expect(create_marker_p1).to_be_visible()
77
+ create_marker_p1.click()
78
+
79
+ # Add a new marker
80
+ marker_pane_p1 = page.locator(".leaflet-marker-pane > div")
81
+ map_el = page.locator("#map")
82
+ map_el.click(position={"x": 200, "y": 200})
83
+ expect(marker_pane_p1).to_have_count(1)
84
+
85
+ # Change the default color
86
+ page.get_by_role("heading", name="Shape properties").click()
87
+ page.locator("#umap-feature-shape-properties").get_by_text("define").first.click()
88
+ page.get_by_title("Lime", exact=True).click()
89
+
90
+ # Assert the new color was used
91
+ marker_style = page.locator(".leaflet-marker-icon .icon_container").get_attribute(
92
+ "style"
93
+ )
94
+ assert "lime" in marker_style
95
+
96
+
97
+ def test_limitbounds_impacts_ui(live_server, page, tilelayer):
98
+ page.goto(f"{live_server.url}/en/map/new/")
99
+
100
+ gear_icon = page.get_by_title("Map advanced properties")
101
+ expect(gear_icon).to_be_visible()
102
+ gear_icon.click()
103
+
104
+ page.get_by_role("heading", name="Limit bounds").click()
105
+ default_zoom_url = f"{live_server.url}/en/map/new/#5/51.110/7.053"
106
+ page.goto(default_zoom_url)
107
+ page.get_by_role("button", name="Use current bounds").click()
108
+
109
+ zoom_in = page.get_by_label("Zoom in")
110
+ zoom_out = page.get_by_label("Zoom out")
111
+
112
+ # It should be possible to zoom in
113
+ zoom_in.click()
114
+ page.wait_for_timeout(500)
115
+ assert page.url != default_zoom_url
116
+
117
+ # But not to zoom out of the window
118
+ zoom_out.click() # back to normal
119
+ page.wait_for_timeout(500)
120
+ assert "leaflet-disabled" in zoom_out.get_attribute("class")
121
+
122
+
123
+ def test_sortkey_impacts_datalayerindex(map, live_server, page):
124
+ # Create points with a "key" property.
125
+ # But we want them to sort by key (First, Second, Third)
126
+ DataLayerFactory(
127
+ map=map,
128
+ data={
129
+ "type": "FeatureCollection",
130
+ "features": [
131
+ {
132
+ "type": "Feature",
133
+ "geometry": {
134
+ "type": "Point",
135
+ "coordinates": [13.6, 48.5],
136
+ },
137
+ "properties": {"name": "Z First", "key": "1st Point"},
138
+ },
139
+ {
140
+ "type": "Feature",
141
+ "geometry": {
142
+ "type": "Point",
143
+ "coordinates": [13.7, 48.4],
144
+ },
145
+ "properties": {"name": "Y Second", "key": "2d Point"},
146
+ },
147
+ {
148
+ "type": "Feature",
149
+ "geometry": {
150
+ "type": "Point",
151
+ "coordinates": [13.5, 48.6],
152
+ },
153
+ "properties": {"name": "X Third", "key": "3rd Point"},
154
+ },
155
+ ],
156
+ },
157
+ )
158
+ map.edit_status = Map.ANONYMOUS
159
+ datalayer = map.datalayer_set.first()
160
+ datalayer.edit_status = DataLayer.ANONYMOUS
161
+ datalayer.save()
162
+ map.save()
163
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
164
+
165
+ # By default, features are sorted by name (Third, Second, First)
166
+ page.get_by_role("button", name="See layers").click()
167
+ page.get_by_role("heading", name="Show/hide layer").locator("i").click()
168
+
169
+ first_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(0)
170
+ second_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(1)
171
+ third_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(2)
172
+ assert "X Third" == first_listed_feature.text_content()
173
+ assert "Y Second" == second_listed_feature.text_content()
174
+ assert "Z First" == third_listed_feature.text_content()
175
+
176
+ # Change the default sortkey to be "key"
177
+ page.get_by_role("button", name="Edit").click()
178
+ page.get_by_role("link", name="Map advanced properties").click()
179
+ page.get_by_role("heading", name="Default properties").click()
180
+
181
+ # Click "define"
182
+ page.locator(".panel .umap-field-sortKey .define").click()
183
+ page.locator('input[name="sortKey"]').click()
184
+ page.locator('input[name="sortKey"]').fill("key")
185
+
186
+ # Click the checkmark to apply the changes
187
+ page.locator(".panel .umap-field-sortKey .blur-button").click()
188
+
189
+ # Features should be sorted by key (First, Second, Third)
190
+ first_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(0)
191
+ second_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(1)
192
+ third_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(2)
193
+ assert "Z First" == first_listed_feature.text_content()
194
+ assert "Y Second" == second_listed_feature.text_content()
195
+ assert "X Third" == third_listed_feature.text_content()