umap-project 2.1.2__py3-none-any.whl → 2.2.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 (211) 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 +10 -6
  11. umap/settings/base.py +1 -0
  12. umap/static/umap/base.css +43 -156
  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 +97 -73
  25. umap/static/umap/js/modules/dompurify.js +12 -0
  26. umap/static/umap/js/modules/facets.js +149 -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.autocomplete.js +40 -25
  36. umap/static/umap/js/umap.controls.js +248 -361
  37. umap/static/umap/js/umap.core.js +77 -366
  38. umap/static/umap/js/umap.datalayer.permissions.js +1 -1
  39. umap/static/umap/js/umap.features.js +65 -43
  40. umap/static/umap/js/umap.forms.js +128 -36
  41. umap/static/umap/js/umap.icon.js +11 -4
  42. umap/static/umap/js/umap.importer.js +78 -58
  43. umap/static/umap/js/umap.js +206 -192
  44. umap/static/umap/js/umap.layer.js +86 -46
  45. umap/static/umap/js/umap.permissions.js +13 -9
  46. umap/static/umap/js/umap.popup.js +26 -30
  47. umap/static/umap/js/umap.share.js +12 -9
  48. umap/static/umap/js/umap.tableeditor.js +4 -6
  49. umap/static/umap/js/umap.ui.js +10 -60
  50. umap/static/umap/locale/am_ET.js +243 -227
  51. umap/static/umap/locale/am_ET.json +21 -9
  52. umap/static/umap/locale/ar.js +243 -227
  53. umap/static/umap/locale/ar.json +21 -9
  54. umap/static/umap/locale/ast.js +243 -227
  55. umap/static/umap/locale/ast.json +21 -9
  56. umap/static/umap/locale/bg.js +243 -227
  57. umap/static/umap/locale/bg.json +21 -9
  58. umap/static/umap/locale/br.js +253 -237
  59. umap/static/umap/locale/br.json +25 -13
  60. umap/static/umap/locale/ca.js +243 -227
  61. umap/static/umap/locale/ca.json +21 -9
  62. umap/static/umap/locale/cs_CZ.js +243 -227
  63. umap/static/umap/locale/cs_CZ.json +21 -9
  64. umap/static/umap/locale/da.js +243 -227
  65. umap/static/umap/locale/da.json +21 -9
  66. umap/static/umap/locale/de.js +243 -227
  67. umap/static/umap/locale/de.json +21 -9
  68. umap/static/umap/locale/el.js +243 -227
  69. umap/static/umap/locale/el.json +21 -9
  70. umap/static/umap/locale/en.js +243 -234
  71. umap/static/umap/locale/en.json +22 -10
  72. umap/static/umap/locale/en_US.json +21 -9
  73. umap/static/umap/locale/es.js +243 -227
  74. umap/static/umap/locale/es.json +21 -9
  75. umap/static/umap/locale/et.js +243 -227
  76. umap/static/umap/locale/et.json +21 -9
  77. umap/static/umap/locale/eu.js +227 -199
  78. umap/static/umap/locale/eu.json +1 -1
  79. umap/static/umap/locale/fa_IR.js +243 -227
  80. umap/static/umap/locale/fa_IR.json +21 -9
  81. umap/static/umap/locale/fi.js +243 -227
  82. umap/static/umap/locale/fi.json +21 -9
  83. umap/static/umap/locale/fr.js +243 -234
  84. umap/static/umap/locale/fr.json +21 -9
  85. umap/static/umap/locale/gl.js +243 -227
  86. umap/static/umap/locale/gl.json +21 -9
  87. umap/static/umap/locale/he.js +243 -227
  88. umap/static/umap/locale/he.json +21 -9
  89. umap/static/umap/locale/hr.js +243 -227
  90. umap/static/umap/locale/hr.json +21 -9
  91. umap/static/umap/locale/hu.js +243 -234
  92. umap/static/umap/locale/hu.json +21 -9
  93. umap/static/umap/locale/id.js +243 -227
  94. umap/static/umap/locale/id.json +21 -9
  95. umap/static/umap/locale/is.js +243 -227
  96. umap/static/umap/locale/is.json +21 -9
  97. umap/static/umap/locale/it.js +243 -234
  98. umap/static/umap/locale/it.json +21 -9
  99. umap/static/umap/locale/ja.js +243 -227
  100. umap/static/umap/locale/ja.json +21 -9
  101. umap/static/umap/locale/ko.js +243 -227
  102. umap/static/umap/locale/ko.json +21 -9
  103. umap/static/umap/locale/lt.js +243 -227
  104. umap/static/umap/locale/lt.json +21 -9
  105. umap/static/umap/locale/ms.js +243 -234
  106. umap/static/umap/locale/ms.json +22 -10
  107. umap/static/umap/locale/nl.js +246 -230
  108. umap/static/umap/locale/nl.json +21 -9
  109. umap/static/umap/locale/no.js +243 -227
  110. umap/static/umap/locale/no.json +21 -9
  111. umap/static/umap/locale/pl.js +243 -227
  112. umap/static/umap/locale/pl.json +21 -9
  113. umap/static/umap/locale/pl_PL.json +21 -9
  114. umap/static/umap/locale/pt.js +243 -227
  115. umap/static/umap/locale/pt.json +21 -9
  116. umap/static/umap/locale/pt_BR.js +243 -227
  117. umap/static/umap/locale/pt_BR.json +21 -9
  118. umap/static/umap/locale/pt_PT.js +243 -227
  119. umap/static/umap/locale/pt_PT.json +21 -9
  120. umap/static/umap/locale/ro.js +243 -227
  121. umap/static/umap/locale/ro.json +21 -9
  122. umap/static/umap/locale/ru.js +243 -227
  123. umap/static/umap/locale/ru.json +21 -9
  124. umap/static/umap/locale/si.js +1 -1
  125. umap/static/umap/locale/si.json +1 -1
  126. umap/static/umap/locale/sk_SK.js +243 -227
  127. umap/static/umap/locale/sk_SK.json +21 -9
  128. umap/static/umap/locale/sl.js +243 -227
  129. umap/static/umap/locale/sl.json +21 -9
  130. umap/static/umap/locale/sr.js +243 -227
  131. umap/static/umap/locale/sr.json +21 -9
  132. umap/static/umap/locale/sv.js +243 -227
  133. umap/static/umap/locale/sv.json +21 -9
  134. umap/static/umap/locale/th_TH.js +243 -227
  135. umap/static/umap/locale/th_TH.json +21 -9
  136. umap/static/umap/locale/tr.js +243 -227
  137. umap/static/umap/locale/tr.json +21 -9
  138. umap/static/umap/locale/uk_UA.js +243 -227
  139. umap/static/umap/locale/uk_UA.json +21 -9
  140. umap/static/umap/locale/vi.js +243 -227
  141. umap/static/umap/locale/vi.json +21 -9
  142. umap/static/umap/locale/vi_VN.json +21 -9
  143. umap/static/umap/locale/zh.js +243 -227
  144. umap/static/umap/locale/zh.json +21 -9
  145. umap/static/umap/locale/zh_CN.json +21 -9
  146. umap/static/umap/locale/zh_TW.Big5.json +21 -9
  147. umap/static/umap/locale/zh_TW.js +243 -234
  148. umap/static/umap/locale/zh_TW.json +21 -9
  149. umap/static/umap/map.css +124 -264
  150. umap/static/umap/test/DataLayer.js +1 -1
  151. umap/static/umap/test/Feature.js +0 -226
  152. umap/static/umap/test/Map.js +0 -304
  153. umap/static/umap/test/Polygon.js +0 -256
  154. umap/static/umap/test/Polyline.js +0 -116
  155. umap/static/umap/test/TableEditor.js +10 -10
  156. umap/static/umap/test/Util.js +0 -521
  157. umap/static/umap/test/index.html +1 -5
  158. umap/static/umap/unittests/URLs.js +1 -1
  159. umap/static/umap/unittests/utils.js +610 -0
  160. umap/static/umap/vars.css +9 -0
  161. umap/static/umap/vendors/dompurify/purify.es.mjs +1525 -0
  162. umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +1 -0
  163. umap/static/umap/vendors/iconlayers/iconLayers.js +1 -1
  164. umap/templates/umap/css.html +2 -0
  165. umap/templates/umap/js.html +0 -1
  166. umap/templates/umap/map_detail.html +4 -0
  167. umap/templates/umap/map_table.html +12 -10
  168. umap/templatetags/umap_tags.py +5 -0
  169. umap/tests/conftest.py +9 -0
  170. umap/tests/fixtures/test_upload_data.csv +2 -1
  171. umap/tests/fixtures/test_upload_data.umap +171 -0
  172. umap/tests/fixtures/test_upload_data_osm.json +33 -0
  173. umap/tests/integration/conftest.py +16 -0
  174. umap/tests/integration/test_anonymous_owned_map.py +30 -5
  175. umap/tests/integration/test_basics.py +21 -0
  176. umap/tests/integration/test_browser.py +16 -36
  177. umap/tests/integration/test_choropleth.py +89 -0
  178. umap/tests/integration/test_collaborative_editing.py +30 -1
  179. umap/tests/integration/test_dashboard.py +10 -0
  180. umap/tests/integration/test_datalayer.py +132 -0
  181. umap/tests/integration/test_draw_polygon.py +363 -0
  182. umap/tests/integration/test_draw_polyline.py +325 -0
  183. umap/tests/integration/test_edit_datalayer.py +145 -6
  184. umap/tests/integration/test_edit_map.py +202 -0
  185. umap/tests/integration/test_edit_marker.py +120 -0
  186. umap/tests/integration/test_edit_polygon.py +122 -0
  187. umap/tests/integration/test_facets_browser.py +132 -11
  188. umap/tests/integration/test_import.py +407 -10
  189. umap/tests/integration/test_map.py +36 -54
  190. umap/tests/integration/test_map_list.py +28 -0
  191. umap/tests/integration/test_owned_map.py +24 -6
  192. umap/tests/integration/test_picto.py +25 -38
  193. umap/tests/integration/test_querystring.py +9 -15
  194. umap/tests/integration/test_slideshow.py +0 -5
  195. umap/tests/integration/test_statics.py +3 -2
  196. umap/tests/integration/test_tableeditor.py +23 -0
  197. umap/tests/integration/test_tilelayer.py +10 -0
  198. umap/tests/integration/test_view_marker.py +64 -0
  199. umap/tests/integration/test_view_polygon.py +59 -0
  200. umap/tests/integration/test_view_polyline.py +51 -0
  201. umap/tests/test_map_views.py +13 -0
  202. {umap_project-2.1.2.dist-info → umap_project-2.2.0.dist-info}/METADATA +12 -12
  203. {umap_project-2.1.2.dist-info → umap_project-2.2.0.dist-info}/RECORD +206 -187
  204. {umap_project-2.1.2.dist-info → umap_project-2.2.0.dist-info}/WHEEL +1 -1
  205. umap/static/umap/test/Choropleth.js +0 -245
  206. umap/static/umap/test/Permissions.js +0 -74
  207. umap/static/umap/vendors/dompurify/purify.min.js +0 -3
  208. umap/static/umap/vendors/dompurify/purify.min.js.map +0 -1
  209. umap/tests/integration/test_drawing.py +0 -243
  210. {umap_project-2.1.2.dist-info → umap_project-2.2.0.dist-info}/entry_points.txt +0 -0
  211. {umap_project-2.1.2.dist-info → umap_project-2.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,325 @@
1
+ import json
2
+ import re
3
+ from pathlib import Path
4
+
5
+ import pytest
6
+ from playwright.sync_api import expect
7
+
8
+ from umap.models import DataLayer
9
+
10
+ pytestmark = pytest.mark.django_db
11
+
12
+
13
+ def save_and_get_json(page):
14
+ with page.expect_response(re.compile(r".*/datalayer/create/.*")):
15
+ page.get_by_role("button", name="Save").click()
16
+ datalayer = DataLayer.objects.last()
17
+ return json.loads(Path(datalayer.geojson.path).read_text())
18
+
19
+
20
+ def test_draw_polyline(page, live_server, tilelayer):
21
+ page.goto(f"{live_server.url}/en/map/new/")
22
+
23
+ # Click on the Draw a line button on a new map.
24
+ create_line = page.locator(".leaflet-control-toolbar ").get_by_title(
25
+ "Draw a polyline"
26
+ )
27
+ create_line.click()
28
+
29
+ # Check no line is present by default.
30
+ # We target with the color, because there is also the drawing line guide (dash-array)
31
+ # around
32
+ lines = page.locator(".leaflet-overlay-pane path[stroke='DarkBlue']")
33
+ guide = page.locator(".leaflet-overlay-pane > svg > g > path")
34
+ expect(lines).to_have_count(0)
35
+ expect(guide).to_have_count(0)
36
+
37
+ # Click on the map, it will create a line.
38
+ map = page.locator("#map")
39
+ map.click(position={"x": 200, "y": 200})
40
+ expect(lines).to_have_count(1)
41
+ expect(guide).to_have_count(1)
42
+ map.click(position={"x": 100, "y": 200})
43
+ expect(lines).to_have_count(1)
44
+ expect(guide).to_have_count(1)
45
+ map.click(position={"x": 100, "y": 100})
46
+ expect(lines).to_have_count(1)
47
+ expect(guide).to_have_count(1)
48
+ # Click again to finish
49
+ map.click(position={"x": 100, "y": 100})
50
+ expect(lines).to_have_count(1)
51
+ expect(guide).to_have_count(0)
52
+
53
+
54
+ def test_clicking_esc_should_finish_line(page, live_server, tilelayer):
55
+ page.goto(f"{live_server.url}/en/map/new/")
56
+
57
+ # Click on the Draw a line button on a new map.
58
+ create_line = page.locator(".leaflet-control-toolbar ").get_by_title(
59
+ "Draw a polyline"
60
+ )
61
+ create_line.click()
62
+
63
+ # Check no line is present by default.
64
+ # We target with the color, because there is also the drawing line guide (dash-array)
65
+ # around
66
+ lines = page.locator(".leaflet-overlay-pane path[stroke='DarkBlue']")
67
+ guide = page.locator(".leaflet-overlay-pane > svg > g > path")
68
+ expect(lines).to_have_count(0)
69
+ expect(guide).to_have_count(0)
70
+
71
+ # Click on the map, it will create a line.
72
+ map = page.locator("#map")
73
+ map.click(position={"x": 200, "y": 200})
74
+ expect(lines).to_have_count(1)
75
+ expect(guide).to_have_count(1)
76
+ map.click(position={"x": 100, "y": 200})
77
+ expect(lines).to_have_count(1)
78
+ expect(guide).to_have_count(1)
79
+ map.click(position={"x": 100, "y": 100})
80
+ expect(lines).to_have_count(1)
81
+ expect(guide).to_have_count(1)
82
+ # Click ESC to finish
83
+ page.keyboard.press("Escape")
84
+ expect(lines).to_have_count(1)
85
+ expect(guide).to_have_count(0)
86
+
87
+
88
+ def test_clicking_esc_should_delete_line_if_empty(page, live_server, tilelayer):
89
+ page.goto(f"{live_server.url}/en/map/new/")
90
+
91
+ # Click on the Draw a line button on a new map.
92
+ create_line = page.locator(".leaflet-control-toolbar ").get_by_title(
93
+ "Draw a polyline"
94
+ )
95
+ create_line.click()
96
+
97
+ # Check no line is present by default.
98
+ # We target with the color, because there is also the drawing line guide (dash-array)
99
+ # around
100
+ lines = page.locator(".leaflet-overlay-pane path[stroke='DarkBlue']")
101
+ guide = page.locator(".leaflet-overlay-pane > svg > g > path")
102
+ expect(lines).to_have_count(0)
103
+ expect(guide).to_have_count(0)
104
+
105
+ map = page.locator("#map")
106
+ map.click(position={"x": 200, "y": 200})
107
+ # At this stage, the line as one element, it should not be created
108
+ # on pressing esc, as invalid
109
+ # Click ESC to finish
110
+ page.keyboard.press("Escape")
111
+ expect(lines).to_have_count(0)
112
+ expect(guide).to_have_count(0)
113
+
114
+
115
+ def test_clicking_esc_should_delete_line_if_invalid(page, live_server, tilelayer):
116
+ page.goto(f"{live_server.url}/en/map/new/")
117
+
118
+ # Click on the Draw a line button on a new map.
119
+ create_line = page.locator(".leaflet-control-toolbar ").get_by_title(
120
+ "Draw a polyline"
121
+ )
122
+ create_line.click()
123
+
124
+ # Check no line is present by default.
125
+ # We target with the color, because there is also the drawing line guide (dash-array)
126
+ # around
127
+ lines = page.locator(".leaflet-overlay-pane path[stroke='DarkBlue']")
128
+ guide = page.locator(".leaflet-overlay-pane > svg > g > path")
129
+ expect(lines).to_have_count(0)
130
+ expect(guide).to_have_count(0)
131
+
132
+ # At this stage, the line as no element, it should not be created
133
+ # on pressing esc
134
+ # Click ESC to finish
135
+ page.keyboard.press("Escape")
136
+ expect(lines).to_have_count(0)
137
+ expect(guide).to_have_count(0)
138
+
139
+
140
+ def test_can_draw_multi(live_server, page, tilelayer):
141
+ page.goto(f"{live_server.url}/en/map/new/")
142
+ lines = page.locator(".leaflet-overlay-pane path")
143
+ expect(lines).to_have_count(0)
144
+ add_shape = page.get_by_title("Add a line to the current multi")
145
+ expect(add_shape).to_be_hidden()
146
+ page.get_by_title("Draw a polyline").click()
147
+ map = page.locator("#map")
148
+ map.click(position={"x": 200, "y": 100})
149
+ map.click(position={"x": 100, "y": 100})
150
+ map.click(position={"x": 100, "y": 200})
151
+ # Click again to finish
152
+ map.click(position={"x": 100, "y": 200})
153
+ expect(add_shape).to_be_visible()
154
+ expect(lines).to_have_count(1)
155
+ add_shape.click()
156
+ map.click(position={"x": 250, "y": 250})
157
+ map.click(position={"x": 200, "y": 250})
158
+ map.click(position={"x": 200, "y": 200})
159
+ # Click again to finish
160
+ map.click(position={"x": 200, "y": 200})
161
+ expect(lines).to_have_count(1)
162
+ page.keyboard.press("Escape")
163
+ expect(add_shape).to_be_hidden()
164
+ lines.first.click(button="right", position={"x": 10, "y": 1})
165
+ expect(page.get_by_role("link", name="Transform to polygon")).to_be_hidden()
166
+ expect(page.get_by_role("link", name="Remove shape from the multi")).to_be_visible()
167
+
168
+
169
+ def test_can_transfer_shape_from_simple_polyline(live_server, page, tilelayer):
170
+ page.goto(f"{live_server.url}/en/map/new/")
171
+ lines = page.locator(".leaflet-overlay-pane path")
172
+ expect(lines).to_have_count(0)
173
+ page.get_by_title("Draw a polyline").click()
174
+ map = page.locator("#map")
175
+
176
+ # Draw a first line
177
+ map.click(position={"x": 200, "y": 100})
178
+ map.click(position={"x": 100, "y": 100})
179
+ map.click(position={"x": 100, "y": 200})
180
+ # Click again to finish
181
+ map.click(position={"x": 100, "y": 200})
182
+ expect(lines).to_have_count(1)
183
+
184
+ # Draw another polygon
185
+ page.get_by_title("Draw a polyline").click()
186
+ map.click(position={"x": 250, "y": 250})
187
+ map.click(position={"x": 200, "y": 250})
188
+ map.click(position={"x": 200, "y": 200})
189
+ # Click again to finish
190
+ map.click(position={"x": 200, "y": 200})
191
+ expect(lines).to_have_count(2)
192
+
193
+ # Now that polygon 2 is selected, right click on first one
194
+ # and transfer shape
195
+ lines.first.click(position={"x": 10, "y": 1}, button="right")
196
+ page.get_by_role("link", name="Transfer shape to edited feature").click()
197
+ expect(lines).to_have_count(1)
198
+
199
+
200
+ def test_can_transfer_shape_from_multi(live_server, page, tilelayer, settings):
201
+ settings.UMAP_ALLOW_ANONYMOUS = True
202
+ page.goto(f"{live_server.url}/en/map/new/")
203
+ lines = page.locator(".leaflet-overlay-pane path")
204
+ expect(lines).to_have_count(0)
205
+ page.get_by_title("Draw a polyline").click()
206
+ map = page.locator("#map")
207
+
208
+ # Draw a multi line
209
+ map.click(position={"x": 200, "y": 100})
210
+ map.click(position={"x": 100, "y": 100})
211
+ map.click(position={"x": 100, "y": 200})
212
+ # Click again to finish
213
+ map.click(position={"x": 100, "y": 200})
214
+ expect(lines).to_have_count(1)
215
+ page.get_by_title("Add a line to the current multi").click()
216
+ map.click(position={"x": 250, "y": 250})
217
+ map.click(position={"x": 200, "y": 250})
218
+ map.click(position={"x": 200, "y": 200})
219
+ # Click again to finish
220
+ map.click(position={"x": 200, "y": 200})
221
+ expect(lines).to_have_count(1)
222
+
223
+ # Draw another line
224
+ page.get_by_title("Draw a polyline").click()
225
+ map.click(position={"x": 350, "y": 350})
226
+ map.click(position={"x": 300, "y": 350})
227
+ map.click(position={"x": 300, "y": 300})
228
+ # Click again to finish
229
+ map.click(position={"x": 300, "y": 300})
230
+ expect(lines).to_have_count(2)
231
+
232
+ # Now that polygon 2 is selected, right click on first one
233
+ # and transfer shape
234
+ lines.first.click(position={"x": 10, "y": 1}, button="right")
235
+ page.get_by_role("link", name="Transfer shape to edited feature").click()
236
+ expect(lines).to_have_count(2)
237
+ data = save_and_get_json(page)
238
+ # FIXME this should be a LineString, not MultiLineString
239
+ assert data["features"][0]["geometry"] == {
240
+ "coordinates": [
241
+ [[-6.569824, 52.49616], [-7.668457, 52.49616], [-7.668457, 53.159947]]
242
+ ],
243
+ "type": "MultiLineString",
244
+ }
245
+ assert data["features"][1]["geometry"] == {
246
+ "coordinates": [
247
+ [[-4.372559, 51.138001], [-5.471191, 51.138001], [-5.471191, 51.822198]],
248
+ [[-7.668457, 54.457267], [-9.865723, 54.457267], [-9.865723, 53.159947]],
249
+ ],
250
+ "type": "MultiLineString",
251
+ }
252
+
253
+
254
+ def test_can_extract_shape(live_server, page, tilelayer):
255
+ page.goto(f"{live_server.url}/en/map/new/")
256
+ lines = page.locator(".leaflet-overlay-pane path")
257
+ expect(lines).to_have_count(0)
258
+ page.get_by_title("Draw a polylin").click()
259
+ map = page.locator("#map")
260
+ map.click(position={"x": 200, "y": 100})
261
+ map.click(position={"x": 100, "y": 100})
262
+ map.click(position={"x": 100, "y": 200})
263
+ # Click again to finish
264
+ map.click(position={"x": 100, "y": 200})
265
+ expect(lines).to_have_count(1)
266
+ extract_button = page.get_by_role("link", name="Extract shape to separate feature")
267
+ expect(extract_button).to_be_hidden()
268
+ page.get_by_title("Add a line to the current multi").click()
269
+ map.click(position={"x": 250, "y": 250})
270
+ map.click(position={"x": 200, "y": 250})
271
+ map.click(position={"x": 200, "y": 200})
272
+ # Click again to finish
273
+ map.click(position={"x": 200, "y": 200})
274
+ expect(lines).to_have_count(1)
275
+ lines.first.click(position={"x": 10, "y": 1}, button="right")
276
+ extract_button.click()
277
+ expect(lines).to_have_count(2)
278
+
279
+
280
+ def test_can_clone_polyline(live_server, page, tilelayer, settings):
281
+ settings.UMAP_ALLOW_ANONYMOUS = True
282
+ page.goto(f"{live_server.url}/en/map/new/")
283
+ lines = page.locator(".leaflet-overlay-pane path")
284
+ expect(lines).to_have_count(0)
285
+ page.get_by_title("Draw a polyline").click()
286
+ map = page.locator("#map")
287
+ map.click(position={"x": 200, "y": 100})
288
+ map.click(position={"x": 100, "y": 100})
289
+ map.click(position={"x": 100, "y": 200})
290
+ # Click again to finish
291
+ map.click(position={"x": 100, "y": 200})
292
+ expect(lines).to_have_count(1)
293
+ lines.first.click(position={"x": 10, "y": 1}, button="right")
294
+ page.get_by_role("link", name="Clone this feature").click()
295
+ expect(lines).to_have_count(2)
296
+ data = save_and_get_json(page)
297
+ assert len(data["features"]) == 2
298
+ assert data["features"][0]["geometry"]["type"] == "LineString"
299
+ assert data["features"][0]["geometry"] == data["features"][1]["geometry"]
300
+ assert data["features"][0]["properties"] == data["features"][1]["properties"]
301
+
302
+
303
+ def test_can_transform_polyline_to_polygon(live_server, page, tilelayer, settings):
304
+ settings.UMAP_ALLOW_ANONYMOUS = True
305
+ page.goto(f"{live_server.url}/en/map/new/")
306
+ paths = page.locator(".leaflet-overlay-pane path")
307
+ # Paths with fill
308
+ polygons = page.locator(".leaflet-overlay-pane path[fill='DarkBlue']")
309
+ expect(paths).to_have_count(0)
310
+ page.get_by_title("Draw a polyline").click()
311
+ map = page.locator("#map")
312
+ map.click(position={"x": 200, "y": 100})
313
+ map.click(position={"x": 100, "y": 100})
314
+ map.click(position={"x": 100, "y": 200})
315
+ # Click again to finish
316
+ map.click(position={"x": 100, "y": 200})
317
+ expect(paths).to_have_count(1)
318
+ expect(polygons).to_have_count(0)
319
+ paths.first.click(position={"x": 10, "y": 1}, button="right")
320
+ page.get_by_role("link", name="Transform to polygon").click()
321
+ expect(polygons).to_have_count(1)
322
+ expect(paths).to_have_count(1)
323
+ data = save_and_get_json(page)
324
+ assert len(data["features"]) == 1
325
+ assert data["features"][0]["geometry"]["type"] == "Polygon"
@@ -1,20 +1,24 @@
1
+ import platform
2
+ import re
3
+
1
4
  from playwright.sync_api import expect
2
5
 
6
+ from umap.models import DataLayer
7
+
8
+ from ..base import DataLayerFactory
9
+
3
10
 
4
11
  def test_should_have_fieldset_for_layer_type_properties(page, live_server, tilelayer):
5
12
  page.goto(f"{live_server.url}/en/map/new/")
6
13
 
7
14
  # Open DataLayers list
8
- button = page.get_by_title("Manage Layers")
9
- expect(button).to_be_visible()
10
- button.click()
15
+ page.get_by_title("Manage layers").click()
11
16
 
12
17
  # Create a layer
13
- page.get_by_title("Manage layers").click()
14
- page.get_by_role("button", name="Add a layer").click()
18
+ page.get_by_title("Add a layer").click()
15
19
  page.locator("input[name=name]").fill("Layer 1")
16
20
 
17
- select = page.locator("#umap-ui-container .umap-field-type select")
21
+ select = page.locator(".panel.on .umap-field-type select")
18
22
  expect(select).to_be_visible()
19
23
 
20
24
  choropleth_header = page.get_by_text("Choropleth: settings")
@@ -44,3 +48,138 @@ def test_should_have_fieldset_for_layer_type_properties(page, live_server, tilel
44
48
  expect(choropleth_header).to_be_hidden()
45
49
  expect(heat_header).to_be_hidden()
46
50
  expect(cluster_header).to_be_hidden()
51
+
52
+
53
+ def test_cancel_deleting_datalayer_should_restore(
54
+ live_server, openmap, datalayer, page
55
+ ):
56
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
57
+ page.get_by_title("See layers").click()
58
+ layers = page.locator(".umap-browser .datalayer")
59
+ markers = page.locator(".leaflet-marker-icon")
60
+ expect(layers).to_have_count(1)
61
+ expect(markers).to_have_count(1)
62
+ page.get_by_role("link", name="Manage layers").click()
63
+ page.once("dialog", lambda dialog: dialog.accept())
64
+ page.locator(".panel.right").get_by_title("Delete layer").click()
65
+ expect(markers).to_have_count(0)
66
+ page.get_by_role("button", name="See layers").click()
67
+ expect(page.get_by_text("test datalayer")).to_be_hidden()
68
+ page.once("dialog", lambda dialog: dialog.accept())
69
+ page.get_by_role("button", name="Cancel edits").click()
70
+ expect(markers).to_have_count(1)
71
+ expect(page.locator(".umap-browser").get_by_text("test datalayer")).to_be_visible()
72
+
73
+
74
+ def test_can_clone_datalayer(live_server, openmap, login, datalayer, page):
75
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
76
+ page.get_by_title("See layers").click()
77
+ layers = page.locator(".umap-browser .datalayer")
78
+ markers = page.locator(".leaflet-marker-icon")
79
+ expect(layers).to_have_count(1)
80
+ expect(markers).to_have_count(1)
81
+ page.get_by_role("link", name="Manage layers").click()
82
+ page.locator(".panel.right").get_by_title("Edit", exact=True).click()
83
+ page.get_by_role("heading", name="Advanced actions").click()
84
+ page.get_by_role("button", name="Clone").click()
85
+ expect(layers).to_have_count(2)
86
+ expect(markers).to_have_count(2)
87
+
88
+
89
+ def test_can_change_icon_class(live_server, openmap, page):
90
+ # Faster than doing a login
91
+ data = {
92
+ "type": "FeatureCollection",
93
+ "features": [
94
+ {
95
+ "type": "Feature",
96
+ "properties": {"name": "Point 4"},
97
+ "geometry": {"type": "Point", "coordinates": [0.856934, 45.290347]},
98
+ },
99
+ ],
100
+ }
101
+ DataLayerFactory(map=openmap, data=data)
102
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
103
+ expect(page.locator(".umap-div-icon")).to_be_visible()
104
+ page.get_by_role("link", name="Manage layers").click()
105
+ expect(page.locator(".umap-circle-icon")).to_be_hidden()
106
+ page.locator(".panel.right").get_by_title("Edit", exact=True).click()
107
+ page.get_by_role("heading", name="Shape properties").click()
108
+ page.locator(".umap-field-iconClass a.define").click()
109
+ page.get_by_text("Circle").click()
110
+ expect(page.locator(".umap-circle-icon")).to_be_visible()
111
+ expect(page.locator(".umap-div-icon")).to_be_hidden()
112
+
113
+
114
+ def test_can_change_name(live_server, openmap, page, datalayer):
115
+ page.goto(
116
+ f"{live_server.url}{openmap.get_absolute_url()}?edit&datalayersControl=expanded"
117
+ )
118
+ page.get_by_role("link", name="Manage layers").click()
119
+ page.locator(".panel.right").get_by_title("Edit", exact=True).click()
120
+ expect(page.locator(".umap-is-dirty")).to_be_hidden()
121
+ page.locator('input[name="name"]').click()
122
+ page.locator('input[name="name"]').press("Control+a")
123
+ page.locator('input[name="name"]').fill("new name")
124
+ expect(page.locator(".umap-browser .datalayer")).to_contain_text("new name")
125
+ expect(page.locator(".umap-is-dirty")).to_be_visible()
126
+ with page.expect_response(re.compile(".*/datalayer/update/.*")):
127
+ page.get_by_role("button", name="Save").click()
128
+ saved = DataLayer.objects.last()
129
+ assert saved.name == "new name"
130
+ expect(page.locator(".umap-is-dirty")).to_be_hidden()
131
+
132
+
133
+ def test_can_create_new_datalayer(live_server, openmap, page, datalayer):
134
+ page.goto(
135
+ f"{live_server.url}{openmap.get_absolute_url()}?edit&datalayersControl=expanded"
136
+ )
137
+ page.get_by_role("link", name="Manage layers").click()
138
+ page.get_by_role("button", name="Add a layer").click()
139
+ page.locator('input[name="name"]').click()
140
+ page.locator('input[name="name"]').fill("my new layer")
141
+ expect(page.get_by_text("my new layer")).to_be_visible()
142
+ with page.expect_response(re.compile(".*/datalayer/create/.*")):
143
+ page.get_by_role("button", name="Save").click()
144
+ assert DataLayer.objects.count() == 2
145
+ saved = DataLayer.objects.last()
146
+ assert saved.name == "my new layer"
147
+ expect(page.locator(".umap-is-dirty")).to_be_hidden()
148
+ # Edit again, it should not create a new datalayer
149
+ page.get_by_role("link", name="Manage layers").click()
150
+ page.locator(".panel.right").get_by_title("Edit", exact=True).first.click()
151
+ page.locator('input[name="name"]').click()
152
+ page.locator('input[name="name"]').fill("my new layer with a new name")
153
+ expect(page.get_by_text("my new layer with a new name")).to_be_visible()
154
+ page.get_by_role("button", name="Save").click()
155
+ with page.expect_response(re.compile(".*/datalayer/update/.*")):
156
+ page.get_by_role("button", name="Save").click()
157
+ assert DataLayer.objects.count() == 2
158
+ saved = DataLayer.objects.last()
159
+ assert saved.name == "my new layer with a new name"
160
+ expect(page.locator(".umap-is-dirty")).to_be_hidden()
161
+
162
+
163
+ def test_can_restore_version(live_server, openmap, page, datalayer):
164
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
165
+ marker = page.locator(".leaflet-marker-icon")
166
+ expect(marker).to_have_class(re.compile(".*umap-ball-icon.*"))
167
+ marker.click(modifiers=["Shift"])
168
+ page.get_by_role("heading", name="Shape properties").click()
169
+ page.locator("#umap-feature-shape-properties").get_by_text("Default").click()
170
+ with page.expect_response(re.compile(".*/datalayer/update/.*")):
171
+ page.get_by_role("button", name="Save").click()
172
+ expect(marker).to_have_class(re.compile(".*umap-div-icon.*"))
173
+ page.get_by_role("link", name="Manage layers").click()
174
+ page.locator(".panel.right").get_by_title("Edit", exact=True).click()
175
+ page.get_by_role("heading", name="Versions").click()
176
+ page.once("dialog", lambda dialog: dialog.accept())
177
+ page.get_by_role("button", name="Restore this version").last.click()
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()