umap-project 3.4.2__py3-none-any.whl → 3.6.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/locale/br/LC_MESSAGES/django.mo +0 -0
- umap/locale/br/LC_MESSAGES/django.po +71 -57
- umap/locale/de/LC_MESSAGES/django.mo +0 -0
- umap/locale/de/LC_MESSAGES/django.po +20 -16
- umap/locale/en/LC_MESSAGES/django.po +14 -14
- umap/locale/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/hu/LC_MESSAGES/django.po +20 -16
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +32 -27
- umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh_TW/LC_MESSAGES/django.po +20 -16
- umap/management/commands/clean_tilelayer.py +0 -1
- umap/management/commands/search_maps.py +95 -0
- umap/settings/__init__.py +9 -1
- umap/settings/base.py +7 -6
- umap/static/umap/css/icon.css +8 -0
- umap/static/umap/img/16-white.svg +5 -2
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/source/16-white.svg +7 -4
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/js/modules/autocomplete.js +1 -9
- umap/static/umap/js/modules/browser.js +27 -10
- umap/static/umap/js/modules/data/features.js +3 -2
- umap/static/umap/js/modules/data/fields.js +12 -2
- umap/static/umap/js/modules/data/layer.js +13 -9
- umap/static/umap/js/modules/domutils.js +4 -0
- umap/static/umap/js/modules/filters.js +11 -10
- umap/static/umap/js/modules/form/builder.js +17 -16
- umap/static/umap/js/modules/form/fields.js +16 -16
- umap/static/umap/js/modules/permissions.js +10 -2
- umap/static/umap/js/modules/rendering/controls.js +202 -9
- umap/static/umap/js/modules/rendering/layers/classified.js +1 -1
- umap/static/umap/js/modules/rendering/map.js +45 -35
- umap/static/umap/js/modules/rendering/template.js +12 -6
- umap/static/umap/js/modules/rules.js +1 -1
- umap/static/umap/js/modules/ui/bar.js +2 -1
- umap/static/umap/js/modules/ui/hash.js +36 -0
- umap/static/umap/js/modules/ui/loader.js +26 -0
- umap/static/umap/js/modules/ui/panel.js +7 -0
- umap/static/umap/js/modules/umap.js +6 -0
- umap/static/umap/js/modules/utils.js +5 -4
- umap/static/umap/js/umap.controls.js +0 -182
- umap/static/umap/locale/am_ET.js +2 -5
- umap/static/umap/locale/am_ET.json +2 -5
- umap/static/umap/locale/ar.js +2 -5
- umap/static/umap/locale/ar.json +2 -5
- umap/static/umap/locale/ast.js +2 -5
- umap/static/umap/locale/ast.json +2 -5
- umap/static/umap/locale/bg.js +2 -5
- umap/static/umap/locale/bg.json +2 -5
- umap/static/umap/locale/br.js +40 -43
- umap/static/umap/locale/br.json +40 -43
- umap/static/umap/locale/ca.js +2 -5
- umap/static/umap/locale/ca.json +2 -5
- umap/static/umap/locale/cs_CZ.js +0 -3
- umap/static/umap/locale/cs_CZ.json +0 -3
- umap/static/umap/locale/da.js +1 -4
- umap/static/umap/locale/da.json +1 -4
- umap/static/umap/locale/de.js +27 -30
- umap/static/umap/locale/de.json +27 -30
- umap/static/umap/locale/el.js +0 -3
- umap/static/umap/locale/el.json +0 -3
- umap/static/umap/locale/en.js +0 -3
- umap/static/umap/locale/en.json +0 -3
- umap/static/umap/locale/en_US.json +2 -5
- umap/static/umap/locale/es.js +0 -3
- umap/static/umap/locale/es.json +0 -3
- umap/static/umap/locale/et.js +0 -3
- umap/static/umap/locale/et.json +0 -3
- umap/static/umap/locale/eu.js +0 -3
- umap/static/umap/locale/eu.json +0 -3
- umap/static/umap/locale/fa_IR.js +0 -3
- umap/static/umap/locale/fa_IR.json +0 -3
- umap/static/umap/locale/fi.js +2 -5
- umap/static/umap/locale/fi.json +2 -5
- umap/static/umap/locale/fr.js +3 -6
- umap/static/umap/locale/fr.json +3 -6
- umap/static/umap/locale/gl.js +0 -3
- umap/static/umap/locale/gl.json +0 -3
- umap/static/umap/locale/he.js +2 -5
- umap/static/umap/locale/he.json +2 -5
- umap/static/umap/locale/hr.js +2 -5
- umap/static/umap/locale/hr.json +2 -5
- umap/static/umap/locale/hu.js +7 -10
- umap/static/umap/locale/hu.json +7 -10
- umap/static/umap/locale/id.js +2 -5
- umap/static/umap/locale/id.json +2 -5
- umap/static/umap/locale/is.js +0 -3
- umap/static/umap/locale/is.json +0 -3
- umap/static/umap/locale/it.js +0 -3
- umap/static/umap/locale/it.json +0 -3
- umap/static/umap/locale/ja.js +2 -5
- umap/static/umap/locale/ja.json +2 -5
- umap/static/umap/locale/ko.js +2 -5
- umap/static/umap/locale/ko.json +2 -5
- umap/static/umap/locale/lt.js +2 -5
- umap/static/umap/locale/lt.json +2 -5
- umap/static/umap/locale/ms.js +0 -3
- umap/static/umap/locale/ms.json +0 -3
- umap/static/umap/locale/nl.js +0 -3
- umap/static/umap/locale/nl.json +0 -3
- umap/static/umap/locale/no.js +2 -5
- umap/static/umap/locale/no.json +2 -5
- umap/static/umap/locale/pl.js +2 -5
- umap/static/umap/locale/pl.json +2 -5
- umap/static/umap/locale/pl_PL.json +2 -5
- umap/static/umap/locale/pt.js +0 -3
- umap/static/umap/locale/pt.json +0 -3
- umap/static/umap/locale/pt_BR.js +2 -5
- umap/static/umap/locale/pt_BR.json +2 -5
- umap/static/umap/locale/pt_PT.js +2 -5
- umap/static/umap/locale/pt_PT.json +2 -5
- umap/static/umap/locale/ro.js +2 -5
- umap/static/umap/locale/ro.json +2 -5
- umap/static/umap/locale/ru.js +2 -5
- umap/static/umap/locale/ru.json +2 -5
- umap/static/umap/locale/sk_SK.js +2 -5
- umap/static/umap/locale/sk_SK.json +2 -5
- umap/static/umap/locale/sl.js +2 -5
- umap/static/umap/locale/sl.json +2 -5
- umap/static/umap/locale/sr.js +2 -5
- umap/static/umap/locale/sr.json +2 -5
- umap/static/umap/locale/sv.js +2 -5
- umap/static/umap/locale/sv.json +2 -5
- umap/static/umap/locale/th_TH.js +2 -5
- umap/static/umap/locale/th_TH.json +2 -5
- umap/static/umap/locale/tr.js +2 -5
- umap/static/umap/locale/tr.json +2 -5
- umap/static/umap/locale/uk_UA.js +2 -5
- umap/static/umap/locale/uk_UA.json +2 -5
- umap/static/umap/locale/vi.js +2 -5
- umap/static/umap/locale/vi.json +2 -5
- umap/static/umap/locale/vi_VN.json +2 -5
- umap/static/umap/locale/zh.js +2 -5
- umap/static/umap/locale/zh.json +2 -5
- umap/static/umap/locale/zh_CN.json +2 -5
- umap/static/umap/locale/zh_TW.Big5.json +2 -5
- umap/static/umap/locale/zh_TW.js +1 -4
- umap/static/umap/locale/zh_TW.json +1 -4
- umap/static/umap/map.css +1 -17
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.esm.js +942 -0
- umap/static/umap/vendors/photon/leaflet.photon.esm.js +472 -0
- umap/sync/app.py +4 -1
- umap/templates/umap/css.html +0 -2
- umap/templates/umap/js.html +0 -5
- umap/templates/umap/team_form.html +2 -1
- umap/tests/fixtures/test_upload_data_with_enum.umap +151 -0
- umap/tests/integration/test_edit_map.py +2 -0
- umap/tests/integration/test_filters.py +24 -0
- umap/tests/integration/test_import.py +40 -23
- umap/tests/integration/test_map.py +1 -1
- umap/tests/integration/test_optimistic_merge.py +7 -1
- umap/tests/integration/test_remote_data.py +1 -1
- umap/tests/test_search_maps_command.py +44 -0
- umap/utils.py +9 -3
- umap/views.py +17 -4
- {umap_project-3.4.2.dist-info → umap_project-3.6.1.dist-info}/METADATA +24 -18
- {umap_project-3.4.2.dist-info → umap_project-3.6.1.dist-info}/RECORD +162 -163
- {umap_project-3.4.2.dist-info → umap_project-3.6.1.dist-info}/WHEEL +1 -1
- umap/static/umap/vendors/hash/leaflet-hash.js +0 -162
- umap/static/umap/vendors/loading/Control.Loading.css +0 -26
- umap/static/umap/vendors/loading/Control.Loading.js +0 -351
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css +0 -1
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css.map +0 -1
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js +0 -4
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js.map +0 -1
- umap/static/umap/vendors/photon/leaflet.photon.js +0 -487
- {umap_project-3.4.2.dist-info → umap_project-3.6.1.dist-info}/entry_points.txt +0 -0
- {umap_project-3.4.2.dist-info → umap_project-3.6.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -219,6 +219,30 @@ def test_choice_with_empty_value(live_server, page, map):
|
|
|
219
219
|
expect(markers).to_have_count(2)
|
|
220
220
|
|
|
221
221
|
|
|
222
|
+
def test_choice_with_numbers(live_server, page, map):
|
|
223
|
+
map.settings["properties"]["onLoadPanel"] = "datafilters"
|
|
224
|
+
map.settings["properties"]["fields"] = [{"key": "mynumber", "type": "Number"}]
|
|
225
|
+
map.settings["properties"]["filters"] = [
|
|
226
|
+
{"fieldKey": "mynumber", "label": "My Number"}
|
|
227
|
+
]
|
|
228
|
+
map.save()
|
|
229
|
+
data = copy.deepcopy(DATALAYER_DATA1)
|
|
230
|
+
data["features"][0]["properties"]["mynumber"] = ""
|
|
231
|
+
del data["features"][1]["properties"]["mynumber"]
|
|
232
|
+
DataLayerFactory(map=map, data=data)
|
|
233
|
+
DataLayerFactory(map=map, data=DATALAYER_DATA2)
|
|
234
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}#6/47.5/-1.5")
|
|
235
|
+
expect(page.get_by_text("<empty value>")).to_be_visible()
|
|
236
|
+
expect(page.get_by_text("14")).to_be_visible()
|
|
237
|
+
markers = page.locator(".leaflet-marker-icon")
|
|
238
|
+
expect(markers).to_have_count(4)
|
|
239
|
+
page.get_by_text("14", exact=True).click()
|
|
240
|
+
expect(markers).to_have_count(1)
|
|
241
|
+
page.get_by_text("14", exact=True).click() # Unselect this filter.
|
|
242
|
+
page.get_by_text("<empty value>", exact=True).click()
|
|
243
|
+
expect(markers).to_have_count(2)
|
|
244
|
+
|
|
245
|
+
|
|
222
246
|
def test_number_with_zero_value(live_server, page, map):
|
|
223
247
|
map.settings["properties"]["onLoadPanel"] = "datafilters"
|
|
224
248
|
map.settings["properties"]["filters"] = [
|
|
@@ -13,6 +13,8 @@ from .helpers import save_and_get_json
|
|
|
13
13
|
|
|
14
14
|
pytestmark = pytest.mark.django_db
|
|
15
15
|
|
|
16
|
+
PANEL_ANIMATION_TIME = 350
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
def test_layers_list_is_updated(live_server, tilelayer, page):
|
|
18
20
|
page.goto(f"{live_server.url}/map/new/")
|
|
@@ -75,7 +77,7 @@ def test_umap_import_from_textarea(live_server, tilelayer, page, settings):
|
|
|
75
77
|
page.goto(f"{live_server.url}/map/new/")
|
|
76
78
|
page.get_by_role("button", name="Open browser").click()
|
|
77
79
|
page.get_by_title("Import data").click()
|
|
78
|
-
page.wait_for_timeout(
|
|
80
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
79
81
|
textarea = page.locator(".umap-import textarea")
|
|
80
82
|
path = Path(__file__).parent.parent / "fixtures/test_upload_data.umap"
|
|
81
83
|
textarea.fill(path.read_text())
|
|
@@ -109,7 +111,7 @@ def test_import_geojson_from_textarea(tilelayer, live_server, page):
|
|
|
109
111
|
expect(paths).to_have_count(0)
|
|
110
112
|
expect(layers).to_have_count(0)
|
|
111
113
|
page.get_by_title("Import data").click()
|
|
112
|
-
page.wait_for_timeout(
|
|
114
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
113
115
|
textarea = page.locator(".umap-import textarea")
|
|
114
116
|
path = Path(__file__).parent.parent / "fixtures/test_upload_data.json"
|
|
115
117
|
textarea.fill(path.read_text())
|
|
@@ -133,7 +135,7 @@ def test_import_invalid_data(tilelayer, live_server, page):
|
|
|
133
135
|
expect(paths).to_have_count(0)
|
|
134
136
|
expect(layers).to_have_count(0)
|
|
135
137
|
page.get_by_title("Import data").click()
|
|
136
|
-
page.wait_for_timeout(
|
|
138
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
137
139
|
textarea = page.locator(".umap-import textarea")
|
|
138
140
|
textarea.fill("invalid data")
|
|
139
141
|
for format in ["geojson", "csv", "gpx", "kml", "georss", "osm", "umap"]:
|
|
@@ -152,7 +154,7 @@ def test_import_kml_from_textarea(tilelayer, live_server, page):
|
|
|
152
154
|
expect(paths).to_have_count(0)
|
|
153
155
|
expect(layers).to_have_count(0)
|
|
154
156
|
page.get_by_title("Import data").click()
|
|
155
|
-
page.wait_for_timeout(
|
|
157
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
156
158
|
textarea = page.locator(".umap-import textarea")
|
|
157
159
|
path = Path(__file__).parent.parent / "fixtures/test_upload_data.kml"
|
|
158
160
|
textarea.fill(path.read_text())
|
|
@@ -175,7 +177,7 @@ def test_import_gpx_from_textarea(tilelayer, live_server, page, settings):
|
|
|
175
177
|
expect(paths).to_have_count(0)
|
|
176
178
|
expect(layers).to_have_count(0)
|
|
177
179
|
page.get_by_title("Import data").click()
|
|
178
|
-
page.wait_for_timeout(
|
|
180
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
179
181
|
textarea = page.locator(".umap-import textarea")
|
|
180
182
|
path = Path(__file__).parent.parent / "fixtures/test_upload_data.gpx"
|
|
181
183
|
textarea.fill(path.read_text())
|
|
@@ -231,7 +233,7 @@ def test_import_osm_from_textarea(tilelayer, live_server, page):
|
|
|
231
233
|
expect(markers).to_have_count(0)
|
|
232
234
|
expect(layers).to_have_count(0)
|
|
233
235
|
page.get_by_title("Import data").click()
|
|
234
|
-
page.wait_for_timeout(
|
|
236
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
235
237
|
textarea = page.locator(".umap-import textarea")
|
|
236
238
|
path = Path(__file__).parent.parent / "fixtures/test_upload_data_osm.json"
|
|
237
239
|
textarea.fill(path.read_text())
|
|
@@ -250,7 +252,7 @@ def test_import_csv_from_textarea(tilelayer, live_server, page):
|
|
|
250
252
|
expect(markers).to_have_count(0)
|
|
251
253
|
expect(layers).to_have_count(0)
|
|
252
254
|
page.get_by_title("Import data").click()
|
|
253
|
-
page.wait_for_timeout(
|
|
255
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
254
256
|
textarea = page.locator(".umap-import textarea")
|
|
255
257
|
path = Path(__file__).parent.parent / "fixtures/test_upload_data.csv"
|
|
256
258
|
textarea.fill(path.read_text())
|
|
@@ -270,7 +272,7 @@ def test_can_import_in_existing_datalayer(live_server, datalayer, page, openmap)
|
|
|
270
272
|
expect(layers).to_have_count(1)
|
|
271
273
|
page.get_by_role("button", name="Edit").click()
|
|
272
274
|
page.get_by_title("Import data").click()
|
|
273
|
-
page.wait_for_timeout(
|
|
275
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
274
276
|
textarea = page.locator(".umap-import textarea")
|
|
275
277
|
path = Path(__file__).parent.parent / "fixtures/test_upload_data.csv"
|
|
276
278
|
textarea.fill(path.read_text())
|
|
@@ -292,7 +294,7 @@ def test_can_replace_datalayer_data(live_server, datalayer, page, openmap):
|
|
|
292
294
|
expect(layers).to_have_count(1)
|
|
293
295
|
page.get_by_role("button", name="Edit").click()
|
|
294
296
|
page.get_by_title("Import data").click()
|
|
295
|
-
page.wait_for_timeout(
|
|
297
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
296
298
|
textarea = page.locator(".umap-import textarea")
|
|
297
299
|
path = Path(__file__).parent.parent / "fixtures/test_upload_data.csv"
|
|
298
300
|
textarea.fill(path.read_text())
|
|
@@ -314,7 +316,7 @@ def test_can_import_in_new_datalayer(live_server, datalayer, page, openmap):
|
|
|
314
316
|
expect(layers).to_have_count(1)
|
|
315
317
|
page.get_by_role("button", name="Edit").click()
|
|
316
318
|
page.get_by_title("Import data").click()
|
|
317
|
-
page.wait_for_timeout(
|
|
319
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
318
320
|
textarea = page.locator(".umap-import textarea")
|
|
319
321
|
path = Path(__file__).parent.parent / "fixtures/test_upload_data.csv"
|
|
320
322
|
textarea.fill(path.read_text())
|
|
@@ -361,7 +363,7 @@ def test_should_remove_dot_in_property_names(live_server, page, settings, tilela
|
|
|
361
363
|
}
|
|
362
364
|
page.goto(f"{live_server.url}/map/new/")
|
|
363
365
|
page.get_by_title("Import data").click()
|
|
364
|
-
page.wait_for_timeout(
|
|
366
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
365
367
|
textarea = page.locator(".umap-import textarea")
|
|
366
368
|
textarea.fill(json.dumps(data))
|
|
367
369
|
page.locator('select[name="format"]').select_option("geojson")
|
|
@@ -421,7 +423,7 @@ def test_import_geometry_collection(live_server, page, tilelayer):
|
|
|
421
423
|
expect(paths).to_have_count(0)
|
|
422
424
|
expect(layers).to_have_count(0)
|
|
423
425
|
page.get_by_title("Import data").click()
|
|
424
|
-
page.wait_for_timeout(
|
|
426
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
425
427
|
textarea = page.locator(".umap-import textarea")
|
|
426
428
|
textarea.fill(json.dumps(data))
|
|
427
429
|
page.locator('select[name="format"]').select_option("geojson")
|
|
@@ -475,7 +477,7 @@ def test_import_geometry_collection_in_feature(live_server, page, tilelayer):
|
|
|
475
477
|
expect(paths).to_have_count(0)
|
|
476
478
|
expect(layers).to_have_count(0)
|
|
477
479
|
page.get_by_title("Import data").click()
|
|
478
|
-
page.wait_for_timeout(
|
|
480
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
479
481
|
textarea = page.locator(".umap-import textarea")
|
|
480
482
|
textarea.fill(json.dumps(data))
|
|
481
483
|
page.locator('select[name="format"]').select_option("geojson")
|
|
@@ -485,6 +487,7 @@ def test_import_geometry_collection_in_feature(live_server, page, tilelayer):
|
|
|
485
487
|
expect(markers).to_have_count(1)
|
|
486
488
|
expect(paths).to_have_count(2)
|
|
487
489
|
# Geometries are treated as separate features.
|
|
490
|
+
page.get_by_text("Layer 1").click() # Open layer box in browser.
|
|
488
491
|
expect(page.get_by_text("foobar")).to_have_count(3)
|
|
489
492
|
|
|
490
493
|
|
|
@@ -510,7 +513,7 @@ def test_import_multipolygon(live_server, page, tilelayer):
|
|
|
510
513
|
expect(paths).to_have_count(0)
|
|
511
514
|
expect(layers).to_have_count(0)
|
|
512
515
|
page.get_by_title("Import data").click()
|
|
513
|
-
page.wait_for_timeout(
|
|
516
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
514
517
|
textarea = page.locator(".umap-import textarea")
|
|
515
518
|
textarea.fill(json.dumps(data))
|
|
516
519
|
page.locator('select[name="format"]').select_option("geojson")
|
|
@@ -541,7 +544,7 @@ def test_import_multipolyline(live_server, page, tilelayer):
|
|
|
541
544
|
expect(paths).to_have_count(0)
|
|
542
545
|
expect(layers).to_have_count(0)
|
|
543
546
|
page.get_by_title("Import data").click()
|
|
544
|
-
page.wait_for_timeout(
|
|
547
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
545
548
|
textarea = page.locator(".umap-import textarea")
|
|
546
549
|
textarea.fill(json.dumps(data))
|
|
547
550
|
page.locator('select[name="format"]').select_option("geojson")
|
|
@@ -572,7 +575,7 @@ def test_import_false_multipoint(live_server, page, tilelayer):
|
|
|
572
575
|
expect(markers).to_have_count(0)
|
|
573
576
|
expect(layers).to_have_count(0)
|
|
574
577
|
page.get_by_title("Import data").click()
|
|
575
|
-
page.wait_for_timeout(
|
|
578
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
576
579
|
textarea = page.locator(".umap-import textarea")
|
|
577
580
|
textarea.fill(json.dumps(data))
|
|
578
581
|
page.locator('select[name="format"]').select_option("geojson")
|
|
@@ -637,7 +640,7 @@ def test_should_not_import_empty_coordinates(live_server, page, tilelayer):
|
|
|
637
640
|
page.goto(f"{live_server.url}/map/new/")
|
|
638
641
|
page.get_by_title("Open browser").click()
|
|
639
642
|
page.get_by_title("Import data").click()
|
|
640
|
-
page.wait_for_timeout(
|
|
643
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
641
644
|
textarea = page.locator(".umap-import textarea")
|
|
642
645
|
textarea.fill(json.dumps(data))
|
|
643
646
|
page.locator('select[name="format"]').select_option("geojson")
|
|
@@ -653,7 +656,7 @@ def test_import_csv_without_valid_latlon_headers(tilelayer, live_server, page):
|
|
|
653
656
|
layers = page.locator(".umap-browser .datalayer")
|
|
654
657
|
markers = page.locator(".leaflet-marker-icon")
|
|
655
658
|
page.get_by_title("Import data").click()
|
|
656
|
-
page.wait_for_timeout(
|
|
659
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
657
660
|
textarea = page.locator(".umap-import textarea")
|
|
658
661
|
textarea.fill("a,b,c\n12.23,48.34,mypoint\n12.23,48.34,mypoint2")
|
|
659
662
|
page.locator('select[name="format"]').select_option("csv")
|
|
@@ -671,7 +674,7 @@ def test_import_csv_with_commas_in_latlon(tilelayer, live_server, page, settings
|
|
|
671
674
|
layers = page.locator(".umap-browser .datalayer")
|
|
672
675
|
markers = page.locator(".leaflet-marker-icon")
|
|
673
676
|
page.get_by_title("Import data").click()
|
|
674
|
-
page.wait_for_timeout(
|
|
677
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
675
678
|
textarea = page.locator(".umap-import textarea")
|
|
676
679
|
textarea.fill("lat;lon;foobar\n12,24;48,34;mypoint\n12,23;48,35;mypoint2")
|
|
677
680
|
page.locator('select[name="format"]').select_option("csv")
|
|
@@ -706,7 +709,7 @@ def test_import_csv_with_wkt_geom(tilelayer, live_server, page, settings):
|
|
|
706
709
|
markers = page.locator(".leaflet-marker-icon")
|
|
707
710
|
paths = page.locator("path")
|
|
708
711
|
page.get_by_title("Import data").click()
|
|
709
|
-
page.wait_for_timeout(
|
|
712
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
710
713
|
textarea = page.locator(".umap-import textarea")
|
|
711
714
|
textarea.fill(
|
|
712
715
|
"Geom;foobar\nPOLYGON ((-64.8 32.3, -65.5 18.3, -80.3 25.2, -64.8 32.3));mypoly\nPOINT(48.35 12.23);mypoint"
|
|
@@ -760,7 +763,7 @@ def test_import_csv_with_geojson_geom(tilelayer, live_server, page, settings):
|
|
|
760
763
|
markers = page.locator(".leaflet-marker-icon")
|
|
761
764
|
paths = page.locator("path")
|
|
762
765
|
page.get_by_title("Import data").click()
|
|
763
|
-
page.wait_for_timeout(
|
|
766
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
764
767
|
textarea = page.locator(".umap-import textarea")
|
|
765
768
|
textarea.fill(
|
|
766
769
|
"geojson;foobar\n"
|
|
@@ -1055,7 +1058,7 @@ def test_import_osm_relation(tilelayer, live_server, page):
|
|
|
1055
1058
|
expect(paths).to_have_count(0)
|
|
1056
1059
|
expect(layers).to_have_count(0)
|
|
1057
1060
|
page.get_by_title("Import data").click()
|
|
1058
|
-
page.wait_for_timeout(
|
|
1061
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
1059
1062
|
textarea = page.locator(".umap-import textarea")
|
|
1060
1063
|
file_path = Path(__file__).parent.parent / "fixtures/test_import_osm_relation.json"
|
|
1061
1064
|
textarea.fill(file_path.read_text())
|
|
@@ -1074,7 +1077,7 @@ def test_import_georss_from_textarea(tilelayer, live_server, page):
|
|
|
1074
1077
|
expect(markers).to_have_count(0)
|
|
1075
1078
|
expect(layers).to_have_count(0)
|
|
1076
1079
|
page.get_by_title("Import data").click()
|
|
1077
|
-
page.wait_for_timeout(
|
|
1080
|
+
page.wait_for_timeout(PANEL_ANIMATION_TIME)
|
|
1078
1081
|
textarea = page.locator(".umap-import textarea")
|
|
1079
1082
|
path = Path(__file__).parent.parent / "fixtures/test_upload_georss.xml"
|
|
1080
1083
|
textarea.fill(path.read_text())
|
|
@@ -1120,3 +1123,17 @@ def test_umap_import_with_iconurl(live_server, tilelayer, page):
|
|
|
1120
1123
|
'img[src="https://umap.incubateur.anct.gouv.fr/uploads/pictogram/car-24.png"]'
|
|
1121
1124
|
)
|
|
1122
1125
|
).to_have_count(2)
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
def test_umap_import_with_enum_and_filter(live_server, tilelayer, page):
|
|
1129
|
+
page.goto(f"{live_server.url}/map/new/")
|
|
1130
|
+
page.get_by_title("Import data").click()
|
|
1131
|
+
file_input = page.locator("input[type='file']")
|
|
1132
|
+
with page.expect_file_chooser() as fc_info:
|
|
1133
|
+
file_input.click()
|
|
1134
|
+
file_chooser = fc_info.value
|
|
1135
|
+
path = Path(__file__).parent.parent / "fixtures/test_upload_data_with_enum.umap"
|
|
1136
|
+
file_chooser.set_files(path)
|
|
1137
|
+
page.get_by_role("button", name="Import data", exact=True).click()
|
|
1138
|
+
markers = page.locator(".umap-large-circle-icon")
|
|
1139
|
+
expect(markers).to_have_count(4)
|
|
@@ -156,7 +156,7 @@ def test_default_view_locate(browser, live_server, map, new_page):
|
|
|
156
156
|
map.save()
|
|
157
157
|
page = new_page(custom_context=context)
|
|
158
158
|
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
|
159
|
-
expect(page).to_have_url(re.compile(r".*#18/39\.
|
|
159
|
+
expect(page).to_have_url(re.compile(r".*#18/39\.162670/8\.529670"))
|
|
160
160
|
|
|
161
161
|
|
|
162
162
|
def test_remote_layer_should_not_be_used_as_datalayer_for_created_features(
|
|
@@ -3,6 +3,7 @@ import re
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from time import sleep
|
|
5
5
|
|
|
6
|
+
import pytest
|
|
6
7
|
from playwright.sync_api import expect
|
|
7
8
|
|
|
8
9
|
from umap.models import DataLayer
|
|
@@ -12,7 +13,12 @@ from ..base import DataLayerFactory, MapFactory
|
|
|
12
13
|
DATALAYER_UPDATE = re.compile(r".*/datalayer/update/.*")
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
# Test with in memory upload AND streamed upload
|
|
17
|
+
@pytest.mark.parametrize("upload_limit", (2621440, 0))
|
|
18
|
+
def test_created_markers_are_merged(
|
|
19
|
+
new_page, live_server, tilelayer, settings, upload_limit
|
|
20
|
+
):
|
|
21
|
+
settings.FILE_UPLOAD_MAX_MEMORY_SIZE = upload_limit
|
|
16
22
|
# Let's create a new map with an empty datalayer
|
|
17
23
|
map = MapFactory(name="server-side merge")
|
|
18
24
|
datalayer = DataLayerFactory(map=map, edit_status=DataLayer.ANONYMOUS, data={})
|
|
@@ -44,7 +44,6 @@ def intercept_remote_data(page):
|
|
|
44
44
|
|
|
45
45
|
# Intercept the route to the proxy
|
|
46
46
|
page.route("https://remote.org/data.json", handle)
|
|
47
|
-
page.on("request", lambda *a, **k: print(a, k))
|
|
48
47
|
|
|
49
48
|
|
|
50
49
|
def test_dynamic_remote_data(page, live_server, tilelayer, map):
|
|
@@ -104,6 +103,7 @@ def test_create_remote_data_layer(page, live_server, tilelayer, settings):
|
|
|
104
103
|
expect(page.locator(".leaflet-marker-icon")).to_have_count(1)
|
|
105
104
|
with page.expect_response(re.compile(".*/datalayer/create/.*")):
|
|
106
105
|
page.get_by_role("button", name="Save draft", exact=True).click()
|
|
106
|
+
assert DataLayer.objects.count() == 1
|
|
107
107
|
datalayer = DataLayer.objects.last()
|
|
108
108
|
data = json.loads(Path(datalayer.geojson.path).read_text())
|
|
109
109
|
assert data == {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from django.core.management import call_command
|
|
3
|
+
|
|
4
|
+
from umap.models import Map
|
|
5
|
+
|
|
6
|
+
from .base import MapFactory
|
|
7
|
+
|
|
8
|
+
pytestmark = pytest.mark.django_db
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_search_and_delete_maps(map, team):
|
|
12
|
+
target = MapFactory(name="find me")
|
|
13
|
+
assert Map.objects.filter(share_status=Map.DELETED).count() == 0
|
|
14
|
+
|
|
15
|
+
call_command("search_maps", "find", "--delete", "--dry-run", "--no-input")
|
|
16
|
+
assert Map.objects.filter(share_status=Map.DELETED).count() == 0
|
|
17
|
+
|
|
18
|
+
call_command("search_maps", "find", "--delete", "--no-input")
|
|
19
|
+
assert Map.objects.filter(share_status=Map.DELETED).count() == 1
|
|
20
|
+
|
|
21
|
+
assert not Map.public.filter(pk=target.pk)
|
|
22
|
+
|
|
23
|
+
call_command("search_maps", "find", "--restore", "--no-input")
|
|
24
|
+
assert Map.objects.filter(share_status=Map.DELETED).count() == 0
|
|
25
|
+
|
|
26
|
+
assert Map.objects.get(pk=target.pk).share_status == Map.DRAFT
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_search_and_block_maps(map, team):
|
|
30
|
+
target = MapFactory(name="find me")
|
|
31
|
+
assert Map.objects.filter(share_status=Map.BLOCKED).count() == 0
|
|
32
|
+
|
|
33
|
+
call_command("search_maps", "find", "--block", "--dry-run", "--no-input")
|
|
34
|
+
assert Map.objects.filter(share_status=Map.BLOCKED).count() == 0
|
|
35
|
+
|
|
36
|
+
call_command("search_maps", "find", "--block", "--no-input")
|
|
37
|
+
assert Map.objects.filter(share_status=Map.BLOCKED).count() == 1
|
|
38
|
+
|
|
39
|
+
assert not Map.public.filter(pk=target.pk)
|
|
40
|
+
|
|
41
|
+
call_command("search_maps", "find", "--restore", "--no-input")
|
|
42
|
+
assert Map.objects.filter(share_status=Map.BLOCKED).count() == 0
|
|
43
|
+
|
|
44
|
+
assert Map.objects.get(pk=target.pk).share_status == Map.DRAFT
|
umap/utils.py
CHANGED
|
@@ -7,7 +7,7 @@ from pathlib import Path
|
|
|
7
7
|
from django.conf import settings
|
|
8
8
|
from django.contrib.staticfiles import finders
|
|
9
9
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
10
|
-
from django.urls import URLPattern, URLResolver, get_resolver
|
|
10
|
+
from django.urls import URLPattern, URLResolver, get_resolver, reverse
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def _get_url_names(module):
|
|
@@ -29,14 +29,20 @@ def _urls_for_js():
|
|
|
29
29
|
"""
|
|
30
30
|
Return templated URLs prepared for javascript.
|
|
31
31
|
"""
|
|
32
|
-
urls = {
|
|
32
|
+
urls = {
|
|
33
|
+
"agnocomplete": f"{reverse('agnocomplete:agnocomplete', kwargs={'klass': 'AutocompleteUser'})}?q={{q}}"
|
|
34
|
+
}
|
|
33
35
|
modules = ["umap.urls"]
|
|
34
36
|
if settings.REALTIME_ENABLED:
|
|
35
37
|
modules.append("umap.sync.app")
|
|
36
38
|
for module in modules:
|
|
37
39
|
names = _get_url_names(module)
|
|
40
|
+
prefix = settings.FORCE_SCRIPT_NAME or ""
|
|
38
41
|
urls.update(
|
|
39
|
-
|
|
42
|
+
zip(
|
|
43
|
+
names,
|
|
44
|
+
[get_uri_template(url, prefix=prefix, module=module) for url in names],
|
|
45
|
+
)
|
|
40
46
|
)
|
|
41
47
|
urls.update(getattr(settings, "UMAP_EXTRA_URLS", {}))
|
|
42
48
|
return urls
|
umap/views.py
CHANGED
|
@@ -6,7 +6,6 @@ import socket
|
|
|
6
6
|
import zipfile
|
|
7
7
|
from datetime import datetime, timedelta
|
|
8
8
|
from http.client import InvalidURL
|
|
9
|
-
from io import BytesIO
|
|
10
9
|
from pathlib import Path
|
|
11
10
|
from smtplib import SMTPException
|
|
12
11
|
from urllib.error import HTTPError, URLError
|
|
@@ -22,6 +21,7 @@ from django.contrib.postgres.search import SearchQuery, SearchVector
|
|
|
22
21
|
from django.contrib.sessions.models import Session
|
|
23
22
|
from django.contrib.staticfiles.storage import staticfiles_storage
|
|
24
23
|
from django.core.exceptions import PermissionDenied
|
|
24
|
+
from django.core.files.uploadedfile import InMemoryUploadedFile
|
|
25
25
|
from django.core.mail import send_mail
|
|
26
26
|
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
|
|
27
27
|
from django.core.signing import BadSignature, Signer, TimestampSigner
|
|
@@ -610,7 +610,8 @@ class MapDetailMixin(SessionMixin):
|
|
|
610
610
|
|
|
611
611
|
def set_preconnect(self, properties, context):
|
|
612
612
|
# Try to extract the tilelayer domain, in order to but a preconnect meta.
|
|
613
|
-
|
|
613
|
+
tilelayer = properties.get("tilelayer") or {}
|
|
614
|
+
url_template = tilelayer.get("url_template")
|
|
614
615
|
# Not explicit tilelayer set, take the first of the list, which will be
|
|
615
616
|
# used by frontend too.
|
|
616
617
|
if not url_template:
|
|
@@ -1335,8 +1336,20 @@ class DataLayerUpdate(FormLessEditMixin, UpdateView):
|
|
|
1335
1336
|
return HttpResponse(status=412)
|
|
1336
1337
|
|
|
1337
1338
|
# Replace the uploaded file by the merged version.
|
|
1338
|
-
|
|
1339
|
-
|
|
1339
|
+
# The geojson here can be either a NamedTemporaryFile or an
|
|
1340
|
+
# InMemoryUploadedFile, depending on whether is bigger than the
|
|
1341
|
+
# FILE_UPLOAD_MAX_MEMORY_SIZE setting (2.5Mo by default).
|
|
1342
|
+
# Now that we loaded all in RAM, let's use an InMemoryUploadedFile.
|
|
1343
|
+
orig = self.request.FILES["geojson"]
|
|
1344
|
+
file = io.BytesIO(json_dumps(merged).encode("utf-8"))
|
|
1345
|
+
file_size = file.getbuffer().nbytes
|
|
1346
|
+
self.request.FILES["geojson"] = InMemoryUploadedFile(
|
|
1347
|
+
file=file,
|
|
1348
|
+
field_name="geojson",
|
|
1349
|
+
name=orig.name,
|
|
1350
|
+
content_type="application/geo+json",
|
|
1351
|
+
size=file_size,
|
|
1352
|
+
charset="utf-8",
|
|
1340
1353
|
)
|
|
1341
1354
|
|
|
1342
1355
|
# Mark the data to be reloaded by form_valid
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: umap-project
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6.1
|
|
4
4
|
Summary: Create maps with OpenStreetMap layers in a minute and embed them in your site.
|
|
5
5
|
Author-email: Yohan Boniface <yb@enix.org>
|
|
6
6
|
Maintainer-email: David Larlet <david@larlet.fr>
|
|
@@ -18,43 +18,49 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
18
18
|
Requires-Python: >=3.10
|
|
19
19
|
Requires-Dist: django-agnocomplete==2.2.0
|
|
20
20
|
Requires-Dist: django-environ==0.12.0
|
|
21
|
-
Requires-Dist: django-probes==1.
|
|
22
|
-
Requires-Dist: django
|
|
23
|
-
Requires-Dist: pillow==12.
|
|
24
|
-
Requires-Dist: psycopg==3.2
|
|
21
|
+
Requires-Dist: django-probes==1.8.0
|
|
22
|
+
Requires-Dist: django<6.0,>=5.1
|
|
23
|
+
Requires-Dist: pillow==12.1.0
|
|
24
|
+
Requires-Dist: psycopg==3.3.2
|
|
25
25
|
Requires-Dist: rcssmin==1.2.2
|
|
26
26
|
Requires-Dist: requests==2.32.5
|
|
27
27
|
Requires-Dist: rjsmin==1.2.5
|
|
28
|
-
Requires-Dist: social-auth-app-django==5.
|
|
29
|
-
Requires-Dist: social-auth-core==4.8.
|
|
28
|
+
Requires-Dist: social-auth-app-django==5.7.0
|
|
29
|
+
Requires-Dist: social-auth-core==4.8.3
|
|
30
|
+
Provides-Extra: deploy
|
|
31
|
+
Requires-Dist: django==5.2.10; extra == 'deploy'
|
|
30
32
|
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: django==5.2.9; extra == 'dev'
|
|
31
34
|
Requires-Dist: djlint==1.36.4; extra == 'dev'
|
|
32
35
|
Requires-Dist: hatch==1.15.1; extra == 'dev'
|
|
33
36
|
Requires-Dist: isort==7.0.0; extra == 'dev'
|
|
34
|
-
Requires-Dist: mkdocs-material==9.7.
|
|
37
|
+
Requires-Dist: mkdocs-material==9.7.1; extra == 'dev'
|
|
35
38
|
Requires-Dist: mkdocs-static-i18n==1.3.0; extra == 'dev'
|
|
36
39
|
Requires-Dist: mkdocs==1.6.1; extra == 'dev'
|
|
37
|
-
Requires-Dist: pymdown-extensions==10.
|
|
38
|
-
Requires-Dist: ruff==0.14.
|
|
39
|
-
Requires-Dist: vermin==1.
|
|
40
|
-
Provides-Extra: docker
|
|
41
|
-
Requires-Dist: uvicorn==0.38.0; extra == 'docker'
|
|
40
|
+
Requires-Dist: pymdown-extensions==10.20.1; extra == 'dev'
|
|
41
|
+
Requires-Dist: ruff==0.14.14; extra == 'dev'
|
|
42
|
+
Requires-Dist: vermin==1.8.0; extra == 'dev'
|
|
42
43
|
Provides-Extra: s3
|
|
43
44
|
Requires-Dist: django-storages[s3]==1.14.6; extra == 's3'
|
|
44
45
|
Provides-Extra: sync
|
|
45
|
-
Requires-Dist: pydantic==2.12.
|
|
46
|
+
Requires-Dist: pydantic==2.12.5; extra == 'sync'
|
|
46
47
|
Requires-Dist: redis==7.1.0; extra == 'sync'
|
|
47
|
-
Requires-Dist:
|
|
48
|
+
Requires-Dist: uvicorn==0.40.0; extra == 'sync'
|
|
49
|
+
Requires-Dist: websockets==16.0; extra == 'sync'
|
|
48
50
|
Provides-Extra: test
|
|
49
51
|
Requires-Dist: daphne==4.2.1; extra == 'test'
|
|
50
52
|
Requires-Dist: factory-boy==3.3.3; extra == 'test'
|
|
51
|
-
Requires-Dist: moto[s3]==5.1.
|
|
53
|
+
Requires-Dist: moto[s3]==5.1.20; extra == 'test'
|
|
52
54
|
Requires-Dist: playwright>=1.39; extra == 'test'
|
|
53
55
|
Requires-Dist: pytest-django==4.11.1; extra == 'test'
|
|
54
|
-
Requires-Dist: pytest-playwright==0.7.
|
|
56
|
+
Requires-Dist: pytest-playwright==0.7.2; extra == 'test'
|
|
55
57
|
Requires-Dist: pytest-rerunfailures==16.1; extra == 'test'
|
|
56
58
|
Requires-Dist: pytest-xdist<4,>=3.5.0; extra == 'test'
|
|
57
|
-
Requires-Dist: pytest==
|
|
59
|
+
Requires-Dist: pytest==9.0.2; extra == 'test'
|
|
60
|
+
Provides-Extra: yunohost
|
|
61
|
+
Requires-Dist: django-yunohost-integration==0.10.9; extra == 'yunohost'
|
|
62
|
+
Requires-Dist: django==5.1.15; extra == 'yunohost'
|
|
63
|
+
Requires-Dist: uvicorn==0.40.0; extra == 'yunohost'
|
|
58
64
|
Description-Content-Type: text/markdown
|
|
59
65
|
|
|
60
66
|
[](https://matrix.to/#/#umap:matrix.org)
|