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
@@ -18,8 +18,9 @@ import {
18
18
  import loadPopup from '../rendering/popup.js'
19
19
 
20
20
  class Feature {
21
- constructor(datalayer, geojson = {}, id = null) {
22
- this.sync = datalayer.map.sync_engine.proxy(this)
21
+ constructor(umap, datalayer, geojson = {}, id = null) {
22
+ this._umap = umap
23
+ this.sync = umap.sync_engine.proxy(this)
23
24
  this._marked_for_deletion = false
24
25
  this._isDirty = false
25
26
  this._ui = null
@@ -69,10 +70,6 @@ class Feature {
69
70
  return this._ui
70
71
  }
71
72
 
72
- get map() {
73
- return this.datalayer?.map
74
- }
75
-
76
73
  get center() {
77
74
  return this.ui.getCenter()
78
75
  }
@@ -139,7 +136,7 @@ class Feature {
139
136
  subject: 'feature',
140
137
  metadata: {
141
138
  id: this.id,
142
- layerId: this.datalayer?.umap_id || null,
139
+ layerId: this.datalayer.id,
143
140
  featureType: this.getClassName(),
144
141
  },
145
142
  }
@@ -168,7 +165,9 @@ class Feature {
168
165
  }
169
166
 
170
167
  getSlug() {
171
- return this.properties[this.map.getOption('slugKey') || 'name'] || ''
168
+ return (
169
+ this.properties[this._umap.getProperty('slugKey') || U.DEFAULT_LABEL_KEY] || ''
170
+ )
172
171
  }
173
172
 
174
173
  getPermalink() {
@@ -196,12 +195,13 @@ class Feature {
196
195
  return
197
196
  }
198
197
  // TODO deal with an event instead?
199
- if (this.map.slideshow) {
200
- this.map.slideshow.current = this
198
+ if (this._umap.slideshow) {
199
+ this._umap.slideshow.current = this
201
200
  }
202
- this.map.currentFeature = this
203
- this.attachPopup()
204
- this.ui.openPopup(latlng || this.center)
201
+ this._umap.currentFeature = this
202
+ this.attachPopup().then(() => {
203
+ this.ui.openPopup(latlng || this.center)
204
+ })
205
205
  }
206
206
 
207
207
  render(fields) {
@@ -209,7 +209,7 @@ class Feature {
209
209
  return field.startsWith('properties.')
210
210
  })
211
211
  if (impactData) {
212
- if (this.map.currentFeature === this) {
212
+ if (this._umap.currentFeature === this) {
213
213
  this.view()
214
214
  }
215
215
  }
@@ -217,7 +217,7 @@ class Feature {
217
217
  }
218
218
 
219
219
  edit(event) {
220
- if (!this.map.editEnabled || this.isReadOnly()) return
220
+ if (!this._umap.editEnabled || this.isReadOnly()) return
221
221
  const container = DomUtil.create('div', 'umap-feature-container')
222
222
  DomUtil.createTitle(
223
223
  container,
@@ -237,15 +237,23 @@ class Feature {
237
237
  container.appendChild(builder.build())
238
238
 
239
239
  const properties = []
240
+ let labelKeyFound = undefined
240
241
  for (const property of this.datalayer._propertiesIndex) {
241
- if (['name', 'description'].includes(property)) {
242
+ if (!labelKeyFound && U.LABEL_KEYS.includes(property)) {
243
+ labelKeyFound = property
244
+ continue
245
+ }
246
+ if (property === 'description') {
242
247
  continue
243
248
  }
244
249
  properties.push([`properties.${property}`, { label: property }])
245
250
  }
246
251
  // We always want name and description for now (properties management to come)
247
252
  properties.unshift('properties.description')
248
- properties.unshift('properties.name')
253
+ if (!labelKeyFound) {
254
+ labelKeyFound = U.DEFAULT_LABEL_KEY
255
+ }
256
+ properties.unshift([`properties.${labelKeyFound}`, { label: labelKeyFound }])
249
257
  builder = new U.FormBuilder(this, properties, {
250
258
  id: 'umap-feature-properties',
251
259
  })
@@ -256,12 +264,12 @@ class Feature {
256
264
  translate('Advanced actions')
257
265
  )
258
266
  this.getAdvancedEditActions(advancedActions)
259
- const onLoad = this.map.editPanel.open({ content: container })
267
+ const onLoad = this._umap.editPanel.open({ content: container })
260
268
  onLoad.then(() => {
261
- builder.helpers['properties.name'].input.focus()
269
+ builder.helpers[`properties.${labelKeyFound}`].input.focus()
262
270
  })
263
- this.map.editedFeature = this
264
- if (!this.ui.isOnScreen(this.map.getBounds())) this.zoomTo(event)
271
+ this._umap.editedFeature = this
272
+ if (!this.ui.isOnScreen(this._umap._leafletMap.getBounds())) this.zoomTo(event)
265
273
  }
266
274
 
267
275
  getAdvancedEditActions(container) {
@@ -270,7 +278,7 @@ class Feature {
270
278
  <i class="icon icon-24 icon-delete"></i>${translate('Delete')}
271
279
  </button>`)
272
280
  button.addEventListener('click', () => {
273
- this.confirmDelete().then(() => this.map.editPanel.close())
281
+ this.confirmDelete().then(() => this._umap.editPanel.close())
274
282
  })
275
283
  container.appendChild(button)
276
284
  }
@@ -319,21 +327,28 @@ class Feature {
319
327
 
320
328
  endEdit() {}
321
329
 
322
- getDisplayName(fallback) {
323
- if (fallback === undefined) fallback = this.datalayer.getName()
324
- const key = this.getOption('labelKey') || 'name'
330
+ getDisplayName() {
331
+ const keys = U.LABEL_KEYS.slice() // Copy.
332
+ const labelKey = this.getOption('labelKey')
325
333
  // Variables mode.
326
- if (U.Utils.hasVar(key))
327
- return U.Utils.greedyTemplate(key, this.extendedProperties())
328
- // Simple mode.
329
- return this.properties[key] || this.properties.title || fallback
334
+ if (labelKey) {
335
+ if (Utils.hasVar(labelKey)) {
336
+ return Utils.greedyTemplate(labelKey, this.extendedProperties())
337
+ }
338
+ keys.unshift(labelKey)
339
+ }
340
+ for (const key of keys) {
341
+ const value = this.properties[key]
342
+ if (value) return value
343
+ }
344
+ return this.datalayer.getName()
330
345
  }
331
346
 
332
347
  hasPopupFooter() {
333
348
  if (this.datalayer.isRemoteLayer() && this.datalayer.options.remoteData.dynamic) {
334
349
  return false
335
350
  }
336
- return this.map.getOption('displayPopupFooter')
351
+ return this._umap.getProperty('displayPopupFooter')
337
352
  }
338
353
 
339
354
  getPopupClass() {
@@ -341,13 +356,15 @@ class Feature {
341
356
  return loadPopup(this.getOption('popupShape') || old)
342
357
  }
343
358
 
344
- attachPopup() {
359
+ async attachPopup() {
345
360
  const Class = this.getPopupClass()
346
- this.ui.bindPopup(new Class(this))
361
+ const popup = new Class(this)
362
+ this.ui.bindPopup(popup)
363
+ return popup.loadContent()
347
364
  }
348
365
 
349
366
  async confirmDelete() {
350
- const confirmed = await this.map.dialog.confirm(
367
+ const confirmed = await this._umap.dialog.confirm(
351
368
  translate('Are you sure you want to delete the feature?')
352
369
  )
353
370
  if (confirmed) {
@@ -359,7 +376,7 @@ class Feature {
359
376
 
360
377
  del(sync) {
361
378
  this.isDirty = true
362
- this.map.closePopup()
379
+ this._umap._leafletMap.closePopup()
363
380
  if (this.datalayer) {
364
381
  this.datalayer.removeFeature(this, sync)
365
382
  }
@@ -417,34 +434,37 @@ class Feature {
417
434
  let value = fallback
418
435
  if (typeof this.staticOptions[option] !== 'undefined') {
419
436
  value = this.staticOptions[option]
420
- } else if (U.Utils.usableOption(this.properties._umap_options, option)) {
437
+ } else if (Utils.usableOption(this.properties._umap_options, option)) {
421
438
  value = this.properties._umap_options[option]
422
439
  } else if (this.datalayer) {
423
440
  value = this.datalayer.getOption(option, this)
424
441
  } else {
425
- value = this.map.getOption(option)
442
+ value = this._umap.getProperty(option)
426
443
  }
427
444
  return value
428
445
  }
429
446
 
430
- getDynamicOption(option, fallback) {
431
- let value = this.getOption(option, fallback)
447
+ getDynamicOption(key, fallback) {
448
+ let value = this.getOption(key, fallback)
432
449
  // There is a variable inside.
433
- if (U.Utils.hasVar(value)) {
434
- value = U.Utils.greedyTemplate(value, this.properties, true)
435
- if (U.Utils.hasVar(value)) value = this.map.getDefaultOption(option)
450
+ if (Utils.hasVar(value)) {
451
+ value = Utils.greedyTemplate(value, this.properties, true)
452
+ if (Utils.hasVar(value)) value = SCHEMA[key]?.default
436
453
  }
437
454
  return value
438
455
  }
439
456
 
440
457
  zoomTo({ easing, latlng, callback } = {}) {
441
- if (easing === undefined) easing = this.map.getOption('easing')
442
- if (callback) this.map.once('moveend', callback.bind(this))
458
+ if (easing === undefined) easing = this._umap.getProperty('easing')
459
+ if (callback) this._umap._leafletMap.once('moveend', callback.bind(this))
443
460
  if (easing) {
444
- this.map.flyTo(this.center, this.getBestZoom())
461
+ this._umap._leafletMap.flyTo(this.center, this.getBestZoom())
445
462
  } else {
446
463
  latlng = latlng || this.center
447
- this.map.setView(latlng, this.getBestZoom() || this.map.getZoom())
464
+ this._umap._leafletMap.setView(
465
+ latlng,
466
+ this.getBestZoom() || this._umap._leafletMap.getZoom()
467
+ )
448
468
  }
449
469
  }
450
470
 
@@ -494,13 +514,9 @@ class Feature {
494
514
  return [U.ToggleEditAction, U.DeleteFeatureAction]
495
515
  }
496
516
 
497
- getMap() {
498
- return this.map
499
- }
500
-
501
517
  isFiltered() {
502
518
  const filterKeys = this.datalayer.getFilterKeys()
503
- const filter = this.map.browser.options.filter
519
+ const filter = this._umap.browser.options.filter
504
520
  if (filter && !this.matchFilter(filter, filterKeys)) return true
505
521
  if (!this.matchFacets()) return true
506
522
  return false
@@ -525,10 +541,10 @@ class Feature {
525
541
  }
526
542
 
527
543
  matchFacets() {
528
- const selected = this.map.facets.selected
544
+ const selected = this._umap.facets.selected
529
545
  for (const [name, { type, min, max, choices }] of Object.entries(selected)) {
530
546
  let value = this.properties[name]
531
- const parser = this.map.facets.getParser(type)
547
+ const parser = this._umap.facets.getParser(type)
532
548
  value = parser(value)
533
549
  switch (type) {
534
550
  case 'date':
@@ -562,10 +578,10 @@ class Feature {
562
578
 
563
579
  extendedProperties() {
564
580
  // Include context properties
565
- const properties = this.map.getGeoContext()
581
+ const properties = this._umap.getGeoContext()
566
582
  const locale = L.getLocale()
567
583
  if (locale) properties.locale = locale
568
- if (L.lang) properties.lang = L.lang
584
+ if (U.lang) properties.lang = U.lang
569
585
  properties.rank = this.getRank() + 1
570
586
  properties.layer = this.datalayer.getName()
571
587
  if (this.ui._map && this.hasGeom()) {
@@ -578,7 +594,7 @@ class Feature {
578
594
  properties.measure = this.ui.getMeasure()
579
595
  }
580
596
  }
581
- return L.extend(properties, this.properties)
597
+ return Object.assign(properties, this.properties)
582
598
  }
583
599
 
584
600
  getRank() {
@@ -612,10 +628,10 @@ class Feature {
612
628
  label: translate('Copy as GeoJSON'),
613
629
  action: () => {
614
630
  L.Util.copyToClipboard(JSON.stringify(this.toGeoJSON()))
615
- this.map.tooltip.open({ content: L._('✅ Copied!') })
631
+ this._umap.tooltip.open({ content: L._('✅ Copied!') })
616
632
  },
617
633
  })
618
- if (this.map.editEnabled && !this.isReadOnly()) {
634
+ if (this._umap.editEnabled && !this.isReadOnly()) {
619
635
  items = items.concat(this.getContextMenuEditItems(event))
620
636
  }
621
637
  return items
@@ -623,7 +639,7 @@ class Feature {
623
639
 
624
640
  getContextMenuEditItems() {
625
641
  let items = ['-']
626
- if (this.map.editedFeature !== this) {
642
+ if (this._umap.editedFeature !== this) {
627
643
  items.push({
628
644
  label: `${translate('Edit this feature')} (⇧+Click)`,
629
645
  action: () => this.edit(),
@@ -631,7 +647,7 @@ class Feature {
631
647
  }
632
648
  items = items.concat(
633
649
  {
634
- label: this.map.help.displayLabel('EDIT_FEATURE_LAYER'),
650
+ label: this._umap.help.displayLabel('EDIT_FEATURE_LAYER'),
635
651
  action: () => this.datalayer.edit(),
636
652
  },
637
653
  {
@@ -645,11 +661,23 @@ class Feature {
645
661
  )
646
662
  return items
647
663
  }
664
+
665
+ isActive() {
666
+ return this._umap.activeFeature === this
667
+ }
668
+
669
+ activate() {
670
+ this._umap.activeFeature = this
671
+ }
672
+
673
+ deactivate() {
674
+ if (this._umap.activeFeature === this) this._umap.activeFeature = undefined
675
+ }
648
676
  }
649
677
 
650
678
  export class Point extends Feature {
651
- constructor(datalayer, geojson, id) {
652
- super(datalayer, geojson, id)
679
+ constructor(umap, datalayer, geojson, id) {
680
+ super(umap, datalayer, geojson, id)
653
681
  this.staticOptions = {
654
682
  mainColor: 'color',
655
683
  className: 'marker',
@@ -750,17 +778,17 @@ class Path extends Feature {
750
778
  }
751
779
 
752
780
  edit(event) {
753
- if (this.map.editEnabled) {
781
+ if (this._umap.editEnabled) {
754
782
  super.edit(event)
755
783
  if (!this.ui.editEnabled()) this.ui.makeGeometryEditable()
756
784
  }
757
785
  }
758
786
 
759
787
  _toggleEditing(event) {
760
- if (this.map.editEnabled) {
788
+ if (this._umap.editEnabled) {
761
789
  if (this.ui.editEnabled()) {
762
790
  this.endEdit()
763
- this.map.editPanel.close()
791
+ this._umap.editPanel.close()
764
792
  } else {
765
793
  this.edit(event)
766
794
  }
@@ -786,7 +814,10 @@ class Path extends Feature {
786
814
  }
787
815
 
788
816
  getBestZoom() {
789
- return this.getOption('zoomTo') || this.map.getBoundsZoom(this.bounds, true)
817
+ return (
818
+ this.getOption('zoomTo') ||
819
+ this._umap._leafletMap.getBoundsZoom(this.bounds, true)
820
+ )
790
821
  }
791
822
 
792
823
  endEdit() {
@@ -825,11 +856,14 @@ class Path extends Feature {
825
856
 
826
857
  zoomTo({ easing, callback }) {
827
858
  // Use bounds instead of centroid for paths.
828
- easing = easing || this.map.getOption('easing')
859
+ easing = easing || this._umap.getProperty('easing')
829
860
  if (easing) {
830
- this.map.flyToBounds(this.bounds, this.getBestZoom())
861
+ this._umap._leafletMap.flyToBounds(this.bounds, this.getBestZoom())
831
862
  } else {
832
- this.map.fitBounds(this.bounds, this.getBestZoom() || this.map.getZoom())
863
+ this._umap._leafletMap.fitBounds(
864
+ this.bounds,
865
+ this.getBestZoom() || this._umap._leafletMap.getZoom()
866
+ )
833
867
  }
834
868
  if (callback) callback.call(this)
835
869
  }
@@ -840,7 +874,7 @@ class Path extends Feature {
840
874
  label: translate('Display measure'),
841
875
  action: () => Alert.info(this.ui.getMeasure()),
842
876
  })
843
- if (this.map.editEnabled && !this.isReadOnly() && this.isMulti()) {
877
+ if (this._umap.editEnabled && !this.isReadOnly() && this.isMulti()) {
844
878
  items.push(...this.getContextMenuMultiItems(event))
845
879
  }
846
880
  return items
@@ -871,11 +905,14 @@ class Path extends Feature {
871
905
 
872
906
  getContextMenuEditItems(event) {
873
907
  const items = super.getContextMenuEditItems(event)
874
- if (this.map?.editedFeature !== this && this.isSameClass(this.map.editedFeature)) {
908
+ if (
909
+ this._umap?.editedFeature !== this &&
910
+ this.isSameClass(this._umap.editedFeature)
911
+ ) {
875
912
  items.push({
876
913
  label: translate('Transfer shape to edited feature'),
877
914
  action: () => {
878
- this.transferShape(event.latlng, this.map.editedFeature)
915
+ this.transferShape(event.latlng, this._umap.editedFeature)
879
916
  },
880
917
  })
881
918
  }
@@ -892,8 +929,8 @@ class Path extends Feature {
892
929
  }
893
930
 
894
931
  export class LineString extends Path {
895
- constructor(datalayer, geojson, id) {
896
- super(datalayer, geojson, id)
932
+ constructor(umap, datalayer, geojson, id) {
933
+ super(umap, datalayer, geojson, id)
897
934
  this.staticOptions = {
898
935
  stroke: true,
899
936
  fill: false,
@@ -977,8 +1014,8 @@ export class LineString extends Path {
977
1014
  }
978
1015
  const a = toMerge[0]
979
1016
  const b = toMerge[1]
980
- const p1 = this.map.latLngToContainerPoint(a[a.length - 1])
981
- const p2 = this.map.latLngToContainerPoint(b[0])
1017
+ const p1 = this._umap._leafletMap.latLngToContainerPoint(a[a.length - 1])
1018
+ const p2 = this._umap._leafletMap.latLngToContainerPoint(b[0])
982
1019
  const tolerance = 5 // px on screen
983
1020
  if (Math.abs(p1.x - p2.x) <= tolerance && Math.abs(p1.y - p2.y) <= tolerance) {
984
1021
  a.pop()
@@ -1022,7 +1059,7 @@ export class LineString extends Path {
1022
1059
  })
1023
1060
  } else if (index === 0 || index === event.vertex.getLastIndex()) {
1024
1061
  items.push({
1025
- label: this.map.help.displayLabel('CONTINUE_LINE'),
1062
+ label: this._umap.help.displayLabel('CONTINUE_LINE'),
1026
1063
  action: () => event.vertex.continue(),
1027
1064
  })
1028
1065
  }
@@ -1038,11 +1075,16 @@ export class LineString extends Path {
1038
1075
  })
1039
1076
  return items
1040
1077
  }
1078
+
1079
+ extendedProperties() {
1080
+ const [gain, loss] = this.ui.getElevation()
1081
+ return Object.assign({ gain, loss }, super.extendedProperties())
1082
+ }
1041
1083
  }
1042
1084
 
1043
1085
  export class Polygon extends Path {
1044
- constructor(datalayer, geojson, id) {
1045
- super(datalayer, geojson, id)
1086
+ constructor(umap, datalayer, geojson, id) {
1087
+ super(umap, datalayer, geojson, id)
1046
1088
  this.staticOptions = {
1047
1089
  mainColor: 'fillColor',
1048
1090
  className: 'polygon',