umap-project 3.3.5__py3-none-any.whl → 3.4.0b0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of umap-project might be problematic. Click here for more details.

Files changed (218) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  3. umap/locale/cs_CZ/LC_MESSAGES/django.po +43 -33
  4. umap/locale/da/LC_MESSAGES/django.mo +0 -0
  5. umap/locale/da/LC_MESSAGES/django.po +43 -33
  6. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/de/LC_MESSAGES/django.po +35 -29
  8. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  9. umap/locale/el/LC_MESSAGES/django.po +35 -29
  10. umap/locale/en/LC_MESSAGES/django.po +34 -28
  11. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  12. umap/locale/es/LC_MESSAGES/django.po +43 -33
  13. umap/locale/et/LC_MESSAGES/django.mo +0 -0
  14. umap/locale/et/LC_MESSAGES/django.po +58 -54
  15. umap/locale/eu/LC_MESSAGES/django.mo +0 -0
  16. umap/locale/eu/LC_MESSAGES/django.po +43 -33
  17. umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
  18. umap/locale/fa_IR/LC_MESSAGES/django.po +43 -33
  19. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  20. umap/locale/fr/LC_MESSAGES/django.po +36 -30
  21. umap/locale/gl/LC_MESSAGES/django.mo +0 -0
  22. umap/locale/gl/LC_MESSAGES/django.po +43 -33
  23. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  24. umap/locale/hu/LC_MESSAGES/django.po +35 -29
  25. umap/locale/is/LC_MESSAGES/django.mo +0 -0
  26. umap/locale/is/LC_MESSAGES/django.po +43 -33
  27. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  28. umap/locale/it/LC_MESSAGES/django.po +43 -33
  29. umap/locale/nl/LC_MESSAGES/django.mo +0 -0
  30. umap/locale/nl/LC_MESSAGES/django.po +35 -29
  31. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  32. umap/locale/pl/LC_MESSAGES/django.po +43 -33
  33. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  34. umap/locale/pt/LC_MESSAGES/django.po +43 -33
  35. umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
  36. umap/locale/th_TH/LC_MESSAGES/django.po +310 -109
  37. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  38. umap/locale/zh_TW/LC_MESSAGES/django.po +80 -70
  39. umap/management/commands/switch_user.py +2 -2
  40. umap/static/umap/base.css +89 -32
  41. umap/static/umap/content.css +129 -33
  42. umap/static/umap/css/bar.css +82 -20
  43. umap/static/umap/css/browser.css +163 -0
  44. umap/static/umap/css/contextmenu.css +15 -0
  45. umap/static/umap/css/dialog.css +36 -16
  46. umap/static/umap/css/form.css +122 -32
  47. umap/static/umap/css/icon.css +46 -3
  48. umap/static/umap/css/panel.css +7 -3
  49. umap/static/umap/css/popup.css +34 -8
  50. umap/static/umap/css/tooltip.css +8 -4
  51. umap/static/umap/img/16-white.svg +26 -8
  52. umap/static/umap/img/16.svg +1 -1
  53. umap/static/umap/img/source/16-white.svg +36 -18
  54. umap/static/umap/img/source/16.svg +1 -1
  55. umap/static/umap/js/components/alerts/alert.css +69 -31
  56. umap/static/umap/js/components/alerts/alert.js +20 -2
  57. umap/static/umap/js/modules/browser.js +64 -56
  58. umap/static/umap/js/modules/caption.js +10 -7
  59. umap/static/umap/js/modules/data/features.js +82 -59
  60. umap/static/umap/js/modules/data/layer.js +75 -166
  61. umap/static/umap/js/modules/domutils.js +109 -0
  62. umap/static/umap/js/modules/filters.js +807 -0
  63. umap/static/umap/js/modules/form/builder.js +8 -5
  64. umap/static/umap/js/modules/form/fields.js +110 -220
  65. umap/static/umap/js/modules/formatter.js +24 -1
  66. umap/static/umap/js/modules/help.js +3 -2
  67. umap/static/umap/js/modules/importers/opendata.js +5 -0
  68. umap/static/umap/js/modules/importers/openrouteservice.js +6 -1
  69. umap/static/umap/js/modules/managers.js +265 -0
  70. umap/static/umap/js/modules/permissions.js +35 -31
  71. umap/static/umap/js/modules/rendering/controls.js +7 -7
  72. umap/static/umap/js/modules/rendering/icon.js +3 -8
  73. umap/static/umap/js/modules/rendering/layers/base.js +1 -1
  74. umap/static/umap/js/modules/rendering/layers/classified.js +17 -10
  75. umap/static/umap/js/modules/rendering/layers/cluster.js +2 -2
  76. umap/static/umap/js/modules/rendering/template.js +44 -8
  77. umap/static/umap/js/modules/rendering/ui.js +29 -23
  78. umap/static/umap/js/modules/rules.js +4 -3
  79. umap/static/umap/js/modules/schema.js +3 -6
  80. umap/static/umap/js/modules/share.js +4 -3
  81. umap/static/umap/js/modules/tableeditor.js +50 -38
  82. umap/static/umap/js/modules/templates.js +2 -3
  83. umap/static/umap/js/modules/ui/bar.js +42 -18
  84. umap/static/umap/js/modules/ui/dialog.js +33 -31
  85. umap/static/umap/js/modules/ui/panel.js +21 -7
  86. umap/static/umap/js/modules/ui/tooltip.js +6 -5
  87. umap/static/umap/js/modules/umap.js +155 -46
  88. umap/static/umap/js/modules/utils.js +23 -1
  89. umap/static/umap/js/umap.core.js +1 -110
  90. umap/static/umap/locale/am_ET.js +40 -14
  91. umap/static/umap/locale/am_ET.json +40 -14
  92. umap/static/umap/locale/ar.js +40 -14
  93. umap/static/umap/locale/ar.json +40 -14
  94. umap/static/umap/locale/ast.js +40 -14
  95. umap/static/umap/locale/ast.json +40 -14
  96. umap/static/umap/locale/bg.js +40 -14
  97. umap/static/umap/locale/bg.json +40 -14
  98. umap/static/umap/locale/br.js +47 -21
  99. umap/static/umap/locale/br.json +47 -21
  100. umap/static/umap/locale/ca.js +40 -14
  101. umap/static/umap/locale/ca.json +40 -14
  102. umap/static/umap/locale/cs_CZ.js +40 -14
  103. umap/static/umap/locale/cs_CZ.json +40 -14
  104. umap/static/umap/locale/da.js +40 -14
  105. umap/static/umap/locale/da.json +40 -14
  106. umap/static/umap/locale/de.js +39 -13
  107. umap/static/umap/locale/de.json +39 -13
  108. umap/static/umap/locale/el.js +40 -14
  109. umap/static/umap/locale/el.json +40 -14
  110. umap/static/umap/locale/en.js +39 -13
  111. umap/static/umap/locale/en.json +39 -13
  112. umap/static/umap/locale/en_US.json +40 -14
  113. umap/static/umap/locale/es.js +40 -14
  114. umap/static/umap/locale/es.json +40 -14
  115. umap/static/umap/locale/et.js +79 -53
  116. umap/static/umap/locale/et.json +79 -53
  117. umap/static/umap/locale/eu.js +72 -46
  118. umap/static/umap/locale/eu.json +72 -46
  119. umap/static/umap/locale/fa_IR.js +40 -14
  120. umap/static/umap/locale/fa_IR.json +40 -14
  121. umap/static/umap/locale/fi.js +40 -14
  122. umap/static/umap/locale/fi.json +40 -14
  123. umap/static/umap/locale/fr.js +39 -13
  124. umap/static/umap/locale/fr.json +39 -13
  125. umap/static/umap/locale/gl.js +40 -14
  126. umap/static/umap/locale/gl.json +40 -14
  127. umap/static/umap/locale/he.js +40 -14
  128. umap/static/umap/locale/he.json +40 -14
  129. umap/static/umap/locale/hr.js +40 -14
  130. umap/static/umap/locale/hr.json +40 -14
  131. umap/static/umap/locale/hu.js +40 -14
  132. umap/static/umap/locale/hu.json +40 -14
  133. umap/static/umap/locale/id.js +40 -14
  134. umap/static/umap/locale/id.json +40 -14
  135. umap/static/umap/locale/is.js +40 -14
  136. umap/static/umap/locale/is.json +40 -14
  137. umap/static/umap/locale/it.js +40 -14
  138. umap/static/umap/locale/it.json +40 -14
  139. umap/static/umap/locale/ja.js +40 -14
  140. umap/static/umap/locale/ja.json +40 -14
  141. umap/static/umap/locale/ko.js +40 -14
  142. umap/static/umap/locale/ko.json +40 -14
  143. umap/static/umap/locale/lt.js +40 -14
  144. umap/static/umap/locale/lt.json +40 -14
  145. umap/static/umap/locale/ms.js +40 -14
  146. umap/static/umap/locale/ms.json +40 -14
  147. umap/static/umap/locale/nl.js +40 -14
  148. umap/static/umap/locale/nl.json +40 -14
  149. umap/static/umap/locale/no.js +40 -14
  150. umap/static/umap/locale/no.json +40 -14
  151. umap/static/umap/locale/pl.js +40 -14
  152. umap/static/umap/locale/pl.json +40 -14
  153. umap/static/umap/locale/pl_PL.json +40 -14
  154. umap/static/umap/locale/pt.js +40 -14
  155. umap/static/umap/locale/pt.json +40 -14
  156. umap/static/umap/locale/pt_BR.js +40 -14
  157. umap/static/umap/locale/pt_BR.json +40 -14
  158. umap/static/umap/locale/pt_PT.js +40 -14
  159. umap/static/umap/locale/pt_PT.json +40 -14
  160. umap/static/umap/locale/ro.js +40 -14
  161. umap/static/umap/locale/ro.json +40 -14
  162. umap/static/umap/locale/ru.js +40 -14
  163. umap/static/umap/locale/ru.json +40 -14
  164. umap/static/umap/locale/sk_SK.js +40 -14
  165. umap/static/umap/locale/sk_SK.json +40 -14
  166. umap/static/umap/locale/sl.js +40 -14
  167. umap/static/umap/locale/sl.json +40 -14
  168. umap/static/umap/locale/sr.js +40 -14
  169. umap/static/umap/locale/sr.json +40 -14
  170. umap/static/umap/locale/sv.js +40 -14
  171. umap/static/umap/locale/sv.json +40 -14
  172. umap/static/umap/locale/th_TH.js +40 -14
  173. umap/static/umap/locale/th_TH.json +40 -14
  174. umap/static/umap/locale/tr.js +40 -14
  175. umap/static/umap/locale/tr.json +40 -14
  176. umap/static/umap/locale/uk_UA.js +40 -14
  177. umap/static/umap/locale/uk_UA.json +40 -14
  178. umap/static/umap/locale/vi.js +40 -14
  179. umap/static/umap/locale/vi.json +40 -14
  180. umap/static/umap/locale/vi_VN.json +40 -14
  181. umap/static/umap/locale/zh.js +40 -14
  182. umap/static/umap/locale/zh.json +40 -14
  183. umap/static/umap/locale/zh_CN.json +40 -14
  184. umap/static/umap/locale/zh_TW.Big5.json +40 -14
  185. umap/static/umap/locale/zh_TW.js +40 -14
  186. umap/static/umap/locale/zh_TW.json +40 -14
  187. umap/static/umap/map.css +60 -223
  188. umap/static/umap/unittests/utils.js +18 -0
  189. umap/static/umap/vars.css +23 -5
  190. umap/templates/umap/components/alerts/alert.html +32 -29
  191. umap/templates/umap/css.html +2 -1
  192. umap/templates/umap/login_popup_end.html +18 -9
  193. umap/templates/umap/user_map_table.html +7 -2
  194. umap/tests/integration/conftest.py +2 -6
  195. umap/tests/integration/test_anonymous_owned_map.py +89 -36
  196. umap/tests/integration/test_basics.py +25 -1
  197. umap/tests/integration/test_browser.py +37 -0
  198. umap/tests/integration/test_datalayer.py +9 -16
  199. umap/tests/integration/test_draw_polygon.py +2 -0
  200. umap/tests/integration/test_edit_marker.py +1 -1
  201. umap/tests/integration/test_export_map.py +19 -0
  202. umap/tests/integration/test_fields.py +522 -0
  203. umap/tests/integration/test_filters.py +617 -0
  204. umap/tests/integration/test_import.py +15 -42
  205. umap/tests/integration/test_remote_data.py +60 -4
  206. umap/tests/integration/test_share.py +4 -4
  207. umap/tests/integration/test_tableeditor.py +31 -7
  208. umap/tests/integration/test_websocket_sync.py +3 -1
  209. umap/tests/test_dashboard.py +10 -0
  210. umap/urls.py +1 -0
  211. umap/views.py +5 -0
  212. {umap_project-3.3.5.dist-info → umap_project-3.4.0b0.dist-info}/METADATA +12 -12
  213. {umap_project-3.3.5.dist-info → umap_project-3.4.0b0.dist-info}/RECORD +216 -213
  214. umap/static/umap/js/modules/facets.js +0 -164
  215. umap/tests/integration/test_facets_browser.py +0 -279
  216. {umap_project-3.3.5.dist-info → umap_project-3.4.0b0.dist-info}/WHEEL +0 -0
  217. {umap_project-3.3.5.dist-info → umap_project-3.4.0b0.dist-info}/entry_points.txt +0 -0
  218. {umap_project-3.3.5.dist-info → umap_project-3.4.0b0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,522 @@
1
+ import json
2
+ import re
3
+ from copy import deepcopy
4
+ from pathlib import Path
5
+
6
+ import pytest
7
+ from playwright.sync_api import expect
8
+
9
+ from umap.models import DataLayer, Map
10
+
11
+ from ..base import DataLayerFactory
12
+
13
+ pytestmark = pytest.mark.django_db
14
+
15
+
16
+ DATALAYER_DATA1 = {
17
+ "type": "FeatureCollection",
18
+ "features": [
19
+ {
20
+ "type": "Feature",
21
+ "properties": {
22
+ "mytype": "even",
23
+ "name": "Point 2",
24
+ "mynumber": 10,
25
+ "mydate": "2024/04/14 12:19:17",
26
+ },
27
+ "geometry": {"type": "Point", "coordinates": [0.065918, 48.385442]},
28
+ },
29
+ {
30
+ "type": "Feature",
31
+ "properties": {
32
+ "mytype": "odd",
33
+ "name": "Point 1",
34
+ "mynumber": 12,
35
+ "mydate": "2024/03/13 12:20:20",
36
+ },
37
+ "geometry": {"type": "Point", "coordinates": [3.55957, 49.767074]},
38
+ },
39
+ ],
40
+ "_umap_options": {
41
+ "name": "Calque 1",
42
+ },
43
+ }
44
+
45
+
46
+ DATALAYER_DATA2 = {
47
+ "type": "FeatureCollection",
48
+ "features": [
49
+ {
50
+ "type": "Feature",
51
+ "properties": {
52
+ "mytype": "even",
53
+ "name": "Point 4",
54
+ "mynumber": 10,
55
+ "mydate": "2024/08/18 13:14:15",
56
+ },
57
+ "geometry": {"type": "Point", "coordinates": [0.856934, 45.290347]},
58
+ },
59
+ {
60
+ "type": "Feature",
61
+ "properties": {
62
+ "mytype": "odd",
63
+ "name": "Point 3",
64
+ "mynumber": 14,
65
+ "mydate": "2024-04-14T10:19:17.000Z",
66
+ },
67
+ "geometry": {"type": "Point", "coordinates": [4.372559, 47.945786]},
68
+ },
69
+ ],
70
+ "_umap_options": {
71
+ "name": "Calque 2",
72
+ },
73
+ }
74
+
75
+
76
+ def test_can_add_field_on_map(live_server, page, openmap):
77
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
78
+ page.get_by_role("button", name="Map advanced properties").click()
79
+ page.get_by_text("Manage Fields").click()
80
+ page.get_by_role("button", name="Add a new field").click()
81
+ page.get_by_role("textbox", name="Field Name ✔").fill("newfield")
82
+ page.get_by_label("Field Type").select_option("Number")
83
+ page.get_by_role("button", name="OK").click()
84
+ with page.expect_response(re.compile(r".*/update/settings/")):
85
+ page.get_by_role("button", name="Save").click()
86
+ saved = Map.objects.get(pk=openmap.pk)
87
+ assert saved.settings["properties"]["fields"] == [
88
+ {"key": "newfield", "type": "Number"}
89
+ ]
90
+
91
+
92
+ def test_can_add_field_on_datalayer(live_server, page, openmap, datalayer):
93
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
94
+ page.get_by_role("button", name="Manage layers").click()
95
+ page.get_by_role("button", name="Edit", exact=True).click()
96
+ page.get_by_text("Manage Fields").click()
97
+ page.get_by_role("button", name="Add a new field").click()
98
+ page.get_by_role("textbox", name="Field Name ✔").fill("newfield")
99
+ page.get_by_label("Field Type").select_option("Number")
100
+ page.get_by_role("button", name="OK").click()
101
+ with page.expect_response(re.compile(r".*/datalayer/update/")):
102
+ page.get_by_role("button", name="Save").click()
103
+ saved = DataLayer.objects.first()
104
+ assert saved.settings["fields"] == [
105
+ {"key": "name", "type": "String"},
106
+ {"key": "description", "type": "Text"},
107
+ {"key": "newfield", "type": "Number"},
108
+ ]
109
+
110
+
111
+ def test_edit_and_rename_field_from_datalayer(live_server, page, openmap):
112
+ DataLayerFactory(map=openmap, data=DATALAYER_DATA1)
113
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
114
+ page.get_by_role("button", name="Manage layers").click()
115
+ page.get_by_role("button", name="Edit", exact=True).click()
116
+ page.get_by_text("Manage Fields").click()
117
+ page.get_by_role("button", name="Edit this field").first.click()
118
+ page.get_by_role("textbox", name="Field Name ✔").fill("mytypenew")
119
+ page.get_by_label("Field Type").select_option("Text")
120
+ page.get_by_role("button", name="OK").click()
121
+ with page.expect_response(re.compile(r".*/datalayer/update/")):
122
+ page.get_by_role("button", name="Save").click()
123
+ saved = DataLayer.objects.first()
124
+ assert saved.settings["fields"] == [
125
+ {
126
+ "key": "mytypenew",
127
+ "type": "Text",
128
+ },
129
+ {
130
+ "key": "name",
131
+ "type": "String",
132
+ },
133
+ {
134
+ "key": "mynumber",
135
+ "type": "String",
136
+ },
137
+ {
138
+ "key": "mydate",
139
+ "type": "String",
140
+ },
141
+ ]
142
+ data = json.loads(Path(saved.geojson.path).read_text())
143
+ assert data["features"][0]["properties"] == {
144
+ "mydate": "2024/03/13 12:20:20",
145
+ "mynumber": 12,
146
+ "mytypenew": "odd",
147
+ "name": "Point 1",
148
+ }
149
+ assert data["features"][1]["properties"] == {
150
+ "mydate": "2024/04/14 12:19:17",
151
+ "mynumber": 10,
152
+ "mytypenew": "even",
153
+ "name": "Point 2",
154
+ }
155
+ page.locator(".edit-undo").click()
156
+ with page.expect_response(re.compile(r".*/datalayer/update/")):
157
+ page.get_by_role("button", name="Save").click()
158
+ saved = DataLayer.objects.first()
159
+ assert saved.settings["fields"] == [
160
+ {
161
+ "key": "mytype",
162
+ "type": "String",
163
+ },
164
+ {
165
+ "key": "name",
166
+ "type": "String",
167
+ },
168
+ {
169
+ "key": "mynumber",
170
+ "type": "String",
171
+ },
172
+ {
173
+ "key": "mydate",
174
+ "type": "String",
175
+ },
176
+ ]
177
+ data = json.loads(Path(saved.geojson.path).read_text())
178
+ assert data["features"][0]["properties"] == {
179
+ "mydate": "2024/03/13 12:20:20",
180
+ "mynumber": 12,
181
+ "mytype": "odd",
182
+ "name": "Point 1",
183
+ }
184
+ assert data["features"][1]["properties"] == {
185
+ "mydate": "2024/04/14 12:19:17",
186
+ "mynumber": 10,
187
+ "mytype": "even",
188
+ "name": "Point 2",
189
+ }
190
+
191
+
192
+ def test_edit_and_rename_field_from_map(live_server, page, openmap):
193
+ dl1 = DataLayerFactory(map=openmap, data=DATALAYER_DATA1)
194
+ DataLayerFactory(map=openmap, data=DATALAYER_DATA2)
195
+ openmap.settings["properties"]["fields"] = [
196
+ {"key": "mytype", "type": "String"},
197
+ {"key": "mynumber", "type": "Number"},
198
+ ]
199
+ openmap.save()
200
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
201
+ page.get_by_role("button", name="Map advanced properties").click()
202
+ page.get_by_text("Manage Fields").click()
203
+ page.get_by_role("button", name="Edit this field").first.click()
204
+ page.get_by_role("textbox", name="Field Name ✔").fill("mytypenew")
205
+ page.get_by_label("Field Type").select_option("Text")
206
+ page.get_by_role("button", name="OK").click()
207
+ with page.expect_response(re.compile(r".*/datalayer/update/")):
208
+ page.get_by_role("button", name="Save").click()
209
+ saved = Map.objects.get(pk=openmap.pk)
210
+ assert saved.settings["properties"]["fields"] == [
211
+ {"key": "mytypenew", "type": "Text"},
212
+ {"key": "mynumber", "type": "Number"},
213
+ ]
214
+ saved = DataLayer.objects.get(pk=dl1.pk)
215
+ assert saved.settings["fields"] == [
216
+ {
217
+ "key": "name",
218
+ "type": "String",
219
+ },
220
+ {
221
+ "key": "mydate",
222
+ "type": "String",
223
+ },
224
+ ]
225
+ data = json.loads(Path(saved.geojson.path).read_text())
226
+ assert data["features"][0]["properties"] == {
227
+ "mydate": "2024/03/13 12:20:20",
228
+ "mynumber": 12,
229
+ "mytypenew": "odd",
230
+ "name": "Point 1",
231
+ }
232
+ assert data["features"][1]["properties"] == {
233
+ "mydate": "2024/04/14 12:19:17",
234
+ "mynumber": 10,
235
+ "mytypenew": "even",
236
+ "name": "Point 2",
237
+ }
238
+ page.locator(".edit-undo").click()
239
+
240
+ with page.expect_response(re.compile(rf".*/datalayer/update/{dl1.pk}")):
241
+ with page.expect_response(re.compile(r".*/update/settings/")):
242
+ page.get_by_role("button", name="Save").click()
243
+ saved = Map.objects.get(pk=openmap.pk)
244
+ assert saved.settings["properties"]["fields"] == [
245
+ {"key": "mytype", "type": "String"},
246
+ {"key": "mynumber", "type": "Number"},
247
+ ]
248
+ saved = DataLayer.objects.get(pk=dl1.pk)
249
+ assert saved.settings["fields"] == [
250
+ {
251
+ "key": "name",
252
+ "type": "String",
253
+ },
254
+ {
255
+ "key": "mydate",
256
+ "type": "String",
257
+ },
258
+ ]
259
+ data = json.loads(Path(saved.geojson.path).read_text())
260
+ assert data["features"][0]["properties"] == {
261
+ "mydate": "2024/03/13 12:20:20",
262
+ "mynumber": 12,
263
+ "mytype": "odd",
264
+ "name": "Point 1",
265
+ }
266
+ assert data["features"][1]["properties"] == {
267
+ "mydate": "2024/04/14 12:19:17",
268
+ "mynumber": 10,
269
+ "mytype": "even",
270
+ "name": "Point 2",
271
+ }
272
+
273
+
274
+ def test_delete_field_from_datalayer(live_server, page, openmap):
275
+ DataLayerFactory(map=openmap, data=DATALAYER_DATA1)
276
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
277
+ page.get_by_role("button", name="Manage layers").click()
278
+ page.get_by_role("button", name="Edit", exact=True).click()
279
+ page.get_by_text("Manage Fields").click()
280
+ page.get_by_role("button", name="Delete this field").first.click()
281
+ page.get_by_role("button", name="OK").click()
282
+ with page.expect_response(re.compile(r".*/datalayer/update/")):
283
+ page.get_by_role("button", name="Save").click()
284
+ saved = DataLayer.objects.first()
285
+ assert saved.settings["fields"] == [
286
+ {
287
+ "key": "name",
288
+ "type": "String",
289
+ },
290
+ {
291
+ "key": "mynumber",
292
+ "type": "String",
293
+ },
294
+ {
295
+ "key": "mydate",
296
+ "type": "String",
297
+ },
298
+ ]
299
+ data = json.loads(Path(saved.geojson.path).read_text())
300
+ assert data["features"][0]["properties"] == {
301
+ "mydate": "2024/03/13 12:20:20",
302
+ "mynumber": 12,
303
+ "name": "Point 1",
304
+ }
305
+ assert data["features"][1]["properties"] == {
306
+ "mydate": "2024/04/14 12:19:17",
307
+ "mynumber": 10,
308
+ "name": "Point 2",
309
+ }
310
+ page.locator(".edit-undo").click()
311
+ with page.expect_response(re.compile(r".*/datalayer/update/")):
312
+ page.get_by_role("button", name="Save").click()
313
+ saved = DataLayer.objects.first()
314
+ assert saved.settings["fields"] == [
315
+ {
316
+ "key": "mytype",
317
+ "type": "String",
318
+ },
319
+ {
320
+ "key": "name",
321
+ "type": "String",
322
+ },
323
+ {
324
+ "key": "mynumber",
325
+ "type": "String",
326
+ },
327
+ {
328
+ "key": "mydate",
329
+ "type": "String",
330
+ },
331
+ ]
332
+ data = json.loads(Path(saved.geojson.path).read_text())
333
+ assert data["features"][0]["properties"] == {
334
+ "mydate": "2024/03/13 12:20:20",
335
+ "mynumber": 12,
336
+ "name": "Point 1",
337
+ "mytype": "odd",
338
+ }
339
+ assert data["features"][1]["properties"] == {
340
+ "mydate": "2024/04/14 12:19:17",
341
+ "mynumber": 10,
342
+ "name": "Point 2",
343
+ "mytype": "even",
344
+ }
345
+
346
+
347
+ def test_delete_field_from_map(live_server, page, openmap):
348
+ dl1 = DataLayerFactory(map=openmap, data=DATALAYER_DATA1)
349
+ DataLayerFactory(map=openmap, data=DATALAYER_DATA2)
350
+ openmap.settings["properties"]["fields"] = [
351
+ {"key": "mytype", "type": "String"},
352
+ {"key": "mynumber", "type": "Number"},
353
+ ]
354
+ openmap.save()
355
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
356
+ page.get_by_role("button", name="Map advanced properties").click()
357
+ page.get_by_text("Manage Fields").click()
358
+ # Delete field mytype
359
+ page.get_by_role("button", name="Delete this field").first.click()
360
+ page.get_by_role("button", name="OK").click()
361
+ with page.expect_response(re.compile(r".*/datalayer/update/")):
362
+ page.get_by_role("button", name="Save").click()
363
+ saved = Map.objects.get(pk=openmap.pk)
364
+ assert saved.settings["properties"]["fields"] == [
365
+ {"key": "mynumber", "type": "Number"},
366
+ ]
367
+ saved = DataLayer.objects.get(pk=dl1.pk)
368
+ assert saved.settings["fields"] == [
369
+ {
370
+ "key": "name",
371
+ "type": "String",
372
+ },
373
+ {
374
+ "key": "mydate",
375
+ "type": "String",
376
+ },
377
+ ]
378
+ data = json.loads(Path(saved.geojson.path).read_text())
379
+ assert data["features"][0]["properties"] == {
380
+ "mydate": "2024/03/13 12:20:20",
381
+ "mynumber": 12,
382
+ "name": "Point 1",
383
+ }
384
+ assert data["features"][1]["properties"] == {
385
+ "mydate": "2024/04/14 12:19:17",
386
+ "mynumber": 10,
387
+ "name": "Point 2",
388
+ }
389
+ page.locator(".edit-undo").click()
390
+ with page.expect_response(re.compile(r"./update/settings/.*")):
391
+ with page.expect_response(re.compile(rf".*/datalayer/update/{dl1.pk}/")):
392
+ page.get_by_role("button", name="Save").click()
393
+ saved = Map.objects.get(pk=openmap.pk)
394
+ assert saved.settings["properties"]["fields"] == [
395
+ {"key": "mytype", "type": "String"},
396
+ {"key": "mynumber", "type": "Number"},
397
+ ]
398
+ saved = DataLayer.objects.get(pk=dl1.pk)
399
+ assert saved.settings["fields"] == [
400
+ {
401
+ "key": "name",
402
+ "type": "String",
403
+ },
404
+ {
405
+ "key": "mydate",
406
+ "type": "String",
407
+ },
408
+ ]
409
+ data = json.loads(Path(saved.geojson.path).read_text())
410
+ assert data["features"][0]["properties"] == {
411
+ "mydate": "2024/03/13 12:20:20",
412
+ "mynumber": 12,
413
+ "name": "Point 1",
414
+ "mytype": "odd",
415
+ }
416
+ assert data["features"][1]["properties"] == {
417
+ "mydate": "2024/04/14 12:19:17",
418
+ "mynumber": 10,
419
+ "name": "Point 2",
420
+ "mytype": "even",
421
+ }
422
+
423
+
424
+ def test_delete_field_from_datalayer_also_in_map(live_server, page, openmap):
425
+ # mytype exist both on map and datalayer 1
426
+ # deleting the field in the datalayer should not delete the data, as the field
427
+ # is also defined on the map
428
+ data = deepcopy(DATALAYER_DATA1)
429
+ data["_umap_options"]["fields"] = [
430
+ {"key": "mytype", "type": "String"},
431
+ {"key": "mynumber", "type": "Number"},
432
+ {"key": "name", "type": "String"},
433
+ {"key": "mydate", "type": "Date"},
434
+ ]
435
+ DataLayerFactory(map=openmap, data=data)
436
+ openmap.settings["properties"]["fields"] = [
437
+ {"key": "mytype", "type": "String"},
438
+ ]
439
+ openmap.save()
440
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
441
+ page.get_by_role("button", name="Manage layers").click()
442
+ page.get_by_role("button", name="Edit", exact=True).first.click()
443
+ page.get_by_text("Manage Fields").click()
444
+ page.get_by_role("button", name="Delete this field").first.click()
445
+ page.get_by_role("button", name="OK").click()
446
+ with page.expect_response(re.compile(r".*/datalayer/update/")):
447
+ page.get_by_role("button", name="Save").click()
448
+ saved = DataLayer.objects.first()
449
+ assert saved.settings["fields"] == [
450
+ {"key": "mynumber", "type": "Number"},
451
+ {"key": "name", "type": "String"},
452
+ {"key": "mydate", "type": "Date"},
453
+ ]
454
+ data = json.loads(Path(saved.geojson.path).read_text())
455
+ assert data["features"][0]["properties"] == {
456
+ "mydate": "2024/03/13 12:20:20",
457
+ "mynumber": 12,
458
+ "name": "Point 1",
459
+ "mytype": "odd",
460
+ }
461
+ assert data["features"][1]["properties"] == {
462
+ "mydate": "2024/04/14 12:19:17",
463
+ "mynumber": 10,
464
+ "name": "Point 2",
465
+ "mytype": "even",
466
+ }
467
+
468
+
469
+ def test_can_change_field_type_with_remote_data(live_server, page, openmap, tilelayer):
470
+ data = {
471
+ "type": "FeatureCollection",
472
+ "features": [
473
+ {
474
+ "type": "Feature",
475
+ "properties": {"name": "Point 2", "myenum": "foofoo,bababar"},
476
+ "geometry": {
477
+ "type": "Point",
478
+ "coordinates": [4.3375, 11.2707],
479
+ },
480
+ },
481
+ {
482
+ "type": "Feature",
483
+ "properties": {"name": "Point 1", "myenum": "feefee,bababar"},
484
+ "geometry": {
485
+ "type": "Point",
486
+ "coordinates": [4.3375, 12.2707],
487
+ },
488
+ },
489
+ ],
490
+ }
491
+
492
+ def handle(route):
493
+ route.fulfill(json=data)
494
+
495
+ DataLayerFactory(
496
+ map=openmap,
497
+ settings={
498
+ "remoteData": {
499
+ "url": "https://remote.org/data.json",
500
+ "format": "geojson",
501
+ },
502
+ },
503
+ )
504
+ # Intercept the route to the proxy
505
+ page.route("https://remote.org/data.json", handle)
506
+
507
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit#9/12.0017/4.4824")
508
+ page.get_by_role("button", name="Manage layers").click()
509
+ page.get_by_role("button", name="Edit", exact=True).click()
510
+ page.locator("summary").filter(has_text="Manage Fields").click()
511
+ # Click on "myenum" edit button
512
+ page.get_by_role("button", name="Edit this field").nth(1).click()
513
+ page.get_by_label("Field Type").select_option("Enum")
514
+ page.get_by_role("button", name="OK").click()
515
+ # Click on "myenum" add filter button
516
+ page.get_by_role("button", name="Add a filter for this field").nth(1).click()
517
+ page.get_by_role("button", name="OK").click()
518
+ page.get_by_role("button", name="Open browser").click()
519
+ page.get_by_text("Filters", exact=True).click()
520
+ expect(page.locator(".panel .umap-filter label")).to_contain_text(
521
+ ["bababar", "feefee", "foofoo"]
522
+ )