umap-project 3.4.2__py3-none-any.whl → 3.6.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.
Files changed (168) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  3. umap/locale/br/LC_MESSAGES/django.po +71 -57
  4. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  5. umap/locale/de/LC_MESSAGES/django.po +20 -16
  6. umap/locale/en/LC_MESSAGES/django.po +14 -14
  7. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/hu/LC_MESSAGES/django.po +20 -16
  9. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/pl/LC_MESSAGES/django.po +32 -27
  11. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  12. umap/locale/zh_TW/LC_MESSAGES/django.po +20 -16
  13. umap/management/commands/clean_tilelayer.py +0 -1
  14. umap/management/commands/search_maps.py +95 -0
  15. umap/settings/__init__.py +9 -1
  16. umap/settings/base.py +7 -6
  17. umap/static/umap/css/icon.css +8 -0
  18. umap/static/umap/img/16-white.svg +5 -2
  19. umap/static/umap/img/16.svg +1 -1
  20. umap/static/umap/img/source/16-white.svg +7 -4
  21. umap/static/umap/img/source/16.svg +1 -1
  22. umap/static/umap/js/modules/autocomplete.js +1 -9
  23. umap/static/umap/js/modules/browser.js +27 -10
  24. umap/static/umap/js/modules/data/features.js +3 -2
  25. umap/static/umap/js/modules/data/fields.js +12 -2
  26. umap/static/umap/js/modules/data/layer.js +13 -9
  27. umap/static/umap/js/modules/domutils.js +4 -0
  28. umap/static/umap/js/modules/filters.js +11 -10
  29. umap/static/umap/js/modules/form/builder.js +17 -16
  30. umap/static/umap/js/modules/form/fields.js +16 -16
  31. umap/static/umap/js/modules/permissions.js +10 -2
  32. umap/static/umap/js/modules/rendering/controls.js +202 -9
  33. umap/static/umap/js/modules/rendering/layers/classified.js +1 -1
  34. umap/static/umap/js/modules/rendering/map.js +45 -35
  35. umap/static/umap/js/modules/rendering/template.js +12 -6
  36. umap/static/umap/js/modules/ui/bar.js +2 -1
  37. umap/static/umap/js/modules/ui/hash.js +36 -0
  38. umap/static/umap/js/modules/ui/loader.js +26 -0
  39. umap/static/umap/js/modules/ui/panel.js +7 -0
  40. umap/static/umap/js/modules/umap.js +6 -0
  41. umap/static/umap/js/modules/utils.js +5 -4
  42. umap/static/umap/js/umap.controls.js +0 -182
  43. umap/static/umap/locale/am_ET.js +2 -5
  44. umap/static/umap/locale/am_ET.json +2 -5
  45. umap/static/umap/locale/ar.js +2 -5
  46. umap/static/umap/locale/ar.json +2 -5
  47. umap/static/umap/locale/ast.js +2 -5
  48. umap/static/umap/locale/ast.json +2 -5
  49. umap/static/umap/locale/bg.js +2 -5
  50. umap/static/umap/locale/bg.json +2 -5
  51. umap/static/umap/locale/br.js +40 -43
  52. umap/static/umap/locale/br.json +40 -43
  53. umap/static/umap/locale/ca.js +2 -5
  54. umap/static/umap/locale/ca.json +2 -5
  55. umap/static/umap/locale/cs_CZ.js +0 -3
  56. umap/static/umap/locale/cs_CZ.json +0 -3
  57. umap/static/umap/locale/da.js +1 -4
  58. umap/static/umap/locale/da.json +1 -4
  59. umap/static/umap/locale/de.js +27 -30
  60. umap/static/umap/locale/de.json +27 -30
  61. umap/static/umap/locale/el.js +0 -3
  62. umap/static/umap/locale/el.json +0 -3
  63. umap/static/umap/locale/en.js +0 -3
  64. umap/static/umap/locale/en.json +0 -3
  65. umap/static/umap/locale/en_US.json +2 -5
  66. umap/static/umap/locale/es.js +0 -3
  67. umap/static/umap/locale/es.json +0 -3
  68. umap/static/umap/locale/et.js +0 -3
  69. umap/static/umap/locale/et.json +0 -3
  70. umap/static/umap/locale/eu.js +0 -3
  71. umap/static/umap/locale/eu.json +0 -3
  72. umap/static/umap/locale/fa_IR.js +0 -3
  73. umap/static/umap/locale/fa_IR.json +0 -3
  74. umap/static/umap/locale/fi.js +2 -5
  75. umap/static/umap/locale/fi.json +2 -5
  76. umap/static/umap/locale/fr.js +3 -6
  77. umap/static/umap/locale/fr.json +3 -6
  78. umap/static/umap/locale/gl.js +0 -3
  79. umap/static/umap/locale/gl.json +0 -3
  80. umap/static/umap/locale/he.js +2 -5
  81. umap/static/umap/locale/he.json +2 -5
  82. umap/static/umap/locale/hr.js +2 -5
  83. umap/static/umap/locale/hr.json +2 -5
  84. umap/static/umap/locale/hu.js +7 -10
  85. umap/static/umap/locale/hu.json +7 -10
  86. umap/static/umap/locale/id.js +2 -5
  87. umap/static/umap/locale/id.json +2 -5
  88. umap/static/umap/locale/is.js +0 -3
  89. umap/static/umap/locale/is.json +0 -3
  90. umap/static/umap/locale/it.js +0 -3
  91. umap/static/umap/locale/it.json +0 -3
  92. umap/static/umap/locale/ja.js +2 -5
  93. umap/static/umap/locale/ja.json +2 -5
  94. umap/static/umap/locale/ko.js +2 -5
  95. umap/static/umap/locale/ko.json +2 -5
  96. umap/static/umap/locale/lt.js +2 -5
  97. umap/static/umap/locale/lt.json +2 -5
  98. umap/static/umap/locale/ms.js +0 -3
  99. umap/static/umap/locale/ms.json +0 -3
  100. umap/static/umap/locale/nl.js +0 -3
  101. umap/static/umap/locale/nl.json +0 -3
  102. umap/static/umap/locale/no.js +2 -5
  103. umap/static/umap/locale/no.json +2 -5
  104. umap/static/umap/locale/pl.js +2 -5
  105. umap/static/umap/locale/pl.json +2 -5
  106. umap/static/umap/locale/pl_PL.json +2 -5
  107. umap/static/umap/locale/pt.js +0 -3
  108. umap/static/umap/locale/pt.json +0 -3
  109. umap/static/umap/locale/pt_BR.js +2 -5
  110. umap/static/umap/locale/pt_BR.json +2 -5
  111. umap/static/umap/locale/pt_PT.js +2 -5
  112. umap/static/umap/locale/pt_PT.json +2 -5
  113. umap/static/umap/locale/ro.js +2 -5
  114. umap/static/umap/locale/ro.json +2 -5
  115. umap/static/umap/locale/ru.js +2 -5
  116. umap/static/umap/locale/ru.json +2 -5
  117. umap/static/umap/locale/sk_SK.js +2 -5
  118. umap/static/umap/locale/sk_SK.json +2 -5
  119. umap/static/umap/locale/sl.js +2 -5
  120. umap/static/umap/locale/sl.json +2 -5
  121. umap/static/umap/locale/sr.js +2 -5
  122. umap/static/umap/locale/sr.json +2 -5
  123. umap/static/umap/locale/sv.js +2 -5
  124. umap/static/umap/locale/sv.json +2 -5
  125. umap/static/umap/locale/th_TH.js +2 -5
  126. umap/static/umap/locale/th_TH.json +2 -5
  127. umap/static/umap/locale/tr.js +2 -5
  128. umap/static/umap/locale/tr.json +2 -5
  129. umap/static/umap/locale/uk_UA.js +2 -5
  130. umap/static/umap/locale/uk_UA.json +2 -5
  131. umap/static/umap/locale/vi.js +2 -5
  132. umap/static/umap/locale/vi.json +2 -5
  133. umap/static/umap/locale/vi_VN.json +2 -5
  134. umap/static/umap/locale/zh.js +2 -5
  135. umap/static/umap/locale/zh.json +2 -5
  136. umap/static/umap/locale/zh_CN.json +2 -5
  137. umap/static/umap/locale/zh_TW.Big5.json +2 -5
  138. umap/static/umap/locale/zh_TW.js +1 -4
  139. umap/static/umap/locale/zh_TW.json +1 -4
  140. umap/static/umap/map.css +1 -17
  141. umap/static/umap/vendors/locatecontrol/L.Control.Locate.esm.js +942 -0
  142. umap/static/umap/vendors/photon/leaflet.photon.esm.js +472 -0
  143. umap/sync/app.py +4 -1
  144. umap/templates/umap/css.html +0 -2
  145. umap/templates/umap/js.html +0 -5
  146. umap/templates/umap/team_form.html +2 -1
  147. umap/tests/integration/test_edit_map.py +2 -0
  148. umap/tests/integration/test_filters.py +24 -0
  149. umap/tests/integration/test_import.py +26 -23
  150. umap/tests/integration/test_map.py +1 -1
  151. umap/tests/integration/test_optimistic_merge.py +7 -1
  152. umap/tests/integration/test_remote_data.py +1 -1
  153. umap/tests/test_search_maps_command.py +44 -0
  154. umap/utils.py +9 -3
  155. umap/views.py +17 -4
  156. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/METADATA +24 -18
  157. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/RECORD +160 -162
  158. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/WHEEL +1 -1
  159. umap/static/umap/vendors/hash/leaflet-hash.js +0 -162
  160. umap/static/umap/vendors/loading/Control.Loading.css +0 -26
  161. umap/static/umap/vendors/loading/Control.Loading.js +0 -351
  162. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css +0 -1
  163. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css.map +0 -1
  164. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js +0 -4
  165. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js.map +0 -1
  166. umap/static/umap/vendors/photon/leaflet.photon.js +0 -487
  167. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/entry_points.txt +0 -0
  168. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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(300) # Time for the panel animation to finish
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())
@@ -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\.16267/8\.52967"))
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
- def test_created_markers_are_merged(new_page, live_server, tilelayer):
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
- dict(zip(names, [get_uri_template(url, module=module) for url in names]))
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
- url_template = properties.get("tilelayer", {}).get("url_template")
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
- self.request.FILES["geojson"].file = BytesIO(
1339
- json_dumps(merged).encode("utf-8")
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.4.2
3
+ Version: 3.6.0
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.7.0
22
- Requires-Dist: django==5.2.8
23
- Requires-Dist: pillow==12.0.0
24
- Requires-Dist: psycopg==3.2.13
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.6.0
29
- Requires-Dist: social-auth-core==4.8.1
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.0; extra == 'dev'
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.16.1; extra == 'dev'
38
- Requires-Dist: ruff==0.14.5; extra == 'dev'
39
- Requires-Dist: vermin==1.7.0; extra == 'dev'
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.3; extra == 'sync'
46
+ Requires-Dist: pydantic==2.12.5; extra == 'sync'
46
47
  Requires-Dist: redis==7.1.0; extra == 'sync'
47
- Requires-Dist: websockets==15.0.1; extra == 'sync'
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.14; extra == 'test'
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.1; extra == 'test'
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==8.4.2; extra == 'test'
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
  [![Matrix](https://img.shields.io/matrix/umap:matrix.org?server_fqdn=matrix.org&logo=matrix)](https://matrix.to/#/#umap:matrix.org)