umap-project 3.1.2__py3-none-any.whl → 3.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/locale/en/LC_MESSAGES/django.mo +0 -0
- umap/locale/en/LC_MESSAGES/django.po +22 -18
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +21 -17
- umap/management/commands/export_pictogram.py +29 -0
- umap/management/commands/migrate_to_S3.py +5 -1
- umap/management/commands/purge_old_versions.py +8 -6
- umap/settings/__init__.py +21 -0
- umap/settings/base.py +3 -0
- umap/static/umap/content.css +7 -2
- umap/static/umap/css/contextmenu.css +58 -2
- umap/static/umap/css/form.css +175 -45
- umap/static/umap/css/icon.css +97 -3
- umap/static/umap/css/panel.css +31 -1
- umap/static/umap/img/16-white.svg +21 -40
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/24-white.svg +9 -9
- umap/static/umap/img/24.svg +23 -10
- umap/static/umap/img/source/16-white.svg +23 -41
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/img/source/24-white.svg +11 -11
- umap/static/umap/img/source/24.svg +25 -12
- umap/static/umap/js/modules/browser.js +1 -1
- umap/static/umap/js/modules/caption.js +8 -0
- umap/static/umap/js/modules/data/features.js +331 -202
- umap/static/umap/js/modules/data/layer.js +263 -152
- umap/static/umap/js/modules/facets.js +2 -2
- umap/static/umap/js/modules/form/builder.js +11 -7
- umap/static/umap/js/modules/form/fields.js +66 -26
- umap/static/umap/js/modules/formatter.js +78 -28
- umap/static/umap/js/modules/importer.js +6 -1
- umap/static/umap/js/modules/importers/opendata.js +138 -33
- umap/static/umap/js/modules/importers/openrouteservice.js +140 -0
- umap/static/umap/js/modules/managers.js +67 -0
- umap/static/umap/js/modules/printer.js +107 -0
- umap/static/umap/js/modules/rendering/controls.js +78 -2
- umap/static/umap/js/modules/rendering/icon.js +116 -87
- umap/static/umap/js/modules/rendering/layers/classified.js +8 -7
- umap/static/umap/js/modules/rendering/layers/cluster.js +199 -63
- umap/static/umap/js/modules/rendering/map.js +6 -2
- umap/static/umap/js/modules/rendering/template.js +71 -1
- umap/static/umap/js/modules/rendering/ui.js +111 -34
- umap/static/umap/js/modules/rules.js +76 -23
- umap/static/umap/js/modules/schema.js +27 -0
- umap/static/umap/js/modules/share.js +19 -12
- umap/static/umap/js/modules/slideshow.js +1 -1
- umap/static/umap/js/modules/sync/updaters.js +1 -6
- umap/static/umap/js/modules/tableeditor.js +13 -37
- umap/static/umap/js/modules/templates.js +7 -6
- umap/static/umap/js/modules/ui/bar.js +6 -1
- umap/static/umap/js/modules/ui/base.js +24 -9
- umap/static/umap/js/modules/ui/contextmenu.js +17 -7
- umap/static/umap/js/modules/ui/dialog.js +7 -4
- umap/static/umap/js/modules/ui/panel.js +7 -0
- umap/static/umap/js/modules/umap.js +84 -67
- umap/static/umap/js/modules/utils.js +8 -7
- umap/static/umap/js/umap.controls.js +22 -57
- umap/static/umap/locale/am_ET.js +81 -9
- umap/static/umap/locale/am_ET.json +81 -9
- umap/static/umap/locale/ar.js +81 -9
- umap/static/umap/locale/ar.json +81 -9
- umap/static/umap/locale/ast.js +81 -9
- umap/static/umap/locale/ast.json +81 -9
- umap/static/umap/locale/bg.js +81 -9
- umap/static/umap/locale/bg.json +81 -9
- umap/static/umap/locale/br.js +68 -29
- umap/static/umap/locale/br.json +68 -29
- umap/static/umap/locale/ca.js +88 -16
- umap/static/umap/locale/ca.json +88 -16
- umap/static/umap/locale/cs_CZ.js +81 -9
- umap/static/umap/locale/cs_CZ.json +81 -9
- umap/static/umap/locale/da.js +48 -9
- umap/static/umap/locale/da.json +48 -9
- umap/static/umap/locale/de.js +48 -9
- umap/static/umap/locale/de.json +48 -9
- umap/static/umap/locale/el.js +58 -13
- umap/static/umap/locale/el.json +58 -13
- umap/static/umap/locale/en.js +48 -9
- umap/static/umap/locale/en.json +48 -9
- umap/static/umap/locale/en_US.json +81 -9
- umap/static/umap/locale/es.js +48 -9
- umap/static/umap/locale/es.json +48 -9
- umap/static/umap/locale/et.js +81 -9
- umap/static/umap/locale/et.json +81 -9
- umap/static/umap/locale/eu.js +97 -25
- umap/static/umap/locale/eu.json +97 -25
- umap/static/umap/locale/fa_IR.js +81 -9
- umap/static/umap/locale/fa_IR.json +81 -9
- umap/static/umap/locale/fi.js +81 -9
- umap/static/umap/locale/fi.json +81 -9
- umap/static/umap/locale/fr.js +48 -9
- umap/static/umap/locale/fr.json +48 -9
- umap/static/umap/locale/gl.js +81 -9
- umap/static/umap/locale/gl.json +81 -9
- umap/static/umap/locale/he.js +81 -9
- umap/static/umap/locale/he.json +81 -9
- umap/static/umap/locale/hr.js +81 -9
- umap/static/umap/locale/hr.json +81 -9
- umap/static/umap/locale/hu.js +72 -27
- umap/static/umap/locale/hu.json +72 -27
- umap/static/umap/locale/id.js +81 -9
- umap/static/umap/locale/id.json +81 -9
- umap/static/umap/locale/is.js +81 -9
- umap/static/umap/locale/is.json +81 -9
- umap/static/umap/locale/it.js +48 -9
- umap/static/umap/locale/it.json +48 -9
- umap/static/umap/locale/ja.js +81 -9
- umap/static/umap/locale/ja.json +81 -9
- umap/static/umap/locale/ko.js +81 -9
- umap/static/umap/locale/ko.json +81 -9
- umap/static/umap/locale/lt.js +81 -9
- umap/static/umap/locale/lt.json +81 -9
- umap/static/umap/locale/ms.js +81 -9
- umap/static/umap/locale/ms.json +81 -9
- umap/static/umap/locale/nl.js +48 -9
- umap/static/umap/locale/nl.json +48 -9
- umap/static/umap/locale/no.js +81 -9
- umap/static/umap/locale/no.json +81 -9
- umap/static/umap/locale/pl.js +81 -9
- umap/static/umap/locale/pl.json +81 -9
- umap/static/umap/locale/pl_PL.json +81 -9
- umap/static/umap/locale/pt.js +81 -9
- umap/static/umap/locale/pt.json +81 -9
- umap/static/umap/locale/pt_BR.js +91 -19
- umap/static/umap/locale/pt_BR.json +91 -19
- umap/static/umap/locale/pt_PT.js +81 -9
- umap/static/umap/locale/pt_PT.json +81 -9
- umap/static/umap/locale/ro.js +81 -9
- umap/static/umap/locale/ro.json +81 -9
- umap/static/umap/locale/ru.js +81 -9
- umap/static/umap/locale/ru.json +81 -9
- umap/static/umap/locale/sk_SK.js +81 -9
- umap/static/umap/locale/sk_SK.json +81 -9
- umap/static/umap/locale/sl.js +81 -9
- umap/static/umap/locale/sl.json +81 -9
- umap/static/umap/locale/sr.js +81 -9
- umap/static/umap/locale/sr.json +81 -9
- umap/static/umap/locale/sv.js +81 -9
- umap/static/umap/locale/sv.json +81 -9
- umap/static/umap/locale/th_TH.js +81 -9
- umap/static/umap/locale/th_TH.json +81 -9
- umap/static/umap/locale/tr.js +81 -9
- umap/static/umap/locale/tr.json +81 -9
- umap/static/umap/locale/uk_UA.js +81 -9
- umap/static/umap/locale/uk_UA.json +81 -9
- umap/static/umap/locale/vi.js +81 -9
- umap/static/umap/locale/vi.json +81 -9
- umap/static/umap/locale/vi_VN.json +81 -9
- umap/static/umap/locale/zh.js +81 -9
- umap/static/umap/locale/zh.json +81 -9
- umap/static/umap/locale/zh_CN.json +81 -9
- umap/static/umap/locale/zh_TW.Big5.json +81 -9
- umap/static/umap/locale/zh_TW.js +98 -26
- umap/static/umap/locale/zh_TW.json +98 -26
- umap/static/umap/map.css +325 -102
- umap/static/umap/vars.css +1 -0
- umap/static/umap/vendors/betterknown/betterknown.mjs +287 -0
- umap/static/umap/vendors/editable/Leaflet.Editable.js +3 -1
- umap/static/umap/vendors/openrouteservice/ors-js-client.js +521 -0
- umap/static/umap/vendors/openrouteservice/ors-js-client.js.map +1 -0
- umap/static/umap/vendors/simple-elevation-chart/elevation.js +63 -0
- umap/static/umap/vendors/simple-elevation-chart/elevation.svg +8 -0
- umap/static/umap/vendors/snapdom/snapdom.min.mjs +3 -0
- umap/storage/fs.py +3 -2
- umap/storage/staticfiles.py +12 -0
- umap/templates/base.html +4 -1
- umap/templates/umap/css.html +0 -4
- umap/templates/umap/js.html +1 -3
- umap/tests/base.py +9 -1
- umap/tests/integration/test_basics.py +3 -1
- umap/tests/integration/test_conditional_rules.py +79 -37
- umap/tests/integration/test_datalayer.py +1 -1
- umap/tests/integration/test_draw_polygon.py +3 -5
- umap/tests/integration/test_draw_polyline.py +4 -6
- umap/tests/integration/test_draw_route.py +178 -0
- umap/tests/integration/test_edit_datalayer.py +1 -1
- umap/tests/integration/test_edit_map.py +1 -1
- umap/tests/integration/test_edit_marker.py +8 -8
- umap/tests/integration/test_edit_polygon.py +2 -2
- umap/tests/integration/test_export_map.py +84 -10
- umap/tests/integration/test_import.py +140 -0
- umap/tests/integration/test_map_preview.py +1 -1
- umap/tests/integration/test_optimistic_merge.py +72 -12
- umap/tests/integration/test_share.py +1 -1
- umap/tests/integration/test_tableeditor.py +10 -7
- umap/tests/integration/test_websocket_sync.py +4 -4
- umap/utils.py +37 -0
- umap/views.py +18 -2
- umap_project-3.3.0.dist-info/METADATA +76 -0
- {umap_project-3.1.2.dist-info → umap_project-3.3.0.dist-info}/RECORD +194 -188
- umap/static/umap/vendors/markercluster/MarkerCluster.Default.css +0 -60
- umap/static/umap/vendors/markercluster/MarkerCluster.css +0 -14
- umap/static/umap/vendors/markercluster/leaflet.markercluster.js +0 -2
- umap/static/umap/vendors/markercluster/leaflet.markercluster.js.map +0 -1
- umap_project-3.1.2.dist-info/METADATA +0 -68
- {umap_project-3.1.2.dist-info → umap_project-3.3.0.dist-info}/WHEEL +0 -0
- {umap_project-3.1.2.dist-info → umap_project-3.3.0.dist-info}/entry_points.txt +0 -0
- {umap_project-3.1.2.dist-info → umap_project-3.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -12,13 +12,13 @@ from ..base import DataLayerFactory, MapFactory
|
|
|
12
12
|
DATALAYER_UPDATE = re.compile(r".*/datalayer/update/.*")
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def test_created_markers_are_merged(
|
|
15
|
+
def test_created_markers_are_merged(new_page, live_server, tilelayer):
|
|
16
16
|
# Let's create a new map with an empty datalayer
|
|
17
17
|
map = MapFactory(name="server-side merge")
|
|
18
18
|
datalayer = DataLayerFactory(map=map, edit_status=DataLayer.ANONYMOUS, data={})
|
|
19
19
|
|
|
20
20
|
# Now navigate to this map and create marker
|
|
21
|
-
page_one =
|
|
21
|
+
page_one = new_page("page 1")
|
|
22
22
|
page_one.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
23
23
|
|
|
24
24
|
save_p1 = page_one.get_by_role("button", name="Save")
|
|
@@ -52,10 +52,20 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
52
52
|
"id": str(datalayer.pk),
|
|
53
53
|
"rank": 0,
|
|
54
54
|
"remoteData": {},
|
|
55
|
+
"fields": [
|
|
56
|
+
{
|
|
57
|
+
"key": "name",
|
|
58
|
+
"type": "String",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"key": "description",
|
|
62
|
+
"type": "Text",
|
|
63
|
+
},
|
|
64
|
+
],
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
# Now navigate to this map from another tab
|
|
58
|
-
page_two =
|
|
68
|
+
page_two = new_page("page 2")
|
|
59
69
|
|
|
60
70
|
page_two.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
61
71
|
|
|
@@ -91,6 +101,16 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
91
101
|
"id": str(datalayer.pk),
|
|
92
102
|
"rank": 0,
|
|
93
103
|
"remoteData": {},
|
|
104
|
+
"fields": [
|
|
105
|
+
{
|
|
106
|
+
"key": "name",
|
|
107
|
+
"type": "String",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"key": "description",
|
|
111
|
+
"type": "Text",
|
|
112
|
+
},
|
|
113
|
+
],
|
|
94
114
|
}
|
|
95
115
|
|
|
96
116
|
# Now create another marker in the first tab
|
|
@@ -111,6 +131,16 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
111
131
|
"id": str(datalayer.pk),
|
|
112
132
|
"rank": 0,
|
|
113
133
|
"remoteData": {},
|
|
134
|
+
"fields": [
|
|
135
|
+
{
|
|
136
|
+
"key": "name",
|
|
137
|
+
"type": "String",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"key": "description",
|
|
141
|
+
"type": "Text",
|
|
142
|
+
},
|
|
143
|
+
],
|
|
114
144
|
}
|
|
115
145
|
|
|
116
146
|
# And again
|
|
@@ -131,6 +161,16 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
131
161
|
"id": str(datalayer.pk),
|
|
132
162
|
"rank": 0,
|
|
133
163
|
"remoteData": {},
|
|
164
|
+
"fields": [
|
|
165
|
+
{
|
|
166
|
+
"key": "name",
|
|
167
|
+
"type": "String",
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"key": "description",
|
|
171
|
+
"type": "Text",
|
|
172
|
+
},
|
|
173
|
+
],
|
|
134
174
|
}
|
|
135
175
|
expect(marker_pane_p1).to_have_count(4)
|
|
136
176
|
|
|
@@ -153,20 +193,30 @@ def test_created_markers_are_merged(context, live_server, tilelayer):
|
|
|
153
193
|
"id": str(datalayer.pk),
|
|
154
194
|
"rank": 0,
|
|
155
195
|
"remoteData": {},
|
|
196
|
+
"fields": [
|
|
197
|
+
{
|
|
198
|
+
"key": "name",
|
|
199
|
+
"type": "String",
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"key": "description",
|
|
203
|
+
"type": "Text",
|
|
204
|
+
},
|
|
205
|
+
],
|
|
156
206
|
}
|
|
157
207
|
expect(marker_pane_p2).to_have_count(5)
|
|
158
208
|
|
|
159
209
|
|
|
160
|
-
def test_empty_datalayers_can_be_merged(
|
|
210
|
+
def test_empty_datalayers_can_be_merged(new_page, live_server, tilelayer):
|
|
161
211
|
# Let's create a new map with an empty datalayer
|
|
162
212
|
map = MapFactory(name="server-side merge")
|
|
163
213
|
DataLayerFactory(map=map, edit_status=DataLayer.ANONYMOUS, data={})
|
|
164
214
|
|
|
165
215
|
# Open two tabs at the same time, on the same empty map
|
|
166
|
-
page_one =
|
|
216
|
+
page_one = new_page("page 1")
|
|
167
217
|
page_one.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
168
218
|
|
|
169
|
-
page_two =
|
|
219
|
+
page_two = new_page("page 2")
|
|
170
220
|
page_two.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
171
221
|
|
|
172
222
|
save_p1 = page_one.get_by_role("button", name="Save")
|
|
@@ -213,15 +263,15 @@ def test_empty_datalayers_can_be_merged(context, live_server, tilelayer):
|
|
|
213
263
|
expect(marker_pane_p2).to_have_count(2)
|
|
214
264
|
|
|
215
265
|
|
|
216
|
-
def test_same_second_edit_doesnt_conflict(
|
|
266
|
+
def test_same_second_edit_doesnt_conflict(new_page, live_server, tilelayer):
|
|
217
267
|
# Let's create a new map with an empty datalayer
|
|
218
268
|
map = MapFactory(name="server-side merge")
|
|
219
269
|
datalayer = DataLayerFactory(map=map, edit_status=DataLayer.ANONYMOUS, data={})
|
|
220
270
|
|
|
221
271
|
# Open the created map on two pages.
|
|
222
|
-
page_one =
|
|
272
|
+
page_one = new_page("page 1")
|
|
223
273
|
page_one.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
224
|
-
page_two =
|
|
274
|
+
page_two = new_page("page 2")
|
|
225
275
|
page_two.goto(f"{live_server.url}{map.get_absolute_url()}?edit")
|
|
226
276
|
|
|
227
277
|
save_p1 = page_one.get_by_role("button", name="Save")
|
|
@@ -280,14 +330,24 @@ def test_same_second_edit_doesnt_conflict(context, live_server, tilelayer):
|
|
|
280
330
|
"id": str(datalayer.pk),
|
|
281
331
|
"rank": 0,
|
|
282
332
|
"remoteData": {},
|
|
333
|
+
"fields": [
|
|
334
|
+
{
|
|
335
|
+
"key": "name",
|
|
336
|
+
"type": "String",
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"key": "description",
|
|
340
|
+
"type": "Text",
|
|
341
|
+
},
|
|
342
|
+
],
|
|
283
343
|
}
|
|
284
344
|
|
|
285
345
|
|
|
286
|
-
def test_should_display_alert_on_conflict(
|
|
346
|
+
def test_should_display_alert_on_conflict(new_page, live_server, datalayer, openmap):
|
|
287
347
|
# Open the map on two pages.
|
|
288
|
-
page_one =
|
|
348
|
+
page_one = new_page("page 1")
|
|
289
349
|
page_one.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
|
|
290
|
-
page_two =
|
|
350
|
+
page_two = new_page("page 2")
|
|
291
351
|
page_two.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
|
|
292
352
|
|
|
293
353
|
# Change name on page one and save
|
|
@@ -27,7 +27,7 @@ def test_iframe_code_can_contain_datalayers(map, live_server, datalayer, page):
|
|
|
27
27
|
|
|
28
28
|
def test_iframe_code_can_contain_feature(map, live_server, datalayer, page):
|
|
29
29
|
page.goto(f"{live_server.url}{map.get_absolute_url()}?share")
|
|
30
|
-
page.locator(".
|
|
30
|
+
page.locator(".icon-container").click()
|
|
31
31
|
textarea = page.locator(".umap-share-iframe")
|
|
32
32
|
expect(textarea).to_be_visible()
|
|
33
33
|
expect(textarea).not_to_have_text(re.compile("feature=Here"))
|
|
@@ -69,7 +69,9 @@ def test_table_editor(live_server, openmap, datalayer, page):
|
|
|
69
69
|
page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
|
|
70
70
|
page.get_by_role("button", name="Manage layers").click()
|
|
71
71
|
page.locator(".panel").get_by_title("Edit properties in a table").click()
|
|
72
|
-
page.
|
|
72
|
+
page.locator("td[data-property=description]").dblclick()
|
|
73
|
+
page.locator('textarea[name="description"]').fill("nice new description")
|
|
74
|
+
page.get_by_text("Add a new field").click()
|
|
73
75
|
page.locator("dialog").locator("input").fill("newprop")
|
|
74
76
|
page.locator("dialog").get_by_role("button", name="OK").click()
|
|
75
77
|
page.locator("td").nth(2).dblclick()
|
|
@@ -83,6 +85,7 @@ def test_table_editor(live_server, openmap, datalayer, page):
|
|
|
83
85
|
page.get_by_role("button", name="Save").click()
|
|
84
86
|
saved = DataLayer.objects.last()
|
|
85
87
|
data = json.loads(Path(saved.geojson.path).read_text())
|
|
88
|
+
assert data["features"][0]["properties"]["description"] == "nice new description"
|
|
86
89
|
assert data["features"][0]["properties"]["newprop"] == "newvalue"
|
|
87
90
|
assert "name" not in data["features"][0]["properties"]
|
|
88
91
|
|
|
@@ -91,7 +94,7 @@ def test_cannot_add_existing_property_name(live_server, openmap, datalayer, page
|
|
|
91
94
|
page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
|
|
92
95
|
page.get_by_role("button", name="Manage layers").click()
|
|
93
96
|
page.locator(".panel").get_by_title("Edit properties in a table").click()
|
|
94
|
-
page.get_by_text("Add a new
|
|
97
|
+
page.get_by_text("Add a new field").click()
|
|
95
98
|
page.locator("dialog").locator("input").fill("name")
|
|
96
99
|
page.get_by_role("button", name="OK").click()
|
|
97
100
|
expect(page.get_by_role("dialog")).to_contain_text(
|
|
@@ -104,7 +107,7 @@ def test_cannot_add_property_with_a_dot(live_server, openmap, datalayer, page):
|
|
|
104
107
|
page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
|
|
105
108
|
page.get_by_role("button", name="Manage layers").click()
|
|
106
109
|
page.locator(".panel").get_by_title("Edit properties in a table").click()
|
|
107
|
-
page.get_by_text("Add a new
|
|
110
|
+
page.get_by_text("Add a new field").click()
|
|
108
111
|
page.locator("dialog").locator("input").fill("foo.bar")
|
|
109
112
|
page.get_by_role("button", name="OK").click()
|
|
110
113
|
expect(page.get_by_role("dialog")).to_contain_text(
|
|
@@ -127,13 +130,13 @@ def test_rename_property(live_server, openmap, page):
|
|
|
127
130
|
expect(page.locator("table th button[data-property=mytype]")).to_have_count(0)
|
|
128
131
|
|
|
129
132
|
page.locator(".panel.full").get_by_role("button", name="Close").click()
|
|
130
|
-
page.locator(".leaflet-marker-icon").first.click()
|
|
133
|
+
page.locator(".leaflet-marker-icon").first.click(button="right")
|
|
131
134
|
page.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
132
135
|
expect(page.locator(".panel.right .umap-field-mynewtype")).to_be_visible()
|
|
133
136
|
expect(page.locator(".panel.right .umap-field-mytype")).to_be_hidden()
|
|
134
137
|
page.locator(".edit-undo").click()
|
|
135
138
|
page.locator(".panel.right").get_by_role("button", name="Close").click()
|
|
136
|
-
page.locator(".leaflet-marker-icon").first.click()
|
|
139
|
+
page.locator(".leaflet-marker-icon").first.click(button="right")
|
|
137
140
|
page.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
138
141
|
expect(page.locator(".panel.right .umap-field-mynewtype")).to_be_hidden()
|
|
139
142
|
expect(page.locator(".panel.right .umap-field-mytype")).to_be_visible()
|
|
@@ -151,12 +154,12 @@ def test_delete_property(live_server, openmap, page):
|
|
|
151
154
|
expect(page.locator("table th button[data-property=mytype]")).to_have_count(0)
|
|
152
155
|
|
|
153
156
|
page.locator(".panel.full").get_by_role("button", name="Close").click()
|
|
154
|
-
page.locator(".leaflet-marker-icon").first.click()
|
|
157
|
+
page.locator(".leaflet-marker-icon").first.click(button="right")
|
|
155
158
|
page.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
156
159
|
expect(page.locator(".panel.right .umap-field-mytype")).to_be_hidden()
|
|
157
160
|
page.locator(".edit-undo").click()
|
|
158
161
|
page.locator(".panel.right").get_by_role("button", name="Close").click()
|
|
159
|
-
page.locator(".leaflet-marker-icon").first.click()
|
|
162
|
+
page.locator(".leaflet-marker-icon").first.click(button="right")
|
|
160
163
|
page.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
161
164
|
expect(page.locator(".panel.right .umap-field-mytype")).to_be_visible()
|
|
162
165
|
|
|
@@ -58,7 +58,7 @@ def test_websocket_connection_can_sync_markers(new_page, asgi_live_server, tilel
|
|
|
58
58
|
peerA.locator("body").press("Escape")
|
|
59
59
|
peerA.wait_for_timeout(300)
|
|
60
60
|
|
|
61
|
-
peerB.locator(".leaflet-marker-icon").first.click()
|
|
61
|
+
peerB.locator(".leaflet-marker-icon").first.click(button="right")
|
|
62
62
|
peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
63
63
|
expect(peerB.locator('input[name="name"]')).to_have_value("Synced name")
|
|
64
64
|
|
|
@@ -137,7 +137,7 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
|
|
|
137
137
|
a_polygon_bbox_t1 = a_polygon.bounding_box()
|
|
138
138
|
assert b_polygon_bbox_t1 == a_polygon_bbox_t1
|
|
139
139
|
|
|
140
|
-
b_polygon.click()
|
|
140
|
+
b_polygon.click(button="right")
|
|
141
141
|
peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
142
142
|
|
|
143
143
|
edited_vertex = peerB.locator("div:nth-child(6)").first
|
|
@@ -151,7 +151,7 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
|
|
|
151
151
|
assert b_polygon_bbox_t2 == a_polygon_bbox_t2
|
|
152
152
|
|
|
153
153
|
# Move the polygon on peer B and check it moved also on peer A
|
|
154
|
-
b_polygon.click()
|
|
154
|
+
b_polygon.click(button="right")
|
|
155
155
|
peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
156
156
|
|
|
157
157
|
b_polygon.drag_to(b_map_el, target_position={"x": 400, "y": 400})
|
|
@@ -340,7 +340,7 @@ def test_websocket_connection_can_sync_late_joining_peer(
|
|
|
340
340
|
expect(b_polygons).to_have_count(1)
|
|
341
341
|
|
|
342
342
|
# Verify marker properties
|
|
343
|
-
peerB.locator(".leaflet-marker-icon").first.click()
|
|
343
|
+
peerB.locator(".leaflet-marker-icon").first.click(button="right")
|
|
344
344
|
peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
|
|
345
345
|
expect(peerB.locator('input[name="name"]')).to_have_value("First marker")
|
|
346
346
|
|
umap/utils.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import gzip
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
|
+
from pathlib import Path
|
|
4
5
|
|
|
5
6
|
from django.conf import settings
|
|
7
|
+
from django.contrib.staticfiles import finders
|
|
6
8
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
7
9
|
from django.urls import URLPattern, URLResolver, get_resolver
|
|
8
10
|
|
|
@@ -185,3 +187,38 @@ def merge_features(reference: list, latest: list, incoming: list):
|
|
|
185
187
|
def json_dumps(obj, **kwargs):
|
|
186
188
|
"""Utility using the Django JSON Encoder when dumping objects"""
|
|
187
189
|
return json.dumps(obj, cls=DjangoJSONEncoder, **kwargs)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def collect_pictograms():
|
|
193
|
+
pictograms = {}
|
|
194
|
+
|
|
195
|
+
for name, definition in settings.UMAP_PICTOGRAMS_COLLECTIONS.items():
|
|
196
|
+
root = Path(definition["path"])
|
|
197
|
+
subfolder = "pictograms"
|
|
198
|
+
if not root.is_absolute():
|
|
199
|
+
found_path = finders.find(root)
|
|
200
|
+
if not found_path:
|
|
201
|
+
print(f"Cannot find {root} in STATIFILES_DIRS")
|
|
202
|
+
continue
|
|
203
|
+
root = Path(found_path.removesuffix(definition["path"].rstrip("/")))
|
|
204
|
+
subfolder = definition["path"]
|
|
205
|
+
categories = {}
|
|
206
|
+
for path in (root / subfolder).iterdir():
|
|
207
|
+
if path.is_dir():
|
|
208
|
+
categories[path.name] = []
|
|
209
|
+
for subpath in path.iterdir():
|
|
210
|
+
if subpath.is_dir() or subpath.name.startswith("."):
|
|
211
|
+
continue
|
|
212
|
+
src = subpath.relative_to(root)
|
|
213
|
+
categories[path.name].append(
|
|
214
|
+
{
|
|
215
|
+
"name": subpath.stem,
|
|
216
|
+
"src": f"{settings.STATIC_URL}{src}",
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
pictograms[name] = {
|
|
220
|
+
"attribution": definition.get("attribution"),
|
|
221
|
+
"categories": categories,
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return pictograms
|
umap/views.py
CHANGED
|
@@ -71,6 +71,7 @@ from .models import DataLayer, Licence, Map, Pictogram, Star, Team, TileLayer
|
|
|
71
71
|
from .utils import (
|
|
72
72
|
ConflictError,
|
|
73
73
|
_urls_for_js,
|
|
74
|
+
collect_pictograms,
|
|
74
75
|
gzip_file,
|
|
75
76
|
is_ajax,
|
|
76
77
|
json_dumps,
|
|
@@ -635,6 +636,8 @@ class MapDetailMixin(SessionMixin):
|
|
|
635
636
|
"defaultLabelKeys": settings.UMAP_LABEL_KEYS,
|
|
636
637
|
"help_links": settings.UMAP_HELP_LINKS,
|
|
637
638
|
}
|
|
639
|
+
if settings.OPENROUTESERVICE_APIKEY:
|
|
640
|
+
properties["ORSAPIKey"] = settings.OPENROUTESERVICE_APIKEY
|
|
638
641
|
created = bool(getattr(self, "object", None))
|
|
639
642
|
if created:
|
|
640
643
|
properties.update(
|
|
@@ -1389,8 +1392,21 @@ class PictogramJSONList(ListView):
|
|
|
1389
1392
|
model = Pictogram
|
|
1390
1393
|
|
|
1391
1394
|
def render_to_response(self, context, **response_kwargs):
|
|
1392
|
-
|
|
1393
|
-
|
|
1395
|
+
if settings.UMAP_PICTOGRAMS_COLLECTIONS:
|
|
1396
|
+
content = collect_pictograms()
|
|
1397
|
+
else:
|
|
1398
|
+
categories = {}
|
|
1399
|
+
for picto in Pictogram.objects.all():
|
|
1400
|
+
category = picto.category or _("Generic")
|
|
1401
|
+
categories.setdefault(category, [])
|
|
1402
|
+
categories[category].append(picto.json)
|
|
1403
|
+
content = {
|
|
1404
|
+
settings.SITE_NAME: {
|
|
1405
|
+
"attribution": settings.SITE_NAME,
|
|
1406
|
+
"categories": categories,
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
return simple_json_response(data=content)
|
|
1394
1410
|
|
|
1395
1411
|
|
|
1396
1412
|
# ############## #
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: umap-project
|
|
3
|
+
Version: 3.3.0
|
|
4
|
+
Summary: Create maps with OpenStreetMap layers in a minute and embed them in your site.
|
|
5
|
+
Author-email: Yohan Boniface <yb@enix.org>
|
|
6
|
+
Maintainer-email: David Larlet <david@larlet.fr>
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: django,geodjango,leaflet,map,openstreetmap
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: django-agnocomplete==2.2.0
|
|
20
|
+
Requires-Dist: django-environ==0.12.0
|
|
21
|
+
Requires-Dist: django-probes==1.7.0
|
|
22
|
+
Requires-Dist: django==5.2.5
|
|
23
|
+
Requires-Dist: pillow==11.3.0
|
|
24
|
+
Requires-Dist: psycopg==3.2.9
|
|
25
|
+
Requires-Dist: rcssmin==1.2.1
|
|
26
|
+
Requires-Dist: requests==2.32.4
|
|
27
|
+
Requires-Dist: rjsmin==1.2.4
|
|
28
|
+
Requires-Dist: social-auth-app-django==5.4.3
|
|
29
|
+
Requires-Dist: social-auth-core==4.5.6
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: djlint==1.36.4; extra == 'dev'
|
|
32
|
+
Requires-Dist: hatch==1.14.1; extra == 'dev'
|
|
33
|
+
Requires-Dist: isort==6.0.1; extra == 'dev'
|
|
34
|
+
Requires-Dist: mkdocs-material==9.6.16; extra == 'dev'
|
|
35
|
+
Requires-Dist: mkdocs-static-i18n==1.3.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: mkdocs==1.6.1; extra == 'dev'
|
|
37
|
+
Requires-Dist: pymdown-extensions==10.16.1; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff==0.12.8; extra == 'dev'
|
|
39
|
+
Requires-Dist: vermin==1.6.0; extra == 'dev'
|
|
40
|
+
Provides-Extra: docker
|
|
41
|
+
Requires-Dist: uvicorn==0.35.0; extra == 'docker'
|
|
42
|
+
Provides-Extra: s3
|
|
43
|
+
Requires-Dist: django-storages[s3]==1.14.6; extra == 's3'
|
|
44
|
+
Provides-Extra: sync
|
|
45
|
+
Requires-Dist: pydantic==2.11.7; extra == 'sync'
|
|
46
|
+
Requires-Dist: redis==6.4.0; extra == 'sync'
|
|
47
|
+
Requires-Dist: websockets==15.0.1; extra == 'sync'
|
|
48
|
+
Provides-Extra: test
|
|
49
|
+
Requires-Dist: daphne==4.2.1; extra == 'test'
|
|
50
|
+
Requires-Dist: factory-boy==3.3.3; extra == 'test'
|
|
51
|
+
Requires-Dist: moto[s3]==5.1.9; extra == 'test'
|
|
52
|
+
Requires-Dist: playwright>=1.39; extra == 'test'
|
|
53
|
+
Requires-Dist: pytest-django==4.11.1; extra == 'test'
|
|
54
|
+
Requires-Dist: pytest-playwright==0.7.0; extra == 'test'
|
|
55
|
+
Requires-Dist: pytest-rerunfailures==15.1; extra == 'test'
|
|
56
|
+
Requires-Dist: pytest-xdist<4,>=3.5.0; extra == 'test'
|
|
57
|
+
Requires-Dist: pytest==8.4.1; extra == 'test'
|
|
58
|
+
Description-Content-Type: text/markdown
|
|
59
|
+
|
|
60
|
+
[](https://matrix.to/#/#umap:matrix.org)
|
|
61
|
+
[](https://forum.openstreetmap.fr/c/utiliser/umap/29)
|
|
62
|
+
[](https://lists.openstreetmap.org/listinfo/umap)
|
|
63
|
+
|
|
64
|
+
[](https://liberapay.com/uMap)
|
|
65
|
+
[](https://opencollective.com/uMap)
|
|
66
|
+
[](https://github.com/sponsors/umap-project)
|
|
67
|
+
|
|
68
|
+
# uMap project
|
|
69
|
+
|
|
70
|
+
uMap lets you create maps with OpenStreetMap layers within minutes and embed them in your site.
|
|
71
|
+
*Because we think that the more OSM will be used, the more OSM will be improved.*
|
|
72
|
+
Built on top of Django and Leaflet.
|
|
73
|
+
|
|
74
|
+
- Have a look at [our website](https://umap-project.org) for an introduction
|
|
75
|
+
- See [our docs](https://docs.umap-project.org/) for technical information
|
|
76
|
+
- Come [chat with us on matrix](https://matrix.to/#/#umap:matrix.org), start a thread on [the forum](https://forum.openstreetmap.fr/c/utiliser/umap/29) or join [the mailing list](https://lists.openstreetmap.org/listinfo/umap)
|