umap-project 2.7.3__py3-none-any.whl → 2.8.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 (292) hide show
  1. umap/__init__.py +1 -1
  2. umap/forms.py +4 -14
  3. umap/locale/am_ET/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/am_ET/LC_MESSAGES/django.po +278 -151
  5. umap/locale/ar/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/ar/LC_MESSAGES/django.po +335 -141
  7. umap/locale/bg/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/bg/LC_MESSAGES/django.po +279 -152
  9. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/br/LC_MESSAGES/django.po +95 -79
  11. umap/locale/ca/LC_MESSAGES/django.mo +0 -0
  12. umap/locale/ca/LC_MESSAGES/django.po +85 -68
  13. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  14. umap/locale/cs_CZ/LC_MESSAGES/django.po +78 -66
  15. umap/locale/da/LC_MESSAGES/django.mo +0 -0
  16. umap/locale/da/LC_MESSAGES/django.po +280 -153
  17. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  18. umap/locale/de/LC_MESSAGES/django.po +80 -64
  19. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  20. umap/locale/el/LC_MESSAGES/django.po +82 -66
  21. umap/locale/en/LC_MESSAGES/django.po +73 -61
  22. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  23. umap/locale/es/LC_MESSAGES/django.po +75 -63
  24. umap/locale/et/LC_MESSAGES/django.mo +0 -0
  25. umap/locale/et/LC_MESSAGES/django.po +280 -153
  26. umap/locale/eu/LC_MESSAGES/django.mo +0 -0
  27. umap/locale/eu/LC_MESSAGES/django.po +82 -66
  28. umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
  29. umap/locale/fa_IR/LC_MESSAGES/django.po +80 -64
  30. umap/locale/fi/LC_MESSAGES/django.mo +0 -0
  31. umap/locale/fi/LC_MESSAGES/django.po +278 -151
  32. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  33. umap/locale/fr/LC_MESSAGES/django.po +75 -63
  34. umap/locale/gl/LC_MESSAGES/django.mo +0 -0
  35. umap/locale/gl/LC_MESSAGES/django.po +280 -153
  36. umap/locale/he/LC_MESSAGES/django.mo +0 -0
  37. umap/locale/he/LC_MESSAGES/django.po +281 -154
  38. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  39. umap/locale/hu/LC_MESSAGES/django.po +80 -64
  40. umap/locale/is/LC_MESSAGES/django.mo +0 -0
  41. umap/locale/is/LC_MESSAGES/django.po +280 -153
  42. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  43. umap/locale/it/LC_MESSAGES/django.po +82 -66
  44. umap/locale/ja/LC_MESSAGES/django.mo +0 -0
  45. umap/locale/ja/LC_MESSAGES/django.po +280 -153
  46. umap/locale/ko/LC_MESSAGES/django.mo +0 -0
  47. umap/locale/ko/LC_MESSAGES/django.po +280 -153
  48. umap/locale/lt/LC_MESSAGES/django.mo +0 -0
  49. umap/locale/lt/LC_MESSAGES/django.po +280 -153
  50. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  51. umap/locale/ms/LC_MESSAGES/django.po +82 -66
  52. umap/locale/nl/LC_MESSAGES/django.mo +0 -0
  53. umap/locale/nl/LC_MESSAGES/django.po +280 -153
  54. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  55. umap/locale/pl/LC_MESSAGES/django.po +82 -66
  56. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  57. umap/locale/pt/LC_MESSAGES/django.po +75 -63
  58. umap/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
  59. umap/locale/pt_BR/LC_MESSAGES/django.po +280 -153
  60. umap/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
  61. umap/locale/pt_PT/LC_MESSAGES/django.po +280 -153
  62. umap/locale/ru/LC_MESSAGES/django.mo +0 -0
  63. umap/locale/ru/LC_MESSAGES/django.po +280 -153
  64. umap/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  65. umap/locale/sk_SK/LC_MESSAGES/django.po +280 -153
  66. umap/locale/sl/LC_MESSAGES/django.mo +0 -0
  67. umap/locale/sl/LC_MESSAGES/django.po +280 -153
  68. umap/locale/sr/LC_MESSAGES/django.mo +0 -0
  69. umap/locale/sr/LC_MESSAGES/django.po +280 -153
  70. umap/locale/sv/LC_MESSAGES/django.mo +0 -0
  71. umap/locale/sv/LC_MESSAGES/django.po +81 -65
  72. umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
  73. umap/locale/th_TH/LC_MESSAGES/django.po +257 -185
  74. umap/locale/tr/LC_MESSAGES/django.mo +0 -0
  75. umap/locale/tr/LC_MESSAGES/django.po +280 -153
  76. umap/locale/uk_UA/LC_MESSAGES/django.mo +0 -0
  77. umap/locale/uk_UA/LC_MESSAGES/django.po +280 -153
  78. umap/locale/vi/LC_MESSAGES/django.mo +0 -0
  79. umap/locale/vi/LC_MESSAGES/django.po +278 -151
  80. umap/locale/zh/LC_MESSAGES/django.mo +0 -0
  81. umap/locale/zh/LC_MESSAGES/django.po +278 -151
  82. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  83. umap/locale/zh_TW/LC_MESSAGES/django.po +97 -81
  84. umap/management/commands/empty_trash.py +35 -0
  85. umap/management/commands/migrate_to_S3.py +29 -0
  86. umap/migrations/0023_alter_datalayer_uuid.py +19 -0
  87. umap/migrations/0024_alter_map_share_status.py +30 -0
  88. umap/migrations/0025_alter_datalayer_geojson.py +24 -0
  89. umap/models.py +68 -116
  90. umap/settings/base.py +23 -3
  91. umap/settings/local_s3.py +45 -0
  92. umap/static/umap/base.css +3 -603
  93. umap/static/umap/content.css +5 -3
  94. umap/static/umap/css/bar.css +202 -0
  95. umap/static/umap/css/form.css +620 -0
  96. umap/static/umap/css/icon.css +21 -1
  97. umap/static/umap/css/popup.css +125 -0
  98. umap/static/umap/img/16-white.svg +16 -4
  99. umap/static/umap/img/16.svg +1 -1
  100. umap/static/umap/img/source/16-white.svg +46 -45
  101. umap/static/umap/img/source/16.svg +1 -753
  102. umap/static/umap/js/components/fragment.js +3 -1
  103. umap/static/umap/js/modules/browser.js +20 -19
  104. umap/static/umap/js/modules/caption.js +21 -22
  105. umap/static/umap/js/modules/data/features.js +120 -78
  106. umap/static/umap/js/modules/data/layer.js +195 -153
  107. umap/static/umap/js/modules/facets.js +9 -9
  108. umap/static/umap/js/modules/formatter.js +5 -5
  109. umap/static/umap/js/modules/global.js +4 -52
  110. umap/static/umap/js/modules/help.js +18 -21
  111. umap/static/umap/js/modules/importer.js +133 -56
  112. umap/static/umap/js/modules/importers/cadastrefr.js +4 -0
  113. umap/static/umap/js/modules/importers/geodatamine.js +3 -3
  114. umap/static/umap/js/modules/importers/overpass.js +5 -0
  115. umap/static/umap/js/modules/permissions.js +85 -87
  116. umap/static/umap/js/modules/rendering/icon.js +2 -1
  117. umap/static/umap/js/modules/rendering/layers/base.js +15 -15
  118. umap/static/umap/js/modules/rendering/layers/classified.js +1 -1
  119. umap/static/umap/js/modules/rendering/layers/cluster.js +1 -1
  120. umap/static/umap/js/modules/rendering/layers/heat.js +1 -1
  121. umap/static/umap/js/modules/rendering/map.js +390 -0
  122. umap/static/umap/js/modules/rendering/popup.js +19 -19
  123. umap/static/umap/js/modules/rendering/template.js +88 -21
  124. umap/static/umap/js/modules/rendering/ui.js +63 -14
  125. umap/static/umap/js/modules/request.js +2 -2
  126. umap/static/umap/js/modules/rules.js +22 -25
  127. umap/static/umap/js/modules/saving.js +47 -0
  128. umap/static/umap/js/modules/schema.js +6 -0
  129. umap/static/umap/js/modules/share.js +21 -24
  130. umap/static/umap/js/modules/slideshow.js +24 -20
  131. umap/static/umap/js/modules/sync/updaters.js +7 -9
  132. umap/static/umap/js/modules/tableeditor.js +20 -19
  133. umap/static/umap/js/modules/ui/bar.js +196 -0
  134. umap/static/umap/js/modules/ui/dialog.js +5 -0
  135. umap/static/umap/js/modules/ui/panel.js +10 -9
  136. umap/static/umap/js/modules/umap.js +1691 -0
  137. umap/static/umap/js/modules/urls.js +2 -2
  138. umap/static/umap/js/modules/utils.js +22 -6
  139. umap/static/umap/js/umap.controls.js +81 -305
  140. umap/static/umap/js/umap.core.js +29 -50
  141. umap/static/umap/js/umap.forms.js +78 -27
  142. umap/static/umap/keycloak.png +0 -0
  143. umap/static/umap/locale/am_ET.js +26 -10
  144. umap/static/umap/locale/am_ET.json +26 -10
  145. umap/static/umap/locale/ar.js +26 -10
  146. umap/static/umap/locale/ar.json +26 -10
  147. umap/static/umap/locale/ast.js +26 -10
  148. umap/static/umap/locale/ast.json +26 -10
  149. umap/static/umap/locale/bg.js +26 -10
  150. umap/static/umap/locale/bg.json +26 -10
  151. umap/static/umap/locale/br.js +27 -20
  152. umap/static/umap/locale/br.json +27 -20
  153. umap/static/umap/locale/ca.js +32 -29
  154. umap/static/umap/locale/ca.json +32 -29
  155. umap/static/umap/locale/cs_CZ.js +24 -17
  156. umap/static/umap/locale/cs_CZ.json +24 -17
  157. umap/static/umap/locale/da.js +26 -10
  158. umap/static/umap/locale/da.json +26 -10
  159. umap/static/umap/locale/de.js +21 -14
  160. umap/static/umap/locale/de.json +21 -14
  161. umap/static/umap/locale/el.js +28 -12
  162. umap/static/umap/locale/el.json +28 -12
  163. umap/static/umap/locale/en.js +14 -9
  164. umap/static/umap/locale/en.json +14 -9
  165. umap/static/umap/locale/en_US.json +26 -10
  166. umap/static/umap/locale/es.js +16 -13
  167. umap/static/umap/locale/es.json +16 -13
  168. umap/static/umap/locale/et.js +26 -10
  169. umap/static/umap/locale/et.json +26 -10
  170. umap/static/umap/locale/eu.js +16 -9
  171. umap/static/umap/locale/eu.json +16 -9
  172. umap/static/umap/locale/fa_IR.js +16 -9
  173. umap/static/umap/locale/fa_IR.json +16 -9
  174. umap/static/umap/locale/fi.js +26 -10
  175. umap/static/umap/locale/fi.json +26 -10
  176. umap/static/umap/locale/fr.js +14 -9
  177. umap/static/umap/locale/fr.json +14 -9
  178. umap/static/umap/locale/gl.js +26 -10
  179. umap/static/umap/locale/gl.json +26 -10
  180. umap/static/umap/locale/he.js +26 -10
  181. umap/static/umap/locale/he.json +26 -10
  182. umap/static/umap/locale/hr.js +26 -10
  183. umap/static/umap/locale/hr.json +26 -10
  184. umap/static/umap/locale/hu.js +16 -9
  185. umap/static/umap/locale/hu.json +16 -9
  186. umap/static/umap/locale/id.js +26 -10
  187. umap/static/umap/locale/id.json +26 -10
  188. umap/static/umap/locale/is.js +26 -10
  189. umap/static/umap/locale/is.json +26 -10
  190. umap/static/umap/locale/it.js +26 -10
  191. umap/static/umap/locale/it.json +26 -10
  192. umap/static/umap/locale/ja.js +26 -10
  193. umap/static/umap/locale/ja.json +26 -10
  194. umap/static/umap/locale/ko.js +26 -10
  195. umap/static/umap/locale/ko.json +26 -10
  196. umap/static/umap/locale/lt.js +26 -10
  197. umap/static/umap/locale/lt.json +26 -10
  198. umap/static/umap/locale/ms.js +28 -12
  199. umap/static/umap/locale/ms.json +28 -12
  200. umap/static/umap/locale/nl.js +28 -12
  201. umap/static/umap/locale/nl.json +28 -12
  202. umap/static/umap/locale/no.js +26 -10
  203. umap/static/umap/locale/no.json +26 -10
  204. umap/static/umap/locale/pl.js +28 -12
  205. umap/static/umap/locale/pl.json +28 -12
  206. umap/static/umap/locale/pl_PL.json +26 -10
  207. umap/static/umap/locale/pt.js +16 -9
  208. umap/static/umap/locale/pt.json +16 -9
  209. umap/static/umap/locale/pt_BR.js +26 -10
  210. umap/static/umap/locale/pt_BR.json +26 -10
  211. umap/static/umap/locale/pt_PT.js +16 -9
  212. umap/static/umap/locale/pt_PT.json +16 -9
  213. umap/static/umap/locale/ro.js +26 -10
  214. umap/static/umap/locale/ro.json +26 -10
  215. umap/static/umap/locale/ru.js +26 -10
  216. umap/static/umap/locale/ru.json +26 -10
  217. umap/static/umap/locale/si.js +7 -7
  218. umap/static/umap/locale/si.json +7 -7
  219. umap/static/umap/locale/sk_SK.js +26 -10
  220. umap/static/umap/locale/sk_SK.json +26 -10
  221. umap/static/umap/locale/sl.js +26 -10
  222. umap/static/umap/locale/sl.json +26 -10
  223. umap/static/umap/locale/sr.js +26 -10
  224. umap/static/umap/locale/sr.json +26 -10
  225. umap/static/umap/locale/sv.js +27 -11
  226. umap/static/umap/locale/sv.json +27 -11
  227. umap/static/umap/locale/th_TH.js +28 -12
  228. umap/static/umap/locale/th_TH.json +28 -12
  229. umap/static/umap/locale/tr.js +26 -10
  230. umap/static/umap/locale/tr.json +26 -10
  231. umap/static/umap/locale/uk_UA.js +26 -10
  232. umap/static/umap/locale/uk_UA.json +26 -10
  233. umap/static/umap/locale/vi.js +26 -10
  234. umap/static/umap/locale/vi.json +26 -10
  235. umap/static/umap/locale/vi_VN.json +26 -10
  236. umap/static/umap/locale/zh.js +26 -10
  237. umap/static/umap/locale/zh.json +26 -10
  238. umap/static/umap/locale/zh_CN.json +26 -10
  239. umap/static/umap/locale/zh_TW.Big5.json +26 -10
  240. umap/static/umap/locale/zh_TW.js +34 -27
  241. umap/static/umap/locale/zh_TW.json +34 -27
  242. umap/static/umap/map.css +39 -530
  243. umap/static/umap/unittests/URLs.js +15 -15
  244. umap/static/umap/unittests/utils.js +23 -1
  245. umap/static/umap/vars.css +2 -1
  246. umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +5 -1
  247. umap/storage/__init__.py +3 -0
  248. umap/storage/fs.py +101 -0
  249. umap/storage/s3.py +61 -0
  250. umap/templates/base.html +2 -0
  251. umap/templates/registration/login.html +7 -6
  252. umap/templates/umap/components/alerts/alert.html +4 -0
  253. umap/templates/umap/css.html +6 -0
  254. umap/templates/umap/js.html +3 -2
  255. umap/templates/umap/map_init.html +6 -5
  256. umap/templates/umap/user_dashboard.html +20 -19
  257. umap/tests/base.py +5 -1
  258. umap/tests/fixtures/test_upload_simple_marker.json +19 -0
  259. umap/tests/integration/conftest.py +2 -1
  260. umap/tests/integration/test_anonymous_owned_map.py +18 -10
  261. umap/tests/integration/test_browser.py +16 -1
  262. umap/tests/integration/test_dashboard.py +1 -1
  263. umap/tests/integration/test_edit_datalayer.py +29 -7
  264. umap/tests/integration/test_import.py +28 -6
  265. umap/tests/integration/test_optimistic_merge.py +31 -8
  266. umap/tests/integration/test_owned_map.py +22 -16
  267. umap/tests/integration/test_popup.py +44 -0
  268. umap/tests/integration/test_save.py +35 -0
  269. umap/tests/integration/test_view_marker.py +12 -0
  270. umap/tests/integration/test_view_polyline.py +257 -0
  271. umap/tests/integration/test_websocket_sync.py +81 -9
  272. umap/tests/test_dashboard.py +82 -0
  273. umap/tests/test_datalayer.py +6 -7
  274. umap/tests/test_datalayer_s3.py +135 -0
  275. umap/tests/test_datalayer_views.py +28 -10
  276. umap/tests/test_empty_trash.py +34 -0
  277. umap/tests/test_map.py +12 -3
  278. umap/tests/test_map_views.py +69 -37
  279. umap/tests/test_statics.py +1 -1
  280. umap/tests/test_team_views.py +35 -1
  281. umap/tests/test_views.py +31 -52
  282. umap/urls.py +3 -3
  283. umap/views.py +126 -90
  284. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/METADATA +16 -13
  285. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/RECORD +289 -269
  286. umap/management/commands/purge_purgatory.py +0 -28
  287. umap/static/umap/js/umap.js +0 -1903
  288. umap/tests/test_purge_purgatory.py +0 -25
  289. /umap/{storage.py → storage/staticfiles.py} +0 -0
  290. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/WHEEL +0 -0
  291. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/entry_points.txt +0 -0
  292. {umap_project-2.7.3.dist-info → umap_project-2.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -20,6 +20,8 @@ import { translate } from '../i18n.js'
20
20
  import { DataLayerPermissions } from '../permissions.js'
21
21
  import { Point, LineString, Polygon } from './features.js'
22
22
  import TableEditor from '../tableeditor.js'
23
+ import { ServerStored } from '../saving.js'
24
+ import * as Schema from '../schema.js'
23
25
 
24
26
  export const LAYER_TYPES = [
25
27
  DefaultLayer,
@@ -35,10 +37,11 @@ const LAYER_MAP = LAYER_TYPES.reduce((acc, klass) => {
35
37
  return acc
36
38
  }, {})
37
39
 
38
- export class DataLayer {
39
- constructor(map, data) {
40
- this.map = map
41
- this.sync = map.sync_engine.proxy(this)
40
+ export class DataLayer extends ServerStored {
41
+ constructor(umap, leafletMap, data = {}) {
42
+ super()
43
+ this._umap = umap
44
+ this.sync = umap.sync_engine.proxy(this)
42
45
  this._index = Array()
43
46
  this._features = {}
44
47
  this._geojson = null
@@ -46,8 +49,9 @@ export class DataLayer {
46
49
  this._loaded = false // Are layer metadata loaded
47
50
  this._dataloaded = false // Are layer data loaded
48
51
 
49
- this.parentPane = this.map.getPane('overlayPane')
50
- this.pane = this.map.createPane(`datalayer${stamp(this)}`, this.parentPane)
52
+ this._leafletMap = leafletMap
53
+ this.parentPane = this._leafletMap.getPane('overlayPane')
54
+ this.pane = this._leafletMap.createPane(`datalayer${stamp(this)}`, this.parentPane)
51
55
  this.pane.dataset.id = stamp(this)
52
56
  // FIXME: should be on layer
53
57
  this.renderer = L.svg({ pane: this.pane })
@@ -58,9 +62,12 @@ export class DataLayer {
58
62
  editMode: 'advanced',
59
63
  }
60
64
 
61
- this._isDirty = false
62
65
  this._isDeleted = false
63
- this.setUmapId(data.id)
66
+ this._referenceVersion = data._referenceVersion
67
+ // Do not save it later.
68
+ delete data._referenceVersion
69
+ data.id = data.id || crypto.randomUUID()
70
+
64
71
  this.setOptions(data)
65
72
 
66
73
  if (!Utils.isObject(this.options.remoteData)) {
@@ -77,8 +84,9 @@ export class DataLayer {
77
84
  }
78
85
  this.backupOptions()
79
86
  this.connectToMap()
80
- this.permissions = new DataLayerPermissions(this)
81
- if (!this.umap_id) {
87
+ this.permissions = new DataLayerPermissions(this._umap, this)
88
+
89
+ if (!this.createdOnServer) {
82
90
  if (this.showAtLoad()) this.show()
83
91
  this.isDirty = true
84
92
  }
@@ -89,23 +97,24 @@ export class DataLayer {
89
97
  if (this.isVisible()) this.propagateShow()
90
98
  }
91
99
 
92
- set isDirty(status) {
93
- this._isDirty = status
100
+ get id() {
101
+ return this.options.id
102
+ }
103
+
104
+ get createdOnServer() {
105
+ return Boolean(this._referenceVersion)
106
+ }
107
+
108
+ onDirty(status) {
94
109
  if (status) {
95
- this.map.isDirty = true
96
110
  // A layer can be made dirty by indirect action (like dragging layers)
97
111
  // we need to have it loaded before saving it.
98
112
  if (!this.isLoaded()) this.fetchData()
99
113
  } else {
100
- this.map.checkDirty()
101
114
  this.isDeleted = false
102
115
  }
103
116
  }
104
117
 
105
- get isDirty() {
106
- return this._isDirty
107
- }
108
-
109
118
  set isDeleted(status) {
110
119
  this._isDeleted = status
111
120
  if (status) this.isDirty = status
@@ -122,9 +131,7 @@ export class DataLayer {
122
131
  getSyncMetadata() {
123
132
  return {
124
133
  subject: 'datalayer',
125
- metadata: {
126
- id: this.umap_id || null,
127
- },
134
+ metadata: { id: this.id },
128
135
  }
129
136
  }
130
137
 
@@ -134,7 +141,7 @@ export class DataLayer {
134
141
  for (const impact of impacts) {
135
142
  switch (impact) {
136
143
  case 'ui':
137
- this.map.onDataLayersChanged()
144
+ this._umap.onDataLayersChanged()
138
145
  break
139
146
  case 'data':
140
147
  if (fields.includes('options.type')) {
@@ -159,9 +166,9 @@ export class DataLayer {
159
166
  }
160
167
 
161
168
  autoLoaded() {
162
- if (!this.map.datalayersFromQueryString) return this.options.displayOnLoad
163
- const datalayerIds = this.map.datalayersFromQueryString
164
- let loadMe = datalayerIds.includes(this.umap_id.toString())
169
+ if (!this._umap.datalayersFromQueryString) return this.options.displayOnLoad
170
+ const datalayerIds = this._umap.datalayersFromQueryString
171
+ let loadMe = datalayerIds.includes(this.id.toString())
165
172
  if (this.options.old_id) {
166
173
  loadMe = loadMe || datalayerIds.includes(this.options.old_id.toString())
167
174
  }
@@ -198,7 +205,7 @@ export class DataLayer {
198
205
  const visible = this.isVisible()
199
206
  if (this.layer) this.layer.clearLayers()
200
207
  // delete this.layer?
201
- if (visible) this.map.removeLayer(this.layer)
208
+ if (visible) this._leafletMap.removeLayer(this.layer)
202
209
  const Class = LAYER_MAP[this.options.type] || DefaultLayer
203
210
  this.layer = new Class(this)
204
211
  // Rendering layer changed, so let's force reset the feature rendering too.
@@ -216,13 +223,13 @@ export class DataLayer {
216
223
  }
217
224
 
218
225
  async fetchData() {
219
- if (!this.umap_id) return
226
+ if (!this.createdOnServer) return
220
227
  if (this._loading) return
221
228
  this._loading = true
222
- const [geojson, response, error] = await this.map.server.get(this._dataUrl())
229
+ const [geojson, response, error] = await this._umap.server.get(this._dataUrl())
223
230
  if (!error) {
224
- this._reference_version = response.headers.get('X-Datalayer-Version')
225
- // FIXME: for now this property is set dynamically from backend
231
+ this.setReferenceVersion({ response, sync: false })
232
+ // FIXME: for now the _umap_options property is set dynamically from backend
226
233
  // And thus it's not in the geojson file in the server
227
234
  // So do not let all options to be reset
228
235
  // Fix is a proper migration so all datalayers settings are
@@ -240,15 +247,16 @@ export class DataLayer {
240
247
 
241
248
  dataChanged() {
242
249
  if (!this.hasDataLoaded()) return
243
- this.map.onDataLayersChanged()
250
+ this._umap.onDataLayersChanged()
244
251
  this.layer.dataChanged()
245
252
  }
246
253
 
247
254
  fromGeoJSON(geojson, sync = true) {
248
- this.addData(geojson, sync)
255
+ const features = this.addData(geojson, sync)
249
256
  this._geojson = geojson
250
257
  this.onDataLoaded()
251
258
  this.dataChanged()
259
+ return features
252
260
  }
253
261
 
254
262
  onDataLoaded() {
@@ -258,6 +266,7 @@ export class DataLayer {
258
266
 
259
267
  async fromUmapGeoJSON(geojson) {
260
268
  if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat
269
+ geojson._umap_options.id = this.id
261
270
  if (geojson._umap_options) this.setOptions(geojson._umap_options)
262
271
  if (this.isRemoteLayer()) await this.fetchRemoteData()
263
272
  else this.fromGeoJSON(geojson, false)
@@ -281,14 +290,14 @@ export class DataLayer {
281
290
 
282
291
  reindex() {
283
292
  const features = Object.values(this._features)
284
- Utils.sortFeatures(features, this.map.getOption('sortKey'), L.lang)
293
+ this.sortFeatures(features)
285
294
  this._index = features.map((feature) => stamp(feature))
286
295
  }
287
296
 
288
297
  showAtZoom() {
289
298
  const from = Number.parseInt(this.options.fromZoom, 10)
290
299
  const to = Number.parseInt(this.options.toZoom, 10)
291
- const zoom = this.map.getZoom()
300
+ const zoom = this._leafletMap.getZoom()
292
301
  return !((!Number.isNaN(from) && zoom < from) || (!Number.isNaN(to) && zoom > to))
293
302
  }
294
303
 
@@ -300,32 +309,27 @@ export class DataLayer {
300
309
  if (!this.isRemoteLayer()) return
301
310
  if (!this.hasDynamicData() && this.hasDataLoaded() && !force) return
302
311
  if (!this.isVisible()) return
303
- let url = this.map.localizeUrl(this.options.remoteData.url)
312
+ let url = this._umap.renderUrl(this.options.remoteData.url)
304
313
  if (this.options.remoteData.proxy) {
305
- url = this.map.proxyUrl(url, this.options.remoteData.ttl)
314
+ url = this._umap.proxyUrl(url, this.options.remoteData.ttl)
306
315
  }
307
- const response = await this.map.request.get(url)
316
+ const response = await this._umap.request.get(url)
308
317
  if (response?.ok) {
309
318
  this.clear()
310
- this.map.formatter
319
+ return this._umap.formatter
311
320
  .parse(await response.text(), this.options.remoteData.format)
312
321
  .then((geojson) => this.fromGeoJSON(geojson))
313
322
  }
314
323
  }
315
324
 
316
325
  isLoaded() {
317
- return !this.umap_id || this._loaded
326
+ return !this.createdOnServer || this._loaded
318
327
  }
319
328
 
320
329
  hasDataLoaded() {
321
330
  return this._dataloaded
322
331
  }
323
332
 
324
- setUmapId(id) {
325
- // Datalayer is null when listening creation form
326
- if (!this.umap_id && id) this.umap_id = id
327
- }
328
-
329
333
  backupOptions() {
330
334
  this._backupOptions = Utils.CopyJSON(this.options)
331
335
  }
@@ -347,25 +351,23 @@ export class DataLayer {
347
351
 
348
352
  connectToMap() {
349
353
  const id = stamp(this)
350
- if (!this.map.datalayers[id]) {
351
- this.map.datalayers[id] = this
354
+ if (!this._umap.datalayers[id]) {
355
+ this._umap.datalayers[id] = this
352
356
  }
353
- if (!this.map.datalayers_index.includes(this)) {
354
- this.map.datalayers_index.push(this)
357
+ if (!this._umap.datalayersIndex.includes(this)) {
358
+ this._umap.datalayersIndex.push(this)
355
359
  }
356
- this.map.onDataLayersChanged()
360
+ this._umap.onDataLayersChanged()
357
361
  }
358
362
 
359
363
  _dataUrl() {
360
- const template = this.map.options.urls.datalayer_view
361
-
362
- let url = Utils.template(template, {
363
- pk: this.umap_id,
364
- map_id: this.map.options.umap_id,
364
+ let url = this._umap.urls.get('datalayer_view', {
365
+ pk: this.id,
366
+ map_id: this._umap.id,
365
367
  })
366
368
 
367
369
  // No browser cache for owners/editors.
368
- if (this.map.hasEditMode()) url = `${url}?${Date.now()}`
370
+ if (this._umap.hasEditMode()) url = `${url}?${Date.now()}`
369
371
  return url
370
372
  }
371
373
 
@@ -392,7 +394,7 @@ export class DataLayer {
392
394
  this._index.push(id)
393
395
  this._features[id] = feature
394
396
  this.indexProperties(feature)
395
- this.map.features_index[feature.getSlug()] = feature
397
+ this._umap.featuresIndex[feature.getSlug()] = feature
396
398
  this.showFeature(feature)
397
399
  this.dataChanged()
398
400
  }
@@ -401,7 +403,7 @@ export class DataLayer {
401
403
  const id = stamp(feature)
402
404
  if (sync !== false) feature.sync.delete()
403
405
  this.hideFeature(feature)
404
- delete this.map.features_index[feature.getSlug()]
406
+ delete this._umap.featuresIndex[feature.getSlug()]
405
407
  feature.disconnectFromDataLayer(this)
406
408
  this._index.splice(this._index.indexOf(id), 1)
407
409
  delete this._features[id]
@@ -427,6 +429,10 @@ export class DataLayer {
427
429
  if (idx !== -1) this._propertiesIndex.splice(idx, 1)
428
430
  }
429
431
 
432
+ allProperties() {
433
+ return this._propertiesIndex
434
+ }
435
+
430
436
  sortedValues(property) {
431
437
  return Object.values(this._features)
432
438
  .map((feature) => feature.properties[property])
@@ -438,13 +444,19 @@ export class DataLayer {
438
444
  try {
439
445
  // Do not fail if remote data is somehow invalid,
440
446
  // otherwise the layer becomes uneditable.
441
- this.makeFeatures(geojson, sync)
447
+ return this.makeFeatures(geojson, sync)
442
448
  } catch (err) {
443
- console.log('Error with DataLayer', this.umap_id)
449
+ console.log('Error with DataLayer', this.id)
444
450
  console.error(err)
451
+ return []
445
452
  }
446
453
  }
447
454
 
455
+ sortFeatures(collection) {
456
+ const sortKeys = this._umap.getProperty('sortKey') || U.DEFAULT_LABEL_KEY
457
+ return Utils.sortFeatures(collection, sortKeys, U.lang)
458
+ }
459
+
448
460
  makeFeatures(geojson = {}, sync = true) {
449
461
  if (geojson.type === 'Feature' || geojson.coordinates) {
450
462
  geojson = [geojson]
@@ -452,10 +464,14 @@ export class DataLayer {
452
464
  const collection = Array.isArray(geojson)
453
465
  ? geojson
454
466
  : geojson.features || geojson.geometries
455
- Utils.sortFeatures(collection, this.map.getOption('sortKey'), L.lang)
456
- for (const feature of collection) {
457
- this.makeFeature(feature, sync)
467
+ if (!collection) return
468
+ const features = []
469
+ this.sortFeatures(collection)
470
+ for (const featureJson of collection) {
471
+ const feature = this.makeFeature(featureJson, sync)
472
+ if (feature) features.push(feature)
458
473
  }
474
+ return features
459
475
  }
460
476
 
461
477
  makeFeature(geojson = {}, sync = true, id = null) {
@@ -466,15 +482,15 @@ export class DataLayer {
466
482
  switch (geometry.type) {
467
483
  case 'Point':
468
484
  // FIXME: deal with MultiPoint
469
- feature = new Point(this, geojson, id)
485
+ feature = new Point(this._umap, this, geojson, id)
470
486
  break
471
487
  case 'MultiLineString':
472
488
  case 'LineString':
473
- feature = new LineString(this, geojson, id)
489
+ feature = new LineString(this._umap, this, geojson, id)
474
490
  break
475
491
  case 'MultiPolygon':
476
492
  case 'Polygon':
477
- feature = new Polygon(this, geojson, id)
493
+ feature = new Polygon(this._umap, this, geojson, id)
478
494
  break
479
495
  default:
480
496
  console.log(geojson)
@@ -492,57 +508,71 @@ export class DataLayer {
492
508
  }
493
509
 
494
510
  async importRaw(raw, format) {
495
- this.map.formatter
511
+ return this._umap.formatter
496
512
  .parse(raw, format)
497
513
  .then((geojson) => this.addData(geojson))
498
- .then(() => this.zoomTo())
499
- this.isDirty = true
514
+ .then((data) => {
515
+ if (data?.length) this.isDirty = true
516
+ return data
517
+ })
500
518
  }
501
519
 
502
- importFromFiles(files, type) {
503
- for (const f of files) {
504
- this.importFromFile(f, type)
520
+ readFile(f) {
521
+ return new Promise((resolve) => {
522
+ const reader = new FileReader()
523
+ reader.onloadend = () => resolve(reader.result)
524
+ reader.readAsText(f)
525
+ })
526
+ }
527
+
528
+ async importFromFiles(files, type) {
529
+ const toLoad = []
530
+ for (const file of files) {
531
+ toLoad.push(this.importFromFile(file, type))
505
532
  }
533
+ const features = await Promise.all(toLoad)
534
+ return new Promise((resolve) => {
535
+ resolve([].concat(...features))
536
+ })
506
537
  }
507
538
 
508
- importFromFile(f, type) {
509
- const reader = new FileReader()
539
+ async importFromFile(file, type) {
510
540
  type = type || Utils.detectFileType(f)
511
- reader.readAsText(f)
512
- reader.onload = (e) => this.importRaw(e.target.result, type)
541
+ const raw = await this.readFile(file)
542
+ return this.importRaw(raw, type)
513
543
  }
514
544
 
515
545
  async importFromUrl(uri, type) {
516
- uri = this.map.localizeUrl(uri)
517
- const response = await this.map.request.get(uri)
546
+ uri = this._umap.renderUrl(uri)
547
+ const response = await this._umap.request.get(uri)
518
548
  if (response?.ok) {
519
- this.importRaw(await response.text(), type)
549
+ return this.importRaw(await response.text(), type)
520
550
  }
521
551
  }
522
552
 
523
553
  getColor() {
524
- return this.options.color || this.map.getOption('color')
554
+ return this.options.color || this._umap.getProperty('color')
525
555
  }
526
556
 
527
557
  getDeleteUrl() {
528
- return Utils.template(this.map.options.urls.datalayer_delete, {
529
- pk: this.umap_id,
530
- map_id: this.map.options.umap_id,
558
+ return this._umap.urls.get('datalayer_delete', {
559
+ pk: this.id,
560
+ map_id: this._umap.id,
531
561
  })
532
562
  }
533
563
 
534
564
  getVersionsUrl() {
535
- return Utils.template(this.map.options.urls.datalayer_versions, {
536
- pk: this.umap_id,
537
- map_id: this.map.options.umap_id,
565
+ return this._umap.urls.get('datalayer_versions', {
566
+ pk: this.id,
567
+ map_id: this._umap.id,
538
568
  })
539
569
  }
540
570
 
541
- getVersionUrl(name) {
542
- return Utils.template(this.map.options.urls.datalayer_version, {
543
- pk: this.umap_id,
544
- map_id: this.map.options.umap_id,
545
- name: name,
571
+ getVersionUrl(ref) {
572
+ return this._umap.urls.get('datalayer_version', {
573
+ pk: this.id,
574
+ map_id: this._umap.id,
575
+ ref: ref,
546
576
  })
547
577
  }
548
578
 
@@ -562,17 +592,17 @@ export class DataLayer {
562
592
  options.name = translate('Clone of {name}', { name: this.options.name })
563
593
  delete options.id
564
594
  const geojson = Utils.CopyJSON(this._geojson)
565
- const datalayer = this.map.createDataLayer(options)
595
+ const datalayer = this._umap.createDataLayer(options)
566
596
  datalayer.fromGeoJSON(geojson)
567
597
  return datalayer
568
598
  }
569
599
 
570
600
  erase() {
571
601
  this.hide()
572
- this.map.datalayers_index.splice(this.getRank(), 1)
602
+ this._umap.datalayersIndex.splice(this.getRank(), 1)
573
603
  this.parentPane.removeChild(this.pane)
574
- this.map.onDataLayersChanged()
575
- this.layer.onDelete(this.map)
604
+ this._umap.onDataLayersChanged()
605
+ this.layer.onDelete(this._leafletMap)
576
606
  this.propagateDelete()
577
607
  this._leaflet_events_bk = this._leaflet_events
578
608
  this.clear()
@@ -581,7 +611,10 @@ export class DataLayer {
581
611
  }
582
612
 
583
613
  reset() {
584
- if (!this.umap_id) this.erase()
614
+ if (!this.createdOnServer) {
615
+ this.erase()
616
+ return
617
+ }
585
618
 
586
619
  this.resetOptions()
587
620
  this.parentPane.appendChild(this.pane)
@@ -604,7 +637,7 @@ export class DataLayer {
604
637
  }
605
638
 
606
639
  edit() {
607
- if (!this.map.editEnabled || !this.isLoaded()) {
640
+ if (!this._umap.editEnabled || !this.isLoaded()) {
608
641
  return
609
642
  }
610
643
  const container = DomUtil.create('div', 'umap-layer-properties-container')
@@ -615,6 +648,7 @@ export class DataLayer {
615
648
  'options.type',
616
649
  { handler: 'LayerTypeChooser', label: translate('Type of layer') },
617
650
  ],
651
+ 'options.labelKey',
618
652
  [
619
653
  'options.displayOnLoad',
620
654
  { label: translate('Display on load'), handler: 'Switch' },
@@ -638,7 +672,7 @@ export class DataLayer {
638
672
  DomUtil.createTitle(container, translate('Layer properties'), 'icon-layers')
639
673
  let builder = new U.FormBuilder(this, metadataFields, {
640
674
  callback(e) {
641
- this.map.onDataLayersChanged()
675
+ this._umap.onDataLayersChanged()
642
676
  if (e.helper.field === 'options.type') {
643
677
  this.edit()
644
678
  }
@@ -687,7 +721,6 @@ export class DataLayer {
687
721
  'options.zoomTo',
688
722
  'options.fromZoom',
689
723
  'options.toZoom',
690
- 'options.labelKey',
691
724
  ]
692
725
 
693
726
  builder = new U.FormBuilder(this, optionsFields, {
@@ -749,7 +782,7 @@ export class DataLayer {
749
782
  },
750
783
  ],
751
784
  ]
752
- if (this.map.options.urls.ajax_proxy) {
785
+ if (this._umap.properties.urls.ajax_proxy) {
753
786
  remoteDataFields.push([
754
787
  'options.remoteData.proxy',
755
788
  {
@@ -775,7 +808,8 @@ export class DataLayer {
775
808
  this
776
809
  )
777
810
 
778
- if (this.map.options.urls.datalayer_versions) this.buildVersionsFieldset(container)
811
+ if (this._umap.properties.urls.datalayer_versions)
812
+ this.buildVersionsFieldset(container)
779
813
 
780
814
  const advancedActions = DomUtil.createFieldset(
781
815
  container,
@@ -788,7 +822,7 @@ export class DataLayer {
788
822
  </button>`)
789
823
  deleteButton.addEventListener('click', () => {
790
824
  this._delete()
791
- this.map.editPanel.close()
825
+ this._umap.editPanel.close()
792
826
  })
793
827
  advancedButtons.appendChild(deleteButton)
794
828
 
@@ -811,7 +845,7 @@ export class DataLayer {
811
845
  },
812
846
  this
813
847
  )
814
- if (this.umap_id) {
848
+ if (this.createdOnServer) {
815
849
  const filename = `${Utils.slugify(this.options.name)}.geojson`
816
850
  const download = Utils.loadTemplate(`
817
851
  <a class="button" href="${this._dataUrl()}" download="${filename}">
@@ -827,9 +861,9 @@ export class DataLayer {
827
861
  // Fixme: remove me when this is merged and released
828
862
  // https://github.com/Leaflet/Leaflet/pull/9052
829
863
  DomEvent.disableClickPropagation(backButton)
830
- DomEvent.on(backButton, 'click', this.map.editDatalayers, this.map)
864
+ DomEvent.on(backButton, 'click', this._umap.editDatalayers, this._umap)
831
865
 
832
- this.map.editPanel.open({
866
+ this._umap.editPanel.open({
833
867
  content: container,
834
868
  actions: [backButton],
835
869
  })
@@ -850,28 +884,22 @@ export class DataLayer {
850
884
  if (this.layer?.defaults?.[option]) {
851
885
  return this.layer.defaults[option]
852
886
  }
853
- return this.map.getOption(option, feature)
887
+ return this._umap.getProperty(option, feature)
854
888
  }
855
889
 
856
890
  async buildVersionsFieldset(container) {
857
891
  const appendVersion = (data) => {
858
892
  const date = new Date(Number.parseInt(data.at, 10))
859
- const content = `${date.toLocaleString(L.lang)} (${Number.parseInt(data.size) / 1000}Kb)`
893
+ const content = `${date.toLocaleString(U.lang)} (${Number.parseInt(data.size) / 1000}Kb)`
860
894
  const el = DomUtil.create('div', 'umap-datalayer-version', versionsContainer)
861
- const button = DomUtil.createButton(
862
- '',
863
- el,
864
- '',
865
- () => this.restore(data.name),
866
- this
867
- )
895
+ const button = DomUtil.createButton('', el, '', () => this.restore(data.ref))
868
896
  button.title = translate('Restore this version')
869
897
  DomUtil.add('span', '', el, content)
870
898
  }
871
899
 
872
900
  const versionsContainer = DomUtil.createFieldset(container, translate('Versions'), {
873
901
  async callback() {
874
- const [{ versions }, response, error] = await this.map.server.get(
902
+ const [{ versions }, response, error] = await this._umap.server.get(
875
903
  this.getVersionsUrl()
876
904
  )
877
905
  if (!error) versions.forEach(appendVersion)
@@ -881,11 +909,11 @@ export class DataLayer {
881
909
  }
882
910
 
883
911
  async restore(version) {
884
- if (!this.map.editEnabled) return
885
- this.map.dialog
912
+ if (!this._umap.editEnabled) return
913
+ this._umap.dialog
886
914
  .confirm(translate('Are you sure you want to restore this version?'))
887
915
  .then(async () => {
888
- const [geojson, response, error] = await this.map.server.get(
916
+ const [geojson, response, error] = await this._umap.server.get(
889
917
  this.getVersionUrl(version)
890
918
  )
891
919
  if (!error) {
@@ -906,13 +934,13 @@ export class DataLayer {
906
934
  }
907
935
 
908
936
  async show() {
909
- this.map.addLayer(this.layer)
937
+ this._leafletMap.addLayer(this.layer)
910
938
  if (!this.isLoaded()) await this.fetchData()
911
939
  this.propagateShow()
912
940
  }
913
941
 
914
942
  hide() {
915
- this.map.removeLayer(this.layer)
943
+ this._leafletMap.removeLayer(this.layer)
916
944
  this.propagateHide()
917
945
  }
918
946
 
@@ -924,12 +952,12 @@ export class DataLayer {
924
952
  else this.hide()
925
953
  }
926
954
 
927
- zoomTo() {
955
+ zoomTo(bounds) {
928
956
  if (!this.isVisible()) return
929
- const bounds = this.layer.getBounds()
957
+ bounds = bounds || this.layer.getBounds()
930
958
  if (bounds.isValid()) {
931
959
  const options = { maxZoom: this.getOption('zoomTo') }
932
- this.map.fitBounds(bounds, options)
960
+ this._leafletMap.fitBounds(bounds, options)
933
961
  }
934
962
  }
935
963
 
@@ -960,7 +988,7 @@ export class DataLayer {
960
988
  }
961
989
 
962
990
  isVisible() {
963
- return Boolean(this.layer && this.map.hasLayer(this.layer))
991
+ return Boolean(this.layer && this._leafletMap.hasLayer(this.layer))
964
992
  }
965
993
 
966
994
  getFeatureByIndex(index) {
@@ -997,7 +1025,7 @@ export class DataLayer {
997
1025
  getPreviousBrowsable() {
998
1026
  let id = this.getRank()
999
1027
  let next
1000
- const index = this.map.datalayers_index
1028
+ const index = this._umap.datalayersIndex
1001
1029
  while (((id = index[++id] ? id : 0), (next = index[id]))) {
1002
1030
  if (next === this || next.canBrowse()) break
1003
1031
  }
@@ -1007,7 +1035,7 @@ export class DataLayer {
1007
1035
  getNextBrowsable() {
1008
1036
  let id = this.getRank()
1009
1037
  let prev
1010
- const index = this.map.datalayers_index
1038
+ const index = this._umap.datalayersIndex
1011
1039
  while (((id = index[--id] ? id : index.length - 1), (prev = index[id]))) {
1012
1040
  if (prev === this || prev.canBrowse()) break
1013
1041
  }
@@ -1023,7 +1051,7 @@ export class DataLayer {
1023
1051
  }
1024
1052
 
1025
1053
  getRank() {
1026
- return this.map.datalayers_index.indexOf(this)
1054
+ return this._umap.datalayersIndex.indexOf(this)
1027
1055
  }
1028
1056
 
1029
1057
  isReadOnly() {
@@ -1036,6 +1064,11 @@ export class DataLayer {
1036
1064
  return this.isReadOnly() || this.isRemoteLayer()
1037
1065
  }
1038
1066
 
1067
+ setReferenceVersion({ response, sync }) {
1068
+ this._referenceVersion = response.headers.get('X-Datalayer-Version')
1069
+ this.sync.update('_referenceVersion', this._referenceVersion)
1070
+ }
1071
+
1039
1072
  async save() {
1040
1073
  if (this.isDeleted) return await this.saveDelete()
1041
1074
  if (!this.isLoaded()) {
@@ -1050,19 +1083,21 @@ export class DataLayer {
1050
1083
  // Filename support is shaky, don't do it for now.
1051
1084
  const blob = new Blob([JSON.stringify(geojson)], { type: 'application/json' })
1052
1085
  formData.append('geojson', blob)
1053
- const saveUrl = this.map.urls.get('datalayer_save', {
1054
- map_id: this.map.options.umap_id,
1055
- pk: this.umap_id,
1086
+ const saveURL = this._umap.urls.get('datalayer_save', {
1087
+ map_id: this._umap.id,
1088
+ pk: this.id,
1089
+ created: this.createdOnServer,
1056
1090
  })
1057
- const headers = this._reference_version
1058
- ? { 'X-Datalayer-Reference': this._reference_version }
1091
+ const headers = this._referenceVersion
1092
+ ? { 'X-Datalayer-Reference': this._referenceVersion }
1059
1093
  : {}
1060
- await this._trySave(saveUrl, headers, formData)
1094
+ const status = await this._trySave(saveURL, headers, formData)
1061
1095
  this._geojson = geojson
1096
+ return status
1062
1097
  }
1063
1098
 
1064
1099
  async _trySave(url, headers, formData) {
1065
- const [data, response, error] = await this.map.server.post(url, headers, formData)
1100
+ const [data, response, error] = await this._umap.server.post(url, headers, formData)
1066
1101
  if (error) {
1067
1102
  if (response && response.status === 412) {
1068
1103
  AlertConflict.error(
@@ -1071,7 +1106,15 @@ export class DataLayer {
1071
1106
  'This situation is tricky, you have to choose carefully which version is pertinent.'
1072
1107
  ),
1073
1108
  async () => {
1074
- await this._trySave(url, {}, formData)
1109
+ // Save again this layer
1110
+ const status = await this._trySave(url, {}, formData)
1111
+ if (status) {
1112
+ this.isDirty = false
1113
+
1114
+ // Call the main save, in case something else needs to be saved
1115
+ // as the conflict stopped the saving flow
1116
+ await this._umap.saveAll()
1117
+ }
1075
1118
  }
1076
1119
  )
1077
1120
  }
@@ -1083,30 +1126,27 @@ export class DataLayer {
1083
1126
  this.fromGeoJSON(data.geojson)
1084
1127
  delete data.geojson
1085
1128
  }
1086
- this._reference_version = response.headers.get('X-Datalayer-Version')
1087
- this.sync.update('_reference_version', this._reference_version)
1088
-
1089
- this.setUmapId(data.id)
1129
+ delete data.id
1130
+ delete data._referenceVersion
1090
1131
  this.updateOptions(data)
1132
+
1133
+ this.setReferenceVersion({ response, sync: true })
1134
+
1091
1135
  this.backupOptions()
1136
+ this.backupData()
1092
1137
  this.connectToMap()
1093
1138
  this._loaded = true
1094
1139
  this.redraw() // Needed for reordering features
1095
- this.isDirty = false
1096
- this.permissions.save()
1140
+ return true
1097
1141
  }
1098
1142
  }
1099
1143
 
1100
1144
  async saveDelete() {
1101
- if (this.umap_id) {
1102
- await this.map.server.post(this.getDeleteUrl())
1145
+ if (this.createdOnServer) {
1146
+ await this._umap.server.post(this.getDeleteUrl())
1103
1147
  }
1104
- delete this.map.datalayers[stamp(this)]
1105
- this.isDirty = false
1106
- }
1107
-
1108
- getMap() {
1109
- return this.map
1148
+ delete this._umap.datalayers[stamp(this)]
1149
+ return true
1110
1150
  }
1111
1151
 
1112
1152
  getName() {
@@ -1115,7 +1155,7 @@ export class DataLayer {
1115
1155
 
1116
1156
  tableEdit() {
1117
1157
  if (!this.isVisible()) return
1118
- const editor = new TableEditor(this)
1158
+ const editor = new TableEditor(this._umap, this, this._leafletMap)
1119
1159
  editor.open()
1120
1160
  }
1121
1161
 
@@ -1123,14 +1163,16 @@ export class DataLayer {
1123
1163
  // This keys will be used to filter feature from the browser text input.
1124
1164
  // By default, it will we use the "name" property, which is also the one used as label in the features list.
1125
1165
  // When map owner has configured another label or sort key, we try to be smart and search in the same keys.
1126
- if (this.map.options.filterKey) return this.map.options.filterKey
1166
+ if (this._umap.properties.filterKey) return this._umap.properties.filterKey
1127
1167
  if (this.getOption('labelKey')) return this.getOption('labelKey')
1128
- if (this.map.options.sortKey) return this.map.options.sortKey
1168
+ if (this._umap.properties.sortKey) return this._umap.properties.sortKey
1129
1169
  return 'displayName'
1130
1170
  }
1131
1171
 
1132
1172
  renderLegend() {
1133
- for (const container of document.querySelectorAll(`.${this.cssId} .datalayer-legend`)) {
1173
+ for (const container of document.querySelectorAll(
1174
+ `.${this.cssId} .datalayer-legend`
1175
+ )) {
1134
1176
  container.innerHTML = ''
1135
1177
  if (this.layer.renderLegend) return this.layer.renderLegend(container)
1136
1178
  const color = DomUtil.create('span', 'datalayer-color', container)
@@ -1174,7 +1216,7 @@ export class DataLayer {
1174
1216
  'click',
1175
1217
  function () {
1176
1218
  if (!this.isVisible()) return
1177
- this.map.dialog
1219
+ this._umap.dialog
1178
1220
  .confirm(translate('Are you sure you want to delete this layer?'))
1179
1221
  .then(() => {
1180
1222
  this._delete()