umap-project 2.4.0b2__py3-none-any.whl → 2.4.2__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 (129) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/el/LC_MESSAGES/django.po +145 -90
  3. umap/locale/en/LC_MESSAGES/django.po +3 -3
  4. umap/locale/eu/LC_MESSAGES/django.po +145 -89
  5. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/pt/LC_MESSAGES/django.po +87 -37
  7. umap/static/umap/base.css +20 -6
  8. umap/static/umap/content.css +2 -2
  9. umap/static/umap/css/dialog.css +1 -1
  10. umap/static/umap/css/importers.css +2 -0
  11. umap/static/umap/css/panel.css +2 -2
  12. umap/static/umap/css/tooltip.css +1 -1
  13. umap/static/umap/img/16-white.svg +1 -3
  14. umap/static/umap/img/source/16-white.svg +2 -4
  15. umap/static/umap/js/components/alerts/alert.css +1 -1
  16. umap/static/umap/js/components/alerts/alert.js +1 -1
  17. umap/static/umap/js/modules/autocomplete.js +4 -4
  18. umap/static/umap/js/modules/browser.js +11 -11
  19. umap/static/umap/js/modules/caption.js +5 -5
  20. umap/static/umap/js/modules/dompurify.js +2 -3
  21. umap/static/umap/js/modules/facets.js +16 -10
  22. umap/static/umap/js/modules/global.js +16 -16
  23. umap/static/umap/js/modules/help.js +2 -2
  24. umap/static/umap/js/modules/importer.js +6 -6
  25. umap/static/umap/js/modules/importers/geodatamine.js +4 -4
  26. umap/static/umap/js/modules/importers/overpass.js +2 -2
  27. umap/static/umap/js/modules/orderable.js +2 -2
  28. umap/static/umap/js/modules/request.js +1 -1
  29. umap/static/umap/js/modules/rules.js +13 -10
  30. umap/static/umap/js/modules/sync/engine.js +3 -3
  31. umap/static/umap/js/modules/sync/updaters.js +10 -11
  32. umap/static/umap/js/modules/sync/websocket.js +1 -1
  33. umap/static/umap/js/modules/ui/dialog.js +1 -1
  34. umap/static/umap/js/modules/ui/panel.js +1 -1
  35. umap/static/umap/js/modules/ui/tooltip.js +6 -6
  36. umap/static/umap/js/modules/urls.js +1 -2
  37. umap/static/umap/js/modules/utils.js +19 -19
  38. umap/static/umap/js/umap.controls.js +26 -28
  39. umap/static/umap/js/umap.core.js +19 -15
  40. umap/static/umap/js/umap.datalayer.permissions.js +15 -18
  41. umap/static/umap/js/umap.features.js +102 -120
  42. umap/static/umap/js/umap.forms.js +46 -74
  43. umap/static/umap/js/umap.icon.js +17 -22
  44. umap/static/umap/js/umap.js +126 -131
  45. umap/static/umap/js/umap.layer.js +159 -167
  46. umap/static/umap/js/umap.permissions.js +6 -9
  47. umap/static/umap/js/umap.popup.js +20 -20
  48. umap/static/umap/js/umap.share.js +9 -15
  49. umap/static/umap/js/umap.slideshow.js +12 -14
  50. umap/static/umap/js/umap.tableeditor.js +5 -5
  51. umap/static/umap/locale/am_ET.json +5 -2
  52. umap/static/umap/locale/ar.json +5 -2
  53. umap/static/umap/locale/ast.json +5 -2
  54. umap/static/umap/locale/bg.json +5 -2
  55. umap/static/umap/locale/br.json +5 -2
  56. umap/static/umap/locale/ca.json +5 -2
  57. umap/static/umap/locale/cs_CZ.json +5 -2
  58. umap/static/umap/locale/da.json +5 -2
  59. umap/static/umap/locale/de.json +5 -2
  60. umap/static/umap/locale/el.json +10 -7
  61. umap/static/umap/locale/en.js +2 -1
  62. umap/static/umap/locale/en.json +5 -2
  63. umap/static/umap/locale/en_US.json +5 -2
  64. umap/static/umap/locale/es.js +9 -8
  65. umap/static/umap/locale/es.json +12 -9
  66. umap/static/umap/locale/et.json +5 -2
  67. umap/static/umap/locale/fa_IR.json +5 -2
  68. umap/static/umap/locale/fi.json +5 -2
  69. umap/static/umap/locale/fr.js +2 -1
  70. umap/static/umap/locale/fr.json +5 -2
  71. umap/static/umap/locale/gl.json +5 -2
  72. umap/static/umap/locale/he.json +5 -2
  73. umap/static/umap/locale/hr.json +5 -2
  74. umap/static/umap/locale/hu.json +5 -2
  75. umap/static/umap/locale/id.json +5 -2
  76. umap/static/umap/locale/is.json +5 -2
  77. umap/static/umap/locale/it.json +5 -2
  78. umap/static/umap/locale/ja.json +5 -2
  79. umap/static/umap/locale/ko.json +5 -2
  80. umap/static/umap/locale/lt.json +5 -2
  81. umap/static/umap/locale/ms.json +5 -2
  82. umap/static/umap/locale/nl.json +5 -2
  83. umap/static/umap/locale/no.json +5 -2
  84. umap/static/umap/locale/pl.json +5 -2
  85. umap/static/umap/locale/pl_PL.json +5 -2
  86. umap/static/umap/locale/pt.js +61 -60
  87. umap/static/umap/locale/pt.json +64 -61
  88. umap/static/umap/locale/pt_BR.json +5 -2
  89. umap/static/umap/locale/pt_PT.json +5 -2
  90. umap/static/umap/locale/ro.json +5 -2
  91. umap/static/umap/locale/ru.json +5 -2
  92. umap/static/umap/locale/sk_SK.json +5 -2
  93. umap/static/umap/locale/sl.json +5 -2
  94. umap/static/umap/locale/sr.json +5 -2
  95. umap/static/umap/locale/sv.json +5 -2
  96. umap/static/umap/locale/th_TH.json +5 -2
  97. umap/static/umap/locale/tr.json +5 -2
  98. umap/static/umap/locale/uk_UA.json +5 -2
  99. umap/static/umap/locale/vi.json +5 -2
  100. umap/static/umap/locale/vi_VN.json +5 -2
  101. umap/static/umap/locale/zh.json +5 -2
  102. umap/static/umap/locale/zh_CN.json +5 -2
  103. umap/static/umap/locale/zh_TW.Big5.json +5 -2
  104. umap/static/umap/locale/zh_TW.json +5 -2
  105. umap/static/umap/map.css +22 -22
  106. umap/static/umap/unittests/utils.js +5 -5
  107. umap/static/umap/vars.css +12 -1
  108. umap/storage.py +1 -1
  109. umap/tests/integration/test_browser.py +76 -3
  110. umap/tests/integration/test_edit_polygon.py +11 -0
  111. umap/tests/integration/test_map.py +29 -0
  112. umap/tests/integration/test_map_preview.py +36 -2
  113. umap/tests/integration/test_view_marker.py +2 -2
  114. umap/tests/test_views.py +2 -2
  115. umap/views.py +3 -2
  116. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/METADATA +3 -3
  117. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/RECORD +120 -129
  118. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/WHEEL +1 -1
  119. umap/.DS_Store +0 -0
  120. umap/static/.DS_Store +0 -0
  121. umap/static/umap/.DS_Store +0 -0
  122. umap/static/umap/favicons/.DS_Store +0 -0
  123. umap/static/umap/fonts/.DS_Store +0 -0
  124. umap/static/umap/img/.DS_Store +0 -0
  125. umap/static/umap/img/source/.DS_Store +0 -0
  126. umap/tests/.DS_Store +0 -0
  127. umap/tests/integration/.DS_Store +0 -0
  128. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/entry_points.txt +0 -0
  129. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/licenses/LICENSE +0 -0
