umap-project 2.0.4__py3-none-any.whl → 2.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- umap/__init__.py +1 -1
- umap/fields.py +3 -1
- umap/locale/br/LC_MESSAGES/django.po +76 -71
- umap/locale/en/LC_MESSAGES/django.po +41 -41
- umap/locale/hu/LC_MESSAGES/django.po +42 -42
- umap/locale/it/LC_MESSAGES/django.po +64 -58
- umap/locale/ms/LC_MESSAGES/django.po +62 -57
- umap/migrations/0018_datalayer_uuid.py +62 -0
- umap/migrations/0019_migrate_internal_remote_datalayers.py +52 -0
- umap/models.py +20 -3
- umap/settings/base.py +1 -0
- umap/settings/dev.py +1 -0
- umap/static/umap/js/modules/browser.js +2 -2
- umap/static/umap/js/modules/global.js +14 -4
- umap/static/umap/js/modules/i18n.js +35 -0
- umap/static/umap/js/modules/leaflet-configure.js +7 -0
- umap/static/umap/js/modules/schema.js +388 -0
- umap/static/umap/js/modules/urls.js +17 -2
- umap/static/umap/js/modules/utils.js +24 -0
- umap/static/umap/js/umap.controls.js +9 -10
- umap/static/umap/js/umap.core.js +5 -5
- umap/static/umap/js/umap.features.js +23 -9
- umap/static/umap/js/umap.forms.js +49 -299
- umap/static/umap/js/umap.icon.js +2 -2
- umap/static/umap/js/umap.js +26 -129
- umap/static/umap/js/umap.layer.js +9 -9
- umap/static/umap/js/umap.popup.js +3 -0
- umap/static/umap/js/umap.share.js +1 -1
- umap/static/umap/locale/am_ET.json +229 -225
- umap/static/umap/locale/ar.json +229 -225
- umap/static/umap/locale/ast.json +229 -225
- umap/static/umap/locale/bg.json +229 -225
- umap/static/umap/locale/br.json +237 -233
- umap/static/umap/locale/ca.json +229 -225
- umap/static/umap/locale/cs_CZ.json +229 -225
- umap/static/umap/locale/da.json +229 -225
- umap/static/umap/locale/de.json +229 -225
- umap/static/umap/locale/el.json +229 -225
- umap/static/umap/locale/en.json +230 -233
- umap/static/umap/locale/en_US.json +229 -225
- umap/static/umap/locale/es.json +229 -225
- umap/static/umap/locale/et.json +229 -225
- umap/static/umap/locale/eu.json +226 -198
- umap/static/umap/locale/fa_IR.json +229 -225
- umap/static/umap/locale/fi.json +229 -225
- umap/static/umap/locale/fr.json +229 -232
- umap/static/umap/locale/gl.json +229 -225
- umap/static/umap/locale/he.json +229 -225
- umap/static/umap/locale/hr.json +229 -225
- umap/static/umap/locale/hu.json +229 -232
- umap/static/umap/locale/id.json +229 -225
- umap/static/umap/locale/is.json +229 -225
- umap/static/umap/locale/it.json +229 -232
- umap/static/umap/locale/ja.json +229 -225
- umap/static/umap/locale/ko.json +229 -225
- umap/static/umap/locale/lt.json +229 -225
- umap/static/umap/locale/ms.json +229 -232
- umap/static/umap/locale/nl.json +232 -228
- umap/static/umap/locale/no.json +229 -225
- umap/static/umap/locale/pl.json +229 -225
- umap/static/umap/locale/pl_PL.json +229 -225
- umap/static/umap/locale/pt.json +229 -225
- umap/static/umap/locale/pt_BR.json +229 -225
- umap/static/umap/locale/pt_PT.json +229 -225
- umap/static/umap/locale/ro.json +229 -225
- umap/static/umap/locale/ru.json +229 -225
- umap/static/umap/locale/sk_SK.json +229 -225
- umap/static/umap/locale/sl.json +229 -225
- umap/static/umap/locale/sr.json +229 -225
- umap/static/umap/locale/sv.json +229 -225
- umap/static/umap/locale/th_TH.json +229 -225
- umap/static/umap/locale/tr.json +229 -225
- umap/static/umap/locale/uk_UA.json +229 -225
- umap/static/umap/locale/vi.json +229 -225
- umap/static/umap/locale/vi_VN.json +229 -225
- umap/static/umap/locale/zh.json +229 -225
- umap/static/umap/locale/zh_CN.json +229 -225
- umap/static/umap/locale/zh_TW.Big5.json +229 -225
- umap/static/umap/locale/zh_TW.json +229 -232
- umap/static/umap/test/index.html +0 -2
- umap/static/umap/{test → unittests}/URLs.js +5 -0
- umap/static/umap/vendors/leaflet/leaflet-src.esm.js +7064 -7064
- umap/static/umap/vendors/photon/leaflet.photon.js +3 -0
- umap/templates/umap/js.html +8 -6
- umap/templatetags/umap_tags.py +3 -2
- umap/tests/integration/test_browser.py +40 -0
- umap/tests/integration/test_collaborative_editing.py +72 -3
- umap/tests/integration/test_export_map.py +226 -9
- umap/tests/integration/test_features_id_generation.py +51 -0
- umap/tests/integration/test_owned_map.py +14 -1
- umap/tests/integration/test_statics.py +3 -3
- umap/tests/integration/test_tilelayer.py +3 -3
- umap/tests/settings.py +3 -3
- umap/tests/test_datalayer_views.py +77 -20
- umap/tests/test_map_views.py +20 -0
- umap/tests/test_merge_features.py +25 -5
- umap/urls.py +12 -12
- umap/utils.py +7 -0
- umap/views.py +58 -49
- umap/wsgi.py +1 -0
- {umap_project-2.0.4.dist-info → umap_project-2.1.1.dist-info}/METADATA +9 -9
- {umap_project-2.0.4.dist-info → umap_project-2.1.1.dist-info}/RECORD +105 -99
- umap/static/umap/test/Map.Export.js +0 -106
- {umap_project-2.0.4.dist-info → umap_project-2.1.1.dist-info}/WHEEL +0 -0
- {umap_project-2.0.4.dist-info → umap_project-2.1.1.dist-info}/entry_points.txt +0 -0
- {umap_project-2.0.4.dist-info → umap_project-2.1.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -388,6 +388,9 @@ L.PhotonSearch = L.PhotonBaseSearch.extend({
|
|
|
388
388
|
if (this.options.includePosition) {
|
|
389
389
|
params.lat = this.map.getCenter().lat;
|
|
390
390
|
params.lon = this.map.getCenter().lng;
|
|
391
|
+
if (this.options.location_bias_scale) {
|
|
392
|
+
params.location_bias_scale = this.options.location_bias_scale;
|
|
393
|
+
}
|
|
391
394
|
}
|
|
392
395
|
if (this.options.bbox && this.options.bbox.length === 4) {
|
|
393
396
|
params.bbox = this.options.bbox.join(',');
|
umap/templates/umap/js.html
CHANGED
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
<script type="module"
|
|
3
3
|
src="{% static 'umap/vendors/leaflet/leaflet-src.esm.js' %}"
|
|
4
4
|
defer></script>
|
|
5
|
+
<script type="module"
|
|
6
|
+
src="{% static 'umap/js/modules/leaflet-configure.js' %}"
|
|
7
|
+
defer></script>
|
|
8
|
+
{% if locale %}
|
|
9
|
+
{% with "umap/locale/"|add:locale|add:".js" as path %}
|
|
10
|
+
<script src="{% static path %}" defer></script>
|
|
11
|
+
{% endwith %}
|
|
12
|
+
{% endif %}
|
|
5
13
|
<script type="module" src="{% static 'umap/js/modules/global.js' %}" defer></script>
|
|
6
14
|
<script src="{% static 'umap/vendors/editable/Path.Drag.js' %}" defer></script>
|
|
7
15
|
<script src="{% static 'umap/vendors/editable/Leaflet.Editable.js' %}" defer></script>
|
|
8
16
|
<script src="{% static 'umap/vendors/hash/leaflet-hash.js' %}" defer></script>
|
|
9
|
-
<script src="{% static 'umap/vendors/i18n/Leaflet.i18n.js' %}" defer></script>
|
|
10
17
|
<script src="{% static 'umap/vendors/editinosm/Leaflet.EditInOSM.js' %}"
|
|
11
18
|
defer></script>
|
|
12
19
|
<script src="{% static 'umap/vendors/minimap/Control.MiniMap.min.js' %}"
|
|
@@ -39,11 +46,6 @@
|
|
|
39
46
|
<script src="{% static 'umap/vendors/colorbrewer/colorbrewer.js' %}" defer></script>
|
|
40
47
|
<script src="{% static 'umap/vendors/simple-statistics/simple-statistics.min.js' %}"
|
|
41
48
|
defer></script>
|
|
42
|
-
{% if locale %}
|
|
43
|
-
{% with "umap/locale/"|add:locale|add:".js" as path %}
|
|
44
|
-
<script src="{% static path %}" defer></script>
|
|
45
|
-
{% endwith %}
|
|
46
|
-
{% endif %}
|
|
47
49
|
<script src="{% static 'umap/js/umap.core.js' %}" defer></script>
|
|
48
50
|
<script src="{% static 'umap/js/umap.autocomplete.js' %}" defer></script>
|
|
49
51
|
<script src="{% static 'umap/js/umap.popup.js' %}" defer></script>
|
umap/templatetags/umap_tags.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import json
|
|
2
1
|
from copy import copy
|
|
3
2
|
|
|
4
3
|
from django import template
|
|
5
4
|
from django.conf import settings
|
|
6
5
|
|
|
6
|
+
from umap.utils import json_dumps
|
|
7
|
+
|
|
7
8
|
register = template.Library()
|
|
8
9
|
|
|
9
10
|
|
|
@@ -25,7 +26,7 @@ def map_fragment(map_instance, **kwargs):
|
|
|
25
26
|
page = kwargs.pop("page", None) or ""
|
|
26
27
|
unique_id = prefix + str(page) + "_" + str(map_instance.pk)
|
|
27
28
|
return {
|
|
28
|
-
"map_settings":
|
|
29
|
+
"map_settings": json_dumps(map_settings),
|
|
29
30
|
"map": map_instance,
|
|
30
31
|
"unique_id": unique_id,
|
|
31
32
|
}
|
|
@@ -291,3 +291,43 @@ def test_should_use_color_variable(live_server, map, page):
|
|
|
291
291
|
expect(features.nth(1)).to_have_css("background-color", "rgb(139, 0, 0)")
|
|
292
292
|
# DarkBlue (default color)
|
|
293
293
|
expect(features.nth(2)).to_have_css("background-color", "rgb(0, 0, 139)")
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def test_should_allow_to_toggle_datalayer_visibility(live_server, map, page, bootstrap):
|
|
297
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
|
298
|
+
markers = page.locator(".leaflet-marker-icon")
|
|
299
|
+
paths = page.locator(".leaflet-overlay-pane path")
|
|
300
|
+
expect(markers).to_have_count(1)
|
|
301
|
+
expect(paths).to_have_count(2)
|
|
302
|
+
toggle = page.locator("#umap-ui-container").get_by_title("Show/hide layer")
|
|
303
|
+
toggle.click()
|
|
304
|
+
expect(markers).to_have_count(0)
|
|
305
|
+
expect(paths).to_have_count(0)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def test_should_have_edit_buttons_in_edit_mode(live_server, map, page, bootstrap):
|
|
309
|
+
# Faster than doing a login
|
|
310
|
+
map.edit_status = Map.ANONYMOUS
|
|
311
|
+
map.save()
|
|
312
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
|
313
|
+
browser = page.locator("#umap-ui-container")
|
|
314
|
+
edit_layer = browser.get_by_title("Edit", exact=True)
|
|
315
|
+
in_table = browser.get_by_title("Edit properties in a table")
|
|
316
|
+
delete_layer = browser.get_by_title("Delete layer")
|
|
317
|
+
edit_feature = browser.get_by_title("Edit this feature")
|
|
318
|
+
delete_feature = browser.get_by_title("Delete this feature")
|
|
319
|
+
expect(edit_layer).to_be_hidden()
|
|
320
|
+
expect(in_table).to_be_hidden()
|
|
321
|
+
expect(delete_layer).to_be_hidden()
|
|
322
|
+
# Does not work
|
|
323
|
+
# to_have_count does not seem to case about the elements being visible or not
|
|
324
|
+
# and to_be_hidden is not happy if the selector resolve to more than on element
|
|
325
|
+
# expect(edit_feature).to_have_count(0)
|
|
326
|
+
# expect(delete_feature).to_be_hidden()
|
|
327
|
+
# Switch to edit mode
|
|
328
|
+
page.get_by_role("button", name="Edit").click()
|
|
329
|
+
expect(edit_layer).to_be_visible()
|
|
330
|
+
expect(in_table).to_be_visible()
|
|
331
|
+
expect(delete_layer).to_be_visible()
|
|
332
|
+
expect(edit_feature).to_have_count(3)
|
|
333
|
+
expect(delete_feature).to_have_count(3)
|
|
@@ -98,7 +98,7 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer):
|
|
|
98
98
|
"name": "test datalayer",
|
|
99
99
|
"inCaption": True,
|
|
100
100
|
"editMode": "advanced",
|
|
101
|
-
"id": datalayer.pk,
|
|
101
|
+
"id": str(datalayer.pk),
|
|
102
102
|
"permissions": {"edit_status": 1},
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -116,7 +116,7 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer):
|
|
|
116
116
|
"name": "test datalayer",
|
|
117
117
|
"inCaption": True,
|
|
118
118
|
"editMode": "advanced",
|
|
119
|
-
"id": datalayer.pk,
|
|
119
|
+
"id": str(datalayer.pk),
|
|
120
120
|
"permissions": {"edit_status": 1},
|
|
121
121
|
}
|
|
122
122
|
expect(marker_pane_p1).to_have_count(4)
|
|
@@ -136,7 +136,7 @@ def test_collaborative_editing_create_markers(context, live_server, tilelayer):
|
|
|
136
136
|
"name": "test datalayer",
|
|
137
137
|
"inCaption": True,
|
|
138
138
|
"editMode": "advanced",
|
|
139
|
-
"id": datalayer.pk,
|
|
139
|
+
"id": str(datalayer.pk),
|
|
140
140
|
"permissions": {"edit_status": 1},
|
|
141
141
|
}
|
|
142
142
|
expect(marker_pane_p2).to_have_count(5)
|
|
@@ -196,3 +196,72 @@ def test_empty_datalayers_can_be_merged(context, live_server, tilelayer):
|
|
|
196
196
|
sleep(1)
|
|
197
197
|
|
|
198
198
|
expect(marker_pane_p2).to_have_count(2)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def test_same_second_edit_doesnt_conflict(context, live_server, tilelayer):
|
|
202
|
+
# Let's create a new map with an empty datalayer
|
|
203
|
+
map = MapFactory(name="collaborative editing")
|
|
204
|
+
datalayer = DataLayerFactory(map=map, edit_status=DataLayer.ANONYMOUS, data={})
|
|
205
|
+
|
|
206
|
+
# Open the created map on two pages.
|
|
207
|
+
page_one = context.new_page()
|
|
208
|
+
page_one.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
209
|
+
page_two = context.new_page()
|
|
210
|
+
page_two.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
211
|
+
|
|
212
|
+
save_p1 = page_one.get_by_role("button", name="Save")
|
|
213
|
+
expect(save_p1).to_be_visible()
|
|
214
|
+
|
|
215
|
+
save_p2 = page_two.get_by_role("button", name="Save")
|
|
216
|
+
expect(save_p2).to_be_visible()
|
|
217
|
+
|
|
218
|
+
# Create a point on the first map
|
|
219
|
+
create_marker_p1 = page_one.get_by_title("Draw a marker")
|
|
220
|
+
expect(create_marker_p1).to_be_visible()
|
|
221
|
+
create_marker_p1.click()
|
|
222
|
+
|
|
223
|
+
# Check no marker is present by default.
|
|
224
|
+
marker_pane_p1 = page_one.locator(".leaflet-marker-pane > div")
|
|
225
|
+
expect(marker_pane_p1).to_have_count(0)
|
|
226
|
+
|
|
227
|
+
# Click on the map, it will place a marker at the given position.
|
|
228
|
+
map_el_p1 = page_one.locator("#map")
|
|
229
|
+
map_el_p1.click(position={"x": 200, "y": 200})
|
|
230
|
+
expect(marker_pane_p1).to_have_count(1)
|
|
231
|
+
|
|
232
|
+
# And add one on the second map as well.
|
|
233
|
+
create_marker_p2 = page_two.get_by_title("Draw a marker")
|
|
234
|
+
expect(create_marker_p2).to_be_visible()
|
|
235
|
+
create_marker_p2.click()
|
|
236
|
+
|
|
237
|
+
marker_pane_p2 = page_two.locator(".leaflet-marker-pane > div")
|
|
238
|
+
|
|
239
|
+
# Click on the map, it will place a marker at the given position.
|
|
240
|
+
map_el_p2 = page_two.locator("#map")
|
|
241
|
+
map_el_p2.click(position={"x": 220, "y": 220})
|
|
242
|
+
expect(marker_pane_p2).to_have_count(1)
|
|
243
|
+
|
|
244
|
+
# Save the two tabs at the same time
|
|
245
|
+
with page_one.expect_response(DATALAYER_UPDATE):
|
|
246
|
+
save_p1.click()
|
|
247
|
+
sleep(0.2) # Needed to avoid having multiple requests coming at the same time.
|
|
248
|
+
save_p2.click()
|
|
249
|
+
|
|
250
|
+
# Now create another marker in the first tab
|
|
251
|
+
create_marker_p1.click()
|
|
252
|
+
map_el_p1.click(position={"x": 150, "y": 150})
|
|
253
|
+
expect(marker_pane_p1).to_have_count(2)
|
|
254
|
+
with page_one.expect_response(DATALAYER_UPDATE):
|
|
255
|
+
save_p1.click()
|
|
256
|
+
|
|
257
|
+
# Should now get the other marker too
|
|
258
|
+
expect(marker_pane_p1).to_have_count(3)
|
|
259
|
+
assert DataLayer.objects.get(pk=datalayer.pk).settings == {
|
|
260
|
+
"browsable": True,
|
|
261
|
+
"displayOnLoad": True,
|
|
262
|
+
"name": "test datalayer",
|
|
263
|
+
"inCaption": True,
|
|
264
|
+
"editMode": "advanced",
|
|
265
|
+
"id": str(datalayer.pk),
|
|
266
|
+
"permissions": {"edit_status": 1},
|
|
267
|
+
}
|
|
@@ -4,10 +4,84 @@ from pathlib import Path
|
|
|
4
4
|
import pytest
|
|
5
5
|
from playwright.sync_api import expect
|
|
6
6
|
|
|
7
|
+
from ..base import DataLayerFactory
|
|
8
|
+
|
|
7
9
|
pytestmark = pytest.mark.django_db
|
|
8
10
|
|
|
11
|
+
DATALAYER_DATA = {
|
|
12
|
+
"type": "FeatureCollection",
|
|
13
|
+
"features": [
|
|
14
|
+
{
|
|
15
|
+
"type": "Feature",
|
|
16
|
+
"properties": {
|
|
17
|
+
"name": "name poly",
|
|
18
|
+
},
|
|
19
|
+
"id": "gyNzM",
|
|
20
|
+
"geometry": {
|
|
21
|
+
"type": "Polygon",
|
|
22
|
+
"coordinates": [
|
|
23
|
+
[
|
|
24
|
+
[11.25, 53.585984],
|
|
25
|
+
[10.151367, 52.975108],
|
|
26
|
+
[12.689209, 52.167194],
|
|
27
|
+
[14.084473, 53.199452],
|
|
28
|
+
[12.634277, 53.618579],
|
|
29
|
+
[11.25, 53.585984],
|
|
30
|
+
[11.25, 53.585984],
|
|
31
|
+
],
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"type": "Feature",
|
|
37
|
+
"properties": {
|
|
38
|
+
"_umap_options": {
|
|
39
|
+
"color": "OliveDrab",
|
|
40
|
+
},
|
|
41
|
+
"name": "test",
|
|
42
|
+
"description": "Some description",
|
|
43
|
+
},
|
|
44
|
+
"id": "QwNjg",
|
|
45
|
+
"geometry": {
|
|
46
|
+
"type": "Point",
|
|
47
|
+
"coordinates": [-0.274658, 52.57635],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"type": "Feature",
|
|
52
|
+
"properties": {
|
|
53
|
+
"_umap_options": {
|
|
54
|
+
"fill": False,
|
|
55
|
+
"opacity": 0.6,
|
|
56
|
+
},
|
|
57
|
+
"name": "test",
|
|
58
|
+
},
|
|
59
|
+
"id": "YwMTM",
|
|
60
|
+
"geometry": {
|
|
61
|
+
"type": "LineString",
|
|
62
|
+
"coordinates": [
|
|
63
|
+
[-0.571289, 54.476422],
|
|
64
|
+
[0.439453, 54.610255],
|
|
65
|
+
[1.724854, 53.448807],
|
|
66
|
+
[4.163818, 53.988395],
|
|
67
|
+
[5.306396, 53.533778],
|
|
68
|
+
[6.591797, 53.709714],
|
|
69
|
+
[7.042236, 53.350551],
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pytest.fixture
|
|
78
|
+
def bootstrap(map, live_server):
|
|
79
|
+
map.settings["properties"]["onLoadPanel"] = "databrowser"
|
|
80
|
+
map.save()
|
|
81
|
+
DataLayerFactory(map=map, data=DATALAYER_DATA)
|
|
82
|
+
|
|
9
83
|
|
|
10
|
-
def test_umap_export(map, live_server,
|
|
84
|
+
def test_umap_export(map, live_server, bootstrap, page):
|
|
11
85
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?share")
|
|
12
86
|
link = page.get_by_role("link", name="full backup")
|
|
13
87
|
expect(link).to_be_visible()
|
|
@@ -34,16 +108,56 @@ def test_umap_export(map, live_server, datalayer, page):
|
|
|
34
108
|
"features": [
|
|
35
109
|
{
|
|
36
110
|
"geometry": {
|
|
37
|
-
"coordinates": [
|
|
111
|
+
"coordinates": [
|
|
112
|
+
[
|
|
113
|
+
[11.25, 53.585984],
|
|
114
|
+
[10.151367, 52.975108],
|
|
115
|
+
[12.689209, 52.167194],
|
|
116
|
+
[14.084473, 53.199452],
|
|
117
|
+
[12.634277, 53.618579],
|
|
118
|
+
[11.25, 53.585984],
|
|
119
|
+
[11.25, 53.585984],
|
|
120
|
+
]
|
|
121
|
+
],
|
|
122
|
+
"type": "Polygon",
|
|
123
|
+
},
|
|
124
|
+
"id": "gyNzM",
|
|
125
|
+
"properties": {"name": "name poly"},
|
|
126
|
+
"type": "Feature",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"geometry": {
|
|
130
|
+
"coordinates": [-0.274658, 52.57635],
|
|
38
131
|
"type": "Point",
|
|
39
132
|
},
|
|
133
|
+
"id": "QwNjg",
|
|
134
|
+
"properties": {
|
|
135
|
+
"_umap_options": {"color": "OliveDrab"},
|
|
136
|
+
"name": "test",
|
|
137
|
+
"description": "Some description",
|
|
138
|
+
},
|
|
139
|
+
"type": "Feature",
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"geometry": {
|
|
143
|
+
"coordinates": [
|
|
144
|
+
[-0.571289, 54.476422],
|
|
145
|
+
[0.439453, 54.610255],
|
|
146
|
+
[1.724854, 53.448807],
|
|
147
|
+
[4.163818, 53.988395],
|
|
148
|
+
[5.306396, 53.533778],
|
|
149
|
+
[6.591797, 53.709714],
|
|
150
|
+
[7.042236, 53.350551],
|
|
151
|
+
],
|
|
152
|
+
"type": "LineString",
|
|
153
|
+
},
|
|
154
|
+
"id": "YwMTM",
|
|
40
155
|
"properties": {
|
|
41
|
-
"_umap_options": {"
|
|
42
|
-
"
|
|
43
|
-
"name": "Here",
|
|
156
|
+
"_umap_options": {"fill": False, "opacity": 0.6},
|
|
157
|
+
"name": "test",
|
|
44
158
|
},
|
|
45
159
|
"type": "Feature",
|
|
46
|
-
}
|
|
160
|
+
},
|
|
47
161
|
],
|
|
48
162
|
"type": "FeatureCollection",
|
|
49
163
|
}
|
|
@@ -66,12 +180,13 @@ def test_umap_export(map, live_server, datalayer, page):
|
|
|
66
180
|
"tilelayersControl": True,
|
|
67
181
|
"zoom": 7,
|
|
68
182
|
"zoomControl": True,
|
|
183
|
+
"onLoadPanel": "databrowser",
|
|
69
184
|
},
|
|
70
185
|
"type": "umap",
|
|
71
186
|
}
|
|
72
187
|
|
|
73
188
|
|
|
74
|
-
def test_csv_export(map, live_server,
|
|
189
|
+
def test_csv_export(map, live_server, bootstrap, page):
|
|
75
190
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?share")
|
|
76
191
|
button = page.get_by_role("button", name="csv")
|
|
77
192
|
expect(button).to_be_visible()
|
|
@@ -83,6 +198,108 @@ def test_csv_export(map, live_server, datalayer, page):
|
|
|
83
198
|
download.save_as(path)
|
|
84
199
|
assert (
|
|
85
200
|
path.read_text()
|
|
86
|
-
== """name,
|
|
87
|
-
|
|
201
|
+
== """name,Latitude,Longitude,description
|
|
202
|
+
name poly,53.0072070131872,12.182431646910137,
|
|
203
|
+
test,52.57635,-0.274658,Some description
|
|
204
|
+
test,53.725145179688646,2.9700064980570517,"""
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def test_gpx_export(map, live_server, bootstrap, page):
|
|
209
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}?share")
|
|
210
|
+
button = page.get_by_role("button", name="gpx")
|
|
211
|
+
expect(button).to_be_visible()
|
|
212
|
+
with page.expect_download() as download_info:
|
|
213
|
+
button.click()
|
|
214
|
+
download = download_info.value
|
|
215
|
+
# FIXME assert mimetype (find no way to access it throught PW)
|
|
216
|
+
assert download.suggested_filename == "test_map.gpx"
|
|
217
|
+
path = Path("/tmp/") / download.suggested_filename
|
|
218
|
+
download.save_as(path)
|
|
219
|
+
assert (
|
|
220
|
+
path.read_text()
|
|
221
|
+
== """<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" creator="togpx"><metadata/><wpt lat="52.57635" lon="-0.274658"><name>test</name><desc>name=test
|
|
222
|
+
description=Some description</desc></wpt><trk><name>name poly</name><desc>name=name poly</desc><trkseg><trkpt lat="53.585984" lon="11.25"/><trkpt lat="52.975108" lon="10.151367"/><trkpt lat="52.167194" lon="12.689209"/><trkpt lat="53.199452" lon="14.084473"/><trkpt lat="53.618579" lon="12.634277"/><trkpt lat="53.585984" lon="11.25"/><trkpt lat="53.585984" lon="11.25"/></trkseg></trk><trk><name>test</name><desc>name=test</desc><trkseg><trkpt lat="54.476422" lon="-0.571289"/><trkpt lat="54.610255" lon="0.439453"/><trkpt lat="53.448807" lon="1.724854"/><trkpt lat="53.988395" lon="4.163818"/><trkpt lat="53.533778" lon="5.306396"/><trkpt lat="53.709714" lon="6.591797"/><trkpt lat="53.350551" lon="7.042236"/></trkseg></trk></gpx>"""
|
|
88
223
|
)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def test_kml_export(map, live_server, bootstrap, page):
|
|
227
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}?share")
|
|
228
|
+
button = page.get_by_role("button", name="kml")
|
|
229
|
+
expect(button).to_be_visible()
|
|
230
|
+
with page.expect_download() as download_info:
|
|
231
|
+
button.click()
|
|
232
|
+
download = download_info.value
|
|
233
|
+
assert download.suggested_filename == "test_map.kml"
|
|
234
|
+
path = Path("/tmp/") / download.suggested_filename
|
|
235
|
+
download.save_as(path)
|
|
236
|
+
assert (
|
|
237
|
+
path.read_text()
|
|
238
|
+
== """<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Document><Placemark><name>name poly</name><ExtendedData><Data name="name"><value>name poly</value></Data></ExtendedData><Polygon><outerBoundaryIs><LinearRing><coordinates>11.25,53.585984 10.151367,52.975108 12.689209,52.167194 14.084473,53.199452 12.634277,53.618579 11.25,53.585984 11.25,53.585984</coordinates></LinearRing></outerBoundaryIs></Polygon></Placemark><Placemark><name>test</name><description>Some description</description><ExtendedData><Data name="_umap_options"><value>[object Object]</value></Data><Data name="name"><value>test</value></Data><Data name="description"><value>Some description</value></Data></ExtendedData><Point><coordinates>-0.274658,52.57635</coordinates></Point></Placemark><Placemark><name>test</name><ExtendedData><Data name="_umap_options"><value>[object Object]</value></Data><Data name="name"><value>test</value></Data></ExtendedData><LineString><coordinates>-0.571289,54.476422 0.439453,54.610255 1.724854,53.448807 4.163818,53.988395 5.306396,53.533778 6.591797,53.709714 7.042236,53.350551</coordinates></LineString></Placemark></Document></kml>"""
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def test_geojson_export(map, live_server, bootstrap, page):
|
|
243
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}?share")
|
|
244
|
+
button = page.get_by_role("button", name="geojson")
|
|
245
|
+
expect(button).to_be_visible()
|
|
246
|
+
with page.expect_download() as download_info:
|
|
247
|
+
button.click()
|
|
248
|
+
download = download_info.value
|
|
249
|
+
assert download.suggested_filename == "test_map.geojson"
|
|
250
|
+
path = Path("/tmp/") / download.suggested_filename
|
|
251
|
+
download.save_as(path)
|
|
252
|
+
assert json.loads(path.read_text()) == {
|
|
253
|
+
"features": [
|
|
254
|
+
{
|
|
255
|
+
"geometry": {
|
|
256
|
+
"coordinates": [
|
|
257
|
+
[
|
|
258
|
+
[11.25, 53.585984],
|
|
259
|
+
[10.151367, 52.975108],
|
|
260
|
+
[12.689209, 52.167194],
|
|
261
|
+
[14.084473, 53.199452],
|
|
262
|
+
[12.634277, 53.618579],
|
|
263
|
+
[11.25, 53.585984],
|
|
264
|
+
[11.25, 53.585984],
|
|
265
|
+
]
|
|
266
|
+
],
|
|
267
|
+
"type": "Polygon",
|
|
268
|
+
},
|
|
269
|
+
"id": "gyNzM",
|
|
270
|
+
"properties": {"name": "name poly"},
|
|
271
|
+
"type": "Feature",
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"geometry": {"coordinates": [-0.274658, 52.57635], "type": "Point"},
|
|
275
|
+
"id": "QwNjg",
|
|
276
|
+
"properties": {
|
|
277
|
+
"_umap_options": {"color": "OliveDrab"},
|
|
278
|
+
"name": "test",
|
|
279
|
+
"description": "Some description",
|
|
280
|
+
},
|
|
281
|
+
"type": "Feature",
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"geometry": {
|
|
285
|
+
"coordinates": [
|
|
286
|
+
[-0.571289, 54.476422],
|
|
287
|
+
[0.439453, 54.610255],
|
|
288
|
+
[1.724854, 53.448807],
|
|
289
|
+
[4.163818, 53.988395],
|
|
290
|
+
[5.306396, 53.533778],
|
|
291
|
+
[6.591797, 53.709714],
|
|
292
|
+
[7.042236, 53.350551],
|
|
293
|
+
],
|
|
294
|
+
"type": "LineString",
|
|
295
|
+
},
|
|
296
|
+
"id": "YwMTM",
|
|
297
|
+
"properties": {
|
|
298
|
+
"_umap_options": {"fill": False, "opacity": 0.6},
|
|
299
|
+
"name": "test",
|
|
300
|
+
},
|
|
301
|
+
"type": "Feature",
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
"type": "FeatureCollection",
|
|
305
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_ids_generation(page, live_server, tilelayer):
|
|
6
|
+
page.goto(f"{live_server.url}/en/map/new/")
|
|
7
|
+
|
|
8
|
+
# Click on the Draw a line button on a new map.
|
|
9
|
+
create_polyline = page.locator(".leaflet-control-toolbar ").get_by_title(
|
|
10
|
+
"Draw a polyline"
|
|
11
|
+
)
|
|
12
|
+
create_polyline.click()
|
|
13
|
+
|
|
14
|
+
map = page.locator("#map")
|
|
15
|
+
map.click(position={"x": 200, "y": 200})
|
|
16
|
+
map.click(position={"x": 100, "y": 100})
|
|
17
|
+
# Click again to finish
|
|
18
|
+
map.click(position={"x": 100, "y": 100})
|
|
19
|
+
|
|
20
|
+
# Click on the Draw a polygon button on a new map.
|
|
21
|
+
create_polygon = page.locator(".leaflet-control-toolbar ").get_by_title(
|
|
22
|
+
"Draw a polygon"
|
|
23
|
+
)
|
|
24
|
+
create_polygon.click()
|
|
25
|
+
|
|
26
|
+
map = page.locator("#map")
|
|
27
|
+
map.click(position={"x": 300, "y": 300})
|
|
28
|
+
map.click(position={"x": 300, "y": 400})
|
|
29
|
+
map.click(position={"x": 350, "y": 450})
|
|
30
|
+
# Click again to finish
|
|
31
|
+
map.click(position={"x": 350, "y": 450})
|
|
32
|
+
|
|
33
|
+
download_panel = page.get_by_title("Share and download")
|
|
34
|
+
download_panel.click()
|
|
35
|
+
|
|
36
|
+
button = page.get_by_role("button", name="geojson")
|
|
37
|
+
|
|
38
|
+
with page.expect_download() as download_info:
|
|
39
|
+
button.click()
|
|
40
|
+
|
|
41
|
+
download = download_info.value
|
|
42
|
+
|
|
43
|
+
path = Path("/tmp/") / download.suggested_filename
|
|
44
|
+
download.save_as(path)
|
|
45
|
+
downloaded = json.loads(path.read_text())
|
|
46
|
+
|
|
47
|
+
assert "features" in downloaded
|
|
48
|
+
features = downloaded["features"]
|
|
49
|
+
assert len(features) == 2
|
|
50
|
+
assert "id" in features[0]
|
|
51
|
+
assert "id" in features[1]
|
|
@@ -134,6 +134,18 @@ def test_owner_has_delete_map_button(map, live_server, login):
|
|
|
134
134
|
advanced.click()
|
|
135
135
|
delete = page.get_by_role("button", name="Delete", exact=True)
|
|
136
136
|
expect(delete).to_be_visible()
|
|
137
|
+
dialog_shown = False
|
|
138
|
+
|
|
139
|
+
def handle_dialog(dialog):
|
|
140
|
+
dialog.accept()
|
|
141
|
+
nonlocal dialog_shown
|
|
142
|
+
dialog_shown = True
|
|
143
|
+
|
|
144
|
+
page.on("dialog", handle_dialog)
|
|
145
|
+
with page.expect_navigation():
|
|
146
|
+
delete.click()
|
|
147
|
+
assert dialog_shown
|
|
148
|
+
assert Map.objects.all().count() == 0
|
|
137
149
|
|
|
138
150
|
|
|
139
151
|
def test_editor_do_not_have_delete_map_button(map, live_server, login, user):
|
|
@@ -210,7 +222,8 @@ def test_can_change_owner(map, live_server, login, user):
|
|
|
210
222
|
close = page.locator(".umap-field-owner .close")
|
|
211
223
|
close.click()
|
|
212
224
|
input = page.locator("input.edit-owner")
|
|
213
|
-
|
|
225
|
+
with page.expect_response(re.compile(r".*/agnocomplete/.*")):
|
|
226
|
+
input.type(user.username)
|
|
214
227
|
input.press("Tab")
|
|
215
228
|
save = page.get_by_role("button", name="Save")
|
|
216
229
|
expect(save).to_be_visible()
|
|
@@ -15,9 +15,9 @@ def staticfiles(settings):
|
|
|
15
15
|
settings.STATIC_ROOT = static_root
|
|
16
16
|
# Make sure settings are properly reset after the test
|
|
17
17
|
settings.STORAGES = deepcopy(settings.STORAGES)
|
|
18
|
-
settings.STORAGES["staticfiles"][
|
|
19
|
-
"
|
|
20
|
-
|
|
18
|
+
settings.STORAGES["staticfiles"]["BACKEND"] = (
|
|
19
|
+
"umap.storage.UmapManifestStaticFilesStorage"
|
|
20
|
+
)
|
|
21
21
|
try:
|
|
22
22
|
call_command("collectstatic", "--noinput")
|
|
23
23
|
yield
|
|
@@ -101,9 +101,9 @@ def test_map_should_display_custom_tilelayer(map, live_server, tilelayers, page)
|
|
|
101
101
|
url_pattern = re.compile(
|
|
102
102
|
r"https://[abc]{1}.basemaps.cartocdn.com/rastertiles/voyager/\d+/\d+/\d+.png"
|
|
103
103
|
)
|
|
104
|
-
map.settings["properties"]["tilelayer"][
|
|
105
|
-
"
|
|
106
|
-
|
|
104
|
+
map.settings["properties"]["tilelayer"]["url_template"] = (
|
|
105
|
+
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png"
|
|
106
|
+
)
|
|
107
107
|
map.settings["properties"]["tilelayersControl"] = True
|
|
108
108
|
map.save()
|
|
109
109
|
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
umap/tests/settings.py
CHANGED
|
@@ -5,9 +5,9 @@ from umap.settings.base import * # pylint: disable=W0614,W0401
|
|
|
5
5
|
SECRET_KEY = "justfortests"
|
|
6
6
|
DEFAULT_FROM_EMAIL = "test@test.org"
|
|
7
7
|
EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
|
|
8
|
-
STORAGES["staticfiles"][
|
|
9
|
-
"
|
|
10
|
-
|
|
8
|
+
STORAGES["staticfiles"]["BACKEND"] = (
|
|
9
|
+
"django.contrib.staticfiles.storage.StaticFilesStorage"
|
|
10
|
+
)
|
|
11
11
|
|
|
12
12
|
if os.environ.get("GITHUB_ACTIONS", False) == "true":
|
|
13
13
|
DATABASES = {
|