@@ -15,11 +15,9 @@ U.Layer = {
15
15
  return this._layers
16
16
  },
17
17
 
18
- getEditableOptions: function () {
19
- return []
20
- },
18
+ getEditableOptions: () => [],
21
19
 
22
- onEdit: function () {},
20
+ onEdit: () => {},
23
21
 
24
22
  hasDataVisible: function () {
25
23
  return !!Object.keys(this._layers).length
@@ -67,11 +65,9 @@ U.Layer.Cluster = L.MarkerClusterGroup.extend({
67
65
  polygonOptions: {
68
66
  color: this.datalayer.getColor(),
69
67
  },
70
- iconCreateFunction: function (cluster) {
71
- return new U.Icon.Cluster(datalayer, cluster)
72
- },
68
+ iconCreateFunction: (cluster) => new U.Icon.Cluster(datalayer, cluster),
73
69
  }
74
- if (this.datalayer.options.cluster && this.datalayer.options.cluster.radius) {
70
+ if (this.datalayer.options.cluster?.radius) {
75
71
  options.maxClusterRadius = this.datalayer.options.cluster.radius
76
72
  }
77
73
  L.MarkerClusterGroup.prototype.initialize.call(this, options)
@@ -99,26 +95,24 @@ U.Layer.Cluster = L.MarkerClusterGroup.extend({
99
95
  return L.MarkerClusterGroup.prototype.removeLayer.call(this, layer)
100
96
  },
101
97
 
102
- getEditableOptions: function () {
103
- return [
104
- [
105
- 'options.cluster.radius',
106
- {
107
- handler: 'BlurIntInput',
108
- placeholder: L._('Clustering radius'),
109
- helpText: L._('Override clustering radius (default 80)'),
110
- },
111
- ],
112
- [
113
- 'options.cluster.textColor',
114
- {
115
- handler: 'TextColorPicker',
116
- placeholder: L._('Auto'),
117
- helpText: L._('Text color for the cluster label'),
118
- },
119
- ],
120
- ]
121
- },
98
+ getEditableOptions: () => [
99
+ [
100
+ 'options.cluster.radius',
101
+ {
102
+ handler: 'BlurIntInput',
103
+ placeholder: L._('Clustering radius'),
104
+ helpText: L._('Override clustering radius (default 80)'),
105
+ },
106
+ ],
107
+ [
108
+ 'options.cluster.textColor',
109
+ {
110
+ handler: 'TextColorPicker',
111
+ placeholder: L._('Auto'),
112
+ helpText: L._('Text color for the cluster label'),
113
+ },
114
+ ],
115
+ ],
122
116
 
123
117
  onEdit: function (field, builder) {
124
118
  if (field === 'options.cluster.radius') {
@@ -182,8 +176,8 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
182
176
  getValues: function () {
183
177
  const values = []
184
178
  this.datalayer.eachLayer((layer) => {
185
- let value = this._getValue(layer)
186
- if (!isNaN(value)) values.push(value)
179
+ const value = this._getValue(layer)
180
+ if (!Number.isNaN(value)) values.push(value)
187
181
  })
188
182
  return values
189
183
  },
@@ -196,9 +190,9 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
196
190
  this.options.colors = []
197
191
  return
198
192
  }
199
- let mode = this.datalayer.options.choropleth.mode,
200
- classes = +this.datalayer.options.choropleth.classes || 5,
201
- breaks
193
+ const mode = this.datalayer.options.choropleth.mode
194
+ let classes = +this.datalayer.options.choropleth.classes || 5
195
+ let breaks
202
196
  classes = Math.min(classes, values.length)
203
197
  if (mode === 'manual') {
204
198
  const manualBreaks = this.datalayer.options.choropleth.breaks
@@ -206,7 +200,7 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
206
200
  breaks = manualBreaks
207
201
  .split(',')
208
202
  .map((b) => +b)
209
- .filter((b) => !isNaN(b))
203
+ .filter((b) => !Number.isNaN(b))
210
204
  }
211
205
  } else if (mode === 'equidistant') {
212
206
  breaks = ss.equalIntervalBreaks(values, classes)
@@ -249,7 +243,7 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
249
243
  addLayer: function (layer) {
250
244
  // Do not add yet the layer to the map
251
245
  // wait for datachanged event, so we want compute breaks once
252
- var id = this.getLayerId(layer)
246
+ const id = this.getLayerId(layer)
253
247
  this._layers[id] = layer
254
248
  return this
255
249
  },
@@ -332,7 +326,9 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
332
326
 
333
327
  renderLegend: function (container) {
334
328
  const parent = L.DomUtil.create('ul', '', container)
335
- let li, color, label
329
+ let li
330
+ let color
331
+ let label
336
332
 
337
333
  this.options.breaks.slice(0, -1).forEach((limit, index) => {
338
334
  li = L.DomUtil.create('li', '', parent)
@@ -364,13 +360,10 @@ U.Layer.Heat = L.HeatLayer.extend({
364
360
 
365
361
  addLayer: function (layer) {
366
362
  if (layer instanceof L.Marker) {
367
- let latlng = layer.getLatLng(),
368
- alt
369
- if (
370
- this.datalayer.options.heat &&
371
- this.datalayer.options.heat.intensityProperty
372
- ) {
373
- alt = parseFloat(
363
+ let latlng = layer.getLatLng()
364
+ let alt
365
+ if (this.datalayer.options.heat?.intensityProperty) {
366
+ alt = Number.parseFloat(
374
367
  layer.properties[this.datalayer.options.heat.intensityProperty || 0]
375
368
  )
376
369
  latlng = new L.LatLng(latlng.lat, latlng.lng, alt)
@@ -383,37 +376,33 @@ U.Layer.Heat = L.HeatLayer.extend({
383
376
  this.setLatLngs([])
384
377
  },
385
378
 
386
- getFeatures: function () {
387
- return {}
388
- },
379
+ getFeatures: () => ({}),
389
380
 
390
381
  getBounds: function () {
391
382
  return L.latLngBounds(this._latlngs)
392
383
  },
393
384
 
394
- getEditableOptions: function () {
395
- return [
396
- [
397
- 'options.heat.radius',
398
- {
399
- handler: 'Range',
400
- min: 10,
401
- max: 100,
402
- step: 5,
403
- label: L._('Heatmap radius'),
404
- helpText: L._('Override heatmap radius (default 25)'),
405
- },
406
- ],
407
- [
408
- 'options.heat.intensityProperty',
409
- {
410
- handler: 'BlurInput',
411
- placeholder: L._('Heatmap intensity property'),
412
- helpText: L._('Optional intensity property for heatmap'),
413
- },
414
- ],
415
- ]
416
- },
385
+ getEditableOptions: () => [
386
+ [
387
+ 'options.heat.radius',
388
+ {
389
+ handler: 'Range',
390
+ min: 10,
391
+ max: 100,
392
+ step: 5,
393
+ label: L._('Heatmap radius'),
394
+ helpText: L._('Override heatmap radius (default 25)'),
395
+ },
396
+ ],
397
+ [
398
+ 'options.heat.intensityProperty',
399
+ {
400
+ handler: 'BlurInput',
401
+ placeholder: L._('Heatmap intensity property'),
402
+ helpText: L._('Optional intensity property for heatmap'),
403
+ },
404
+ ],
405
+ ],
417
406
 
418
407
  onEdit: function (field, builder) {
419
408
  if (field === 'options.heat.intensityProperty') {
@@ -440,23 +429,23 @@ U.Layer.Heat = L.HeatLayer.extend({
440
429
  if (!this._map) {
441
430
  return
442
431
  }
443
- var data = [],
444
- r = this._heat._r,
445
- size = this._map.getSize(),
446
- bounds = new L.Bounds(L.point([-r, -r]), size.add([r, r])),
447
- cellSize = r / 2,
448
- grid = [],
449
- panePos = this._map._getMapPanePos(),
450
- offsetX = panePos.x % cellSize,
451
- offsetY = panePos.y % cellSize,
452
- i,
453
- len,
454
- p,
455
- cell,
456
- x,
457
- y,
458
- j,
459
- len2
432
+ const data = []
433
+ const r = this._heat._r
434
+ const size = this._map.getSize()
435
+ const bounds = new L.Bounds(L.point([-r, -r]), size.add([r, r]))
436
+ const cellSize = r / 2
437
+ const grid = []
438
+ const panePos = this._map._getMapPanePos()
439
+ const offsetX = panePos.x % cellSize
440
+ const offsetY = panePos.y % cellSize
441
+ let i
442
+ let len
443
+ let p
444
+ let cell
445
+ let x
446
+ let y
447
+ let j
448
+ let len2
460
449
 
461
450
  this._max = 1
462
451
 
@@ -465,7 +454,7 @@ U.Layer.Heat = L.HeatLayer.extend({
465
454
  x = Math.floor((p.x - offsetX) / cellSize) + 2
466
455
  y = Math.floor((p.y - offsetY) / cellSize) + 2
467
456
 
468
- var alt =
457
+ const alt =
469
458
  this._latlngs[i].alt !== undefined
470
459
  ? this._latlngs[i].alt
471
460
  : this._latlngs[i][2] !== undefined
@@ -538,23 +527,20 @@ U.DataLayer = L.Evented.extend({
538
527
 
539
528
  let isDirty = false
540
529
  let isDeleted = false
541
- const self = this
542
530
  try {
543
531
  Object.defineProperty(this, 'isDirty', {
544
- get: function () {
545
- return isDirty
546
- },
547
- set: function (status) {
548
- if (!isDirty && status) self.fire('dirty')
532
+ get: () => isDirty,
533
+ set: (status) => {
534
+ if (!isDirty && status) this.fire('dirty')
549
535
  isDirty = status
550
536
  if (status) {
551
- self.map.addDirtyDatalayer(self)
537
+ this.map.addDirtyDatalayer(this)
552
538
  // A layer can be made dirty by indirect action (like dragging layers)
553
539
  // we need to have it loaded before saving it.
554
- if (!self.isLoaded()) self.fetchData()
540
+ if (!this.isLoaded()) this.fetchData()
555
541
  } else {
556
- self.map.removeDirtyDatalayer(self)
557
- self.isDeleted = false
542
+ this.map.removeDirtyDatalayer(this)
543
+ this.isDeleted = false
558
544
  }
559
545
  },
560
546
  })
@@ -563,13 +549,11 @@ U.DataLayer = L.Evented.extend({
563
549
  }
564
550
  try {
565
551
  Object.defineProperty(this, 'isDeleted', {
566
- get: function () {
567
- return isDeleted
568
- },
569
- set: function (status) {
570
- if (!isDeleted && status) self.fire('deleted')
552
+ get: () => isDeleted,
553
+ set: (status) => {
554
+ if (!isDeleted && status) this.fire('deleted')
571
555
  isDeleted = status
572
- if (status) self.isDirty = status
556
+ if (status) this.isDirty = status
573
557
  },
574
558
  })
575
559
  } catch (e) {
@@ -582,11 +566,11 @@ U.DataLayer = L.Evented.extend({
582
566
  this.options.remoteData = {}
583
567
  }
584
568
  // Retrocompat
585
- if (this.options.remoteData && this.options.remoteData.from) {
569
+ if (this.options.remoteData?.from) {
586
570
  this.options.fromZoom = this.options.remoteData.from
587
571
  delete this.options.remoteData.from
588
572
  }
589
- if (this.options.remoteData && this.options.remoteData.to) {
573
+ if (this.options.remoteData?.to) {
590
574
  this.options.toZoom = this.options.remoteData.to
591
575
  delete this.options.remoteData.to
592
576
  }
@@ -618,9 +602,9 @@ U.DataLayer = L.Evented.extend({
618
602
  },
619
603
 
620
604
  render: function (fields, builder) {
621
- let impacts = U.Utils.getImpactsFromSchema(fields)
605
+ const impacts = U.Utils.getImpactsFromSchema(fields)
622
606
 
623
- for (let impact of impacts) {
607
+ for (const impact of impacts) {
624
608
  switch (impact) {
625
609
  case 'ui':
626
610
  this.map.onDataLayersChanged()
@@ -745,8 +729,8 @@ U.DataLayer = L.Evented.extend({
745
729
  }
746
730
  },
747
731
 
748
- fromGeoJSON: function (geojson) {
749
- this.addData(geojson)
732
+ fromGeoJSON: function (geojson, sync = true) {
733
+ this.addData(geojson, sync)
750
734
  this._geojson = geojson
751
735
  this._dataloaded = true
752
736
  this.fire('dataloaded')
@@ -757,7 +741,7 @@ U.DataLayer = L.Evented.extend({
757
741
  if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat
758
742
  if (geojson._umap_options) this.setOptions(geojson._umap_options)
759
743
  if (this.isRemoteLayer()) await this.fetchRemoteData()
760
- else this.fromGeoJSON(geojson)
744
+ else this.fromGeoJSON(geojson, false)
761
745
  this._loaded = true
762
746
  },
763
747
 
@@ -787,14 +771,14 @@ U.DataLayer = L.Evented.extend({
787
771
  },
788
772
 
789
773
  showAtZoom: function () {
790
- const from = parseInt(this.options.fromZoom, 10),
791
- to = parseInt(this.options.toZoom, 10),
792
- zoom = this.map.getZoom()
793
- return !((!isNaN(from) && zoom < from) || (!isNaN(to) && zoom > to))
774
+ const from = Number.parseInt(this.options.fromZoom, 10)
775
+ const to = Number.parseInt(this.options.toZoom, 10)
776
+ const zoom = this.map.getZoom()
777
+ return !((!Number.isNaN(from) && zoom < from) || (!Number.isNaN(to) && zoom > to))
794
778
  },
795
779
 
796
780
  hasDynamicData: function () {
797
- return !!(this.options.remoteData && this.options.remoteData.dynamic)
781
+ return !!this.options.remoteData?.dynamic
798
782
  },
799
783
 
800
784
  fetchRemoteData: async function (force) {
@@ -806,7 +790,7 @@ U.DataLayer = L.Evented.extend({
806
790
  url = this.map.proxyUrl(url, this.options.remoteData.ttl)
807
791
  }
808
792
  const response = await this.map.request.get(url)
809
- if (response && response.ok) {
793
+ if (response?.ok) {
810
794
  this.clear()
811
795
  this.rawToGeoJSON(
812
796
  await response.text(),
@@ -884,11 +868,7 @@ U.DataLayer = L.Evented.extend({
884
868
  },
885
869
 
886
870
  isRemoteLayer: function () {
887
- return Boolean(
888
- this.options.remoteData &&
889
- this.options.remoteData.url &&
890
- this.options.remoteData.format
891
- )
871
+ return Boolean(this.options.remoteData?.url && this.options.remoteData.format)
892
872
  },
893
873
 
894
874
  isClustered: function () {
@@ -911,12 +891,13 @@ U.DataLayer = L.Evented.extend({
911
891
  if (this.hasDataLoaded()) this.fire('datachanged')
912
892
  },
913
893
 
914
- removeLayer: function (feature) {
894
+ removeLayer: function (feature, sync) {
915
895
  const id = L.stamp(feature)
896
+ if (sync !== false) feature.sync.delete()
897
+ this.layer.removeLayer(feature)
916
898
  feature.disconnectFromDataLayer(this)
917
899
  this._index.splice(this._index.indexOf(id), 1)
918
900
  delete this._layers[id]
919
- this.layer.removeLayer(feature)
920
901
  delete this.map.features_index[feature.getSlug()]
921
902
  if (this.hasDataLoaded()) this.fire('datachanged')
922
903
  },
@@ -938,11 +919,11 @@ U.DataLayer = L.Evented.extend({
938
919
  if (idx !== -1) this._propertiesIndex.splice(idx, 1)
939
920
  },
940
921
 
941
- addData: function (geojson) {
922
+ addData: function (geojson, sync) {
942
923
  try {
943
924
  // Do not fail if remote data is somehow invalid,
944
925
  // otherwise the layer becomes uneditable.
945
- this.geojsonToFeatures(geojson)
926
+ this.geojsonToFeatures(geojson, sync)
946
927
  } catch (err) {
947
928
  console.log('Error with DataLayer', this.umap_id)
948
929
  console.error(err)
@@ -953,7 +934,7 @@ U.DataLayer = L.Evented.extend({
953
934
  this.rawToGeoJSON(c, type, (geojson) => this.addData(geojson))
954
935
  },
955
936
 
956
- rawToGeoJSON: function (c, type, callback) {
937
+ rawToGeoJSON: (c, type, callback) => {
957
938
  const toDom = (x) => {
958
939
  const doc = new DOMParser().parseFromString(x, 'text/xml')
959
940
  const errorNode = doc.querySelector('parsererror')
@@ -975,7 +956,7 @@ U.DataLayer = L.Evented.extend({
975
956
  // csv2geojson fallback to null geometries when it cannot determine
976
957
  // lat or lon columns. This is valid geojson, but unwanted from a user
977
958
  // point of view.
978
- if (result && result.features.length) {
959
+ if (result?.features.length) {
979
960
  if (result.features[0].geometry === null) {
980
961
  err = {
981
962
  type: 'Error',
@@ -996,7 +977,7 @@ U.DataLayer = L.Evented.extend({
996
977
  U.Alert.error(message, 10000)
997
978
  console.error(err)
998
979
  }
999
- if (result && result.features.length) {
980
+ if (result?.features.length) {
1000
981
  callback(result)
1001
982
  }
1002
983
  }
@@ -1029,9 +1010,9 @@ U.DataLayer = L.Evented.extend({
1029
1010
  // The choice of the name is not ours, because it is required by Leaflet.
1030
1011
  // It is misleading, as the returned objects are uMap objects, and not
1031
1012
  // GeoJSON features.
1032
- geojsonToFeatures: function (geojson) {
1013
+ geojsonToFeatures: function (geojson, sync) {
1033
1014
  if (!geojson) return
1034
- const features = geojson instanceof Array ? geojson : geojson.features
1015
+ const features = Array.isArray(geojson) ? geojson : geojson.features
1035
1016
  let i
1036
1017
  let len
1037
1018
 
@@ -1045,10 +1026,10 @@ U.DataLayer = L.Evented.extend({
1045
1026
 
1046
1027
  const geometry = geojson.type === 'Feature' ? geojson.geometry : geojson
1047
1028
 
1048
- let feature = this.geoJSONToLeaflet({ geometry, geojson })
1029
+ const feature = this.geoJSONToLeaflet({ geometry, geojson })
1049
1030
  if (feature) {
1050
1031
  this.addLayer(feature)
1051
- feature.onCommit()
1032
+ if (sync) feature.onCommit()
1052
1033
  return feature
1053
1034
  }
1054
1035
  },
@@ -1077,7 +1058,8 @@ U.DataLayer = L.Evented.extend({
1077
1058
  } = {}) {
1078
1059
  if (!geometry) return // null geometry is valid geojson.
1079
1060
  const coords = geometry.coordinates
1080
- let latlng, latlngs
1061
+ let latlng
1062
+ let latlngs
1081
1063
 
1082
1064
  // Create a default geojson if none is provided
1083
1065
  if (geojson === undefined) geojson = { type: 'Feature', geometry: geometry }
@@ -1176,7 +1158,7 @@ U.DataLayer = L.Evented.extend({
1176
1158
  importFromUrl: async function (uri, type) {
1177
1159
  uri = this.map.localizeUrl(uri)
1178
1160
  const response = await this.map.request.get(uri)
1179
- if (response && response.ok) {
1161
+ if (response?.ok) {
1180
1162
  this.importRaw(await response.text(), type)
1181
1163
  }
1182
1164
  },
@@ -1222,8 +1204,8 @@ U.DataLayer = L.Evented.extend({
1222
1204
  const options = U.Utils.CopyJSON(this.options)
1223
1205
  options.name = L._('Clone of {name}', { name: this.options.name })
1224
1206
  delete options.id
1225
- const geojson = U.Utils.CopyJSON(this._geojson),
1226
- datalayer = this.map.createDataLayer(options)
1207
+ const geojson = U.Utils.CopyJSON(this._geojson)
1208
+ const datalayer = this.map.createDataLayer(options)
1227
1209
  datalayer.fromGeoJSON(geojson)
1228
1210
  return datalayer
1229
1211
  },
@@ -1272,28 +1254,28 @@ U.DataLayer = L.Evented.extend({
1272
1254
  if (!this.map.editEnabled || !this.isLoaded()) {
1273
1255
  return
1274
1256
  }
1275
- const container = L.DomUtil.create('div', 'umap-layer-properties-container'),
1276
- metadataFields = [
1277
- 'options.name',
1278
- 'options.description',
1279
- ['options.type', { handler: 'LayerTypeChooser', label: L._('Type of layer') }],
1280
- ['options.displayOnLoad', { label: L._('Display on load'), handler: 'Switch' }],
1281
- [
1282
- 'options.browsable',
1283
- {
1284
- label: L._('Data is browsable'),
1285
- handler: 'Switch',
1286
- helpEntries: 'browsable',
1287
- },
1288
- ],
1289
- [
1290
- 'options.inCaption',
1291
- {
1292
- label: L._('Show this layer in the caption'),
1293
- handler: 'Switch',
1294
- },
1295
- ],
1296
- ]
1257
+ const container = L.DomUtil.create('div', 'umap-layer-properties-container')
1258
+ const metadataFields = [
1259
+ 'options.name',
1260
+ 'options.description',
1261
+ ['options.type', { handler: 'LayerTypeChooser', label: L._('Type of layer') }],
1262
+ ['options.displayOnLoad', { label: L._('Display on load'), handler: 'Switch' }],
1263
+ [
1264
+ 'options.browsable',
1265
+ {
1266
+ label: L._('Data is browsable'),
1267
+ handler: 'Switch',
1268
+ helpEntries: 'browsable',
1269
+ },
1270
+ ],
1271
+ [
1272
+ 'options.inCaption',
1273
+ {
1274
+ label: L._('Show this layer in the caption'),
1275
+ handler: 'Switch',
1276
+ },
1277
+ ],
1278
+ ]
1297
1279
  L.DomUtil.createTitle(container, L._('Layer properties'), 'icon-layers')
1298
1280
  let builder = new U.FormBuilder(this, metadataFields, {
1299
1281
  callback: function (e) {
@@ -1318,7 +1300,7 @@ U.DataLayer = L.Evented.extend({
1318
1300
  layerProperties.appendChild(builder.build())
1319
1301
  }
1320
1302
 
1321
- let shapeOptions = [
1303
+ const shapeOptions = [
1322
1304
  'options.color',
1323
1305
  'options.iconClass',
1324
1306
  'options.iconUrl',
@@ -1337,7 +1319,7 @@ U.DataLayer = L.Evented.extend({
1337
1319
  const shapeProperties = L.DomUtil.createFieldset(container, L._('Shape properties'))
1338
1320
  shapeProperties.appendChild(builder.build())
1339
1321
 
1340
- let optionsFields = [
1322
+ const optionsFields = [
1341
1323
  'options.smoothFactor',
1342
1324
  'options.dashArray',
1343
1325
  'options.zoomTo',
@@ -1484,23 +1466,23 @@ U.DataLayer = L.Evented.extend({
1484
1466
  },
1485
1467
 
1486
1468
  getOption: function (option, feature) {
1487
- if (this.layer && this.layer.getOption) {
1469
+ if (this.layer?.getOption) {
1488
1470
  const value = this.layer.getOption(option, feature)
1489
1471
  if (typeof value !== 'undefined') return value
1490
1472
  }
1491
1473
  if (typeof this.getOwnOption(option) !== 'undefined') {
1492
1474
  return this.getOwnOption(option)
1493
- } else if (this.layer && this.layer.defaults && this.layer.defaults[option]) {
1475
+ }
1476
+ if (this.layer?.defaults?.[option]) {
1494
1477
  return this.layer.defaults[option]
1495
- } else {
1496
- return this.map.getOption(option, feature)
1497
1478
  }
1479
+ return this.map.getOption(option, feature)
1498
1480
  },
1499
1481
 
1500
1482
  buildVersionsFieldset: async function (container) {
1501
1483
  const appendVersion = (data) => {
1502
- const date = new Date(parseInt(data.at, 10))
1503
- const content = `${date.toLocaleString(L.lang)} (${parseInt(data.size) / 1000}Kb)`
1484
+ const date = new Date(Number.parseInt(data.at, 10))
1485
+ const content = `${date.toLocaleString(L.lang)} (${Number.parseInt(data.size) / 1000}Kb)`
1504
1486
  const el = L.DomUtil.create('div', 'umap-datalayer-version', versionsContainer)
1505
1487
  const button = L.DomUtil.createButton(
1506
1488
  '',
@@ -1576,7 +1558,7 @@ U.DataLayer = L.Evented.extend({
1576
1558
 
1577
1559
  // Is this layer type browsable in theorie
1578
1560
  isBrowsable: function () {
1579
- return this.layer && this.layer.browsable
1561
+ return this.layer?.browsable
1580
1562
  },
1581
1563
 
1582
1564
  // Is this layer browsable in theorie
@@ -1757,6 +1739,16 @@ U.DataLayer = L.Evented.extend({
1757
1739
  const editor = new U.TableEditor(this)
1758
1740
  editor.edit()
1759
1741
  },
1742
+
1743
+ getFilterKeys: function () {
1744
+ // This keys will be used to filter feature from the browser text input.
1745
+ // By default, it will we use the "name" property, which is also the one used as label in the features list.
1746
+ // When map owner has configured another label or sort key, we try to be smart and search in the same keys.
1747
+ if (this.map.options.filterKey) return this.map.options.filterKey
1748
+ if (this.options.labelKey) return this.options.labelKey
1749
+ if (this.map.options.sortKey) return this.map.options.sortKey
1750
+ return 'name'
1751
+ },
1760
1752
  })
1761
1753
 
1762
1754
  L.TileLayer.include({
@@ -12,16 +12,13 @@ U.MapPermissions = L.Class.extend({
12
12
  this.setOptions(map.options.permissions)
13
13
  this.map = map
14
14
  let isDirty = false
15
- const self = this
16
15
  try {
17
16
  Object.defineProperty(this, 'isDirty', {
18
- get: function () {
19
- return isDirty
20
- },
21
- set: function (status) {
17
+ get: () => isDirty,
18
+ set: (status) => {
22
19
  isDirty = status
23
20
  if (status) {
24
- self.map.isDirty = status
21
+ this.map.isDirty = status
25
22
  }
26
23
  },
27
24
  })
@@ -38,7 +35,7 @@ U.MapPermissions = L.Class.extend({
38
35
  return (
39
36
  this.map.options.user &&
40
37
  this.map.options.permissions.owner &&
41
- this.map.options.user.id == this.map.options.permissions.owner.id
38
+ this.map.options.user.id === this.map.options.permissions.owner.id
42
39
  )
43
40
  },
44
41
 
@@ -154,7 +151,7 @@ U.MapPermissions = L.Class.extend({
154
151
  if (this.isOwner() || this.isAnonymousMap())
155
152
  formData.append('edit_status', this.options.edit_status)
156
153
  if (this.isOwner()) {
157
- formData.append('owner', this.options.owner && this.options.owner.id)
154
+ formData.append('owner', this.options.owner?.id)
158
155
  formData.append('share_status', this.options.share_status)
159
156
  }
160
157
  const [data, response, error] = await this.map.server.post(
@@ -183,7 +180,7 @@ U.MapPermissions = L.Class.extend({
183
180
  },
184
181
 
185
182
  addOwnerLink: function (element, container) {
186
- if (this.options.owner && this.options.owner.name && this.options.owner.url) {
183
+ if (this.options.owner?.name && this.options.owner.url) {
187
184
  const ownerContainer = L.DomUtil.add(
188
185
  element,
189
186
  'umap-map-owner',