umap-project 2.6.3__py3-none-any.whl → 2.7.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (137) hide show
  1. umap/__init__.py +1 -1
  2. umap/admin.py +64 -1
  3. umap/asgi.py +15 -0
  4. umap/context_processors.py +1 -0
  5. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/cs_CZ/LC_MESSAGES/django.po +96 -92
  7. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/de/LC_MESSAGES/django.po +19 -18
  9. umap/locale/en/LC_MESSAGES/django.po +47 -43
  10. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  11. umap/locale/es/LC_MESSAGES/django.po +134 -128
  12. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  13. umap/locale/fr/LC_MESSAGES/django.po +51 -47
  14. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  15. umap/locale/pt/LC_MESSAGES/django.po +64 -60
  16. umap/management/commands/clean_tilelayer.py +152 -0
  17. umap/management/commands/purge_purgatory.py +28 -0
  18. umap/models.py +27 -2
  19. umap/settings/base.py +3 -1
  20. umap/static/umap/base.css +4 -4
  21. umap/static/umap/css/contextmenu.css +6 -1
  22. umap/static/umap/css/icon.css +7 -2
  23. umap/static/umap/css/importers.css +4 -0
  24. umap/static/umap/img/16-white.svg +9 -2
  25. umap/static/umap/img/16.svg +1 -181
  26. umap/static/umap/img/24-white.svg +1 -0
  27. umap/static/umap/img/24.svg +1 -0
  28. umap/static/umap/img/importers/cadastrefr.svg +23 -0
  29. umap/static/umap/img/source/16-white.svg +10 -3
  30. umap/static/umap/img/source/16.svg +753 -197
  31. umap/static/umap/img/source/24-white.svg +3 -2
  32. umap/static/umap/img/source/24.svg +3 -2
  33. umap/static/umap/js/modules/autocomplete.js +7 -3
  34. umap/static/umap/js/modules/browser.js +54 -1
  35. umap/static/umap/js/modules/caption.js +16 -5
  36. umap/static/umap/js/modules/data/features.js +176 -2
  37. umap/static/umap/js/modules/data/layer.js +57 -40
  38. umap/static/umap/js/modules/formatter.js +3 -2
  39. umap/static/umap/js/modules/global.js +2 -0
  40. umap/static/umap/js/modules/importer.js +3 -0
  41. umap/static/umap/js/modules/importers/cadastrefr.js +62 -0
  42. umap/static/umap/js/modules/importers/communesfr.js +15 -3
  43. umap/static/umap/js/modules/permissions.js +123 -93
  44. umap/static/umap/js/modules/rendering/layers/classified.js +2 -0
  45. umap/static/umap/js/modules/rendering/ui.js +60 -213
  46. umap/static/umap/js/modules/share.js +1 -3
  47. umap/static/umap/js/modules/slideshow.js +1 -1
  48. umap/static/umap/js/modules/sync/engine.js +371 -14
  49. umap/static/umap/js/modules/sync/hlc.js +106 -0
  50. umap/static/umap/js/modules/sync/updaters.js +18 -6
  51. umap/static/umap/js/modules/sync/websocket.js +1 -1
  52. umap/static/umap/js/modules/tableeditor.js +1 -1
  53. umap/static/umap/js/modules/ui/base.js +2 -2
  54. umap/static/umap/js/modules/ui/contextmenu.js +51 -18
  55. umap/static/umap/js/modules/urls.js +5 -1
  56. umap/static/umap/js/modules/utils.js +28 -4
  57. umap/static/umap/js/umap.controls.js +73 -52
  58. umap/static/umap/js/umap.core.js +3 -3
  59. umap/static/umap/js/umap.forms.js +3 -1
  60. umap/static/umap/js/umap.js +115 -124
  61. umap/static/umap/locale/br.js +13 -4
  62. umap/static/umap/locale/br.json +13 -4
  63. umap/static/umap/locale/ca.js +28 -15
  64. umap/static/umap/locale/ca.json +28 -15
  65. umap/static/umap/locale/cs_CZ.js +87 -78
  66. umap/static/umap/locale/cs_CZ.json +87 -78
  67. umap/static/umap/locale/de.js +17 -8
  68. umap/static/umap/locale/de.json +17 -8
  69. umap/static/umap/locale/en.js +13 -2
  70. umap/static/umap/locale/en.json +13 -2
  71. umap/static/umap/locale/es.js +330 -319
  72. umap/static/umap/locale/es.json +330 -319
  73. umap/static/umap/locale/eu.js +10 -3
  74. umap/static/umap/locale/eu.json +10 -3
  75. umap/static/umap/locale/fa_IR.js +11 -4
  76. umap/static/umap/locale/fa_IR.json +11 -4
  77. umap/static/umap/locale/fr.js +15 -4
  78. umap/static/umap/locale/fr.json +15 -4
  79. umap/static/umap/locale/hu.js +10 -3
  80. umap/static/umap/locale/hu.json +10 -3
  81. umap/static/umap/locale/pt.js +17 -8
  82. umap/static/umap/locale/pt.json +17 -8
  83. umap/static/umap/locale/pt_PT.js +13 -4
  84. umap/static/umap/locale/pt_PT.json +13 -4
  85. umap/static/umap/locale/zh_TW.js +13 -4
  86. umap/static/umap/locale/zh_TW.json +13 -4
  87. umap/static/umap/map.css +44 -29
  88. umap/static/umap/unittests/hlc.js +165 -0
  89. umap/static/umap/unittests/sync.js +321 -15
  90. umap/static/umap/unittests/utils.js +47 -0
  91. umap/static/umap/vars.css +2 -1
  92. umap/static/umap/vendors/colorbrewer/colorbrewer.js +309 -317
  93. umap/static/umap/vendors/dompurify/purify.es.js +15 -16
  94. umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
  95. umap/static/umap/vendors/georsstogeojson/GeoRSSToGeoJSON.js +111 -80
  96. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js +2 -2
  97. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js.map +1 -1
  98. umap/static/umap/vendors/simple-statistics/simple-statistics.min.js +1 -1
  99. umap/static/umap/vendors/simple-statistics/simple-statistics.min.js.map +1 -1
  100. umap/templates/umap/css.html +0 -2
  101. umap/templates/umap/dashboard_menu.html +4 -2
  102. umap/templates/umap/js.html +0 -5
  103. umap/templates/umap/map_detail.html +2 -2
  104. umap/tests/fixtures/test_upload_data.csv +2 -2
  105. umap/tests/integration/test_anonymous_owned_map.py +1 -0
  106. umap/tests/integration/test_basics.py +1 -1
  107. umap/tests/integration/test_browser.py +69 -7
  108. umap/tests/integration/test_caption.py +3 -3
  109. umap/tests/integration/test_circles_layer.py +12 -0
  110. umap/tests/integration/test_datalayer.py +2 -1
  111. umap/tests/integration/test_draw_polygon.py +17 -9
  112. umap/tests/integration/test_draw_polyline.py +12 -8
  113. umap/tests/integration/test_edit_datalayer.py +5 -8
  114. umap/tests/integration/test_edit_map.py +2 -2
  115. umap/tests/integration/test_edit_marker.py +1 -1
  116. umap/tests/integration/test_facets_browser.py +3 -3
  117. umap/tests/integration/test_import.py +1 -0
  118. umap/tests/integration/test_map.py +1 -0
  119. umap/tests/integration/test_owned_map.py +1 -1
  120. umap/tests/integration/test_view_marker.py +63 -0
  121. umap/tests/integration/test_view_polygon.py +12 -12
  122. umap/tests/integration/test_websocket_sync.py +65 -3
  123. umap/tests/test_clean_tilelayer.py +83 -0
  124. umap/tests/test_datalayer.py +24 -0
  125. umap/tests/test_map_views.py +20 -0
  126. umap/tests/test_purge_purgatory.py +25 -0
  127. umap/tests/test_websocket_server.py +22 -0
  128. umap/urls.py +5 -1
  129. umap/views.py +6 -3
  130. umap/websocket_server.py +130 -27
  131. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/METADATA +18 -14
  132. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/RECORD +135 -127
  133. umap/static/umap/vendors/contextmenu/leaflet.contextmenu.min.css +0 -1
  134. umap/static/umap/vendors/contextmenu/leaflet.contextmenu.min.js +0 -7
  135. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/WHEEL +0 -0
  136. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/entry_points.txt +0 -0
  137. {umap_project-2.6.3.dist-info → umap_project-2.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -58,6 +58,7 @@ U.Map = L.Map.extend({
58
58
  this.panel = new U.Panel(this)
59
59
  this.dialog = new U.Dialog({ className: 'dark' })
60
60
  this.tooltip = new U.Tooltip(this._controlContainer)
61
+ this.contextmenu = new U.ContextMenu()
61
62
  if (this.hasEditMode()) {
62
63
  this.editPanel = new U.EditPanel(this)
63
64
  this.fullPanel = new U.FullPanel(this)
@@ -109,10 +110,9 @@ U.Map = L.Map.extend({
109
110
  delete this.options.advancedFilterKey
110
111
  }
111
112
 
112
- // Global storage for retrieving datalayers and features
113
- this.datalayers = {}
114
- this.datalayers_index = []
115
- this.dirty_datalayers = []
113
+ // Global storage for retrieving datalayers and features.
114
+ this.datalayers = {} // All datalayers, including deleted.
115
+ this.datalayers_index = [] // Datalayers actually on the map and ordered.
116
116
  this.features_index = {}
117
117
 
118
118
  // Needed for actions labels
@@ -191,14 +191,17 @@ U.Map = L.Map.extend({
191
191
  this.renderEditToolbar()
192
192
  }
193
193
 
194
- this.initShortcuts()
195
- if (!this.options.noControl) this.initCaptionBar()
196
- this.onceDataLoaded(this.setViewFromQueryString)
194
+ if (!this.options.noControl) {
195
+ this.initShortcuts()
196
+ this.initCaptionBar()
197
+ this.on('contextmenu', this.onContextMenu)
198
+ this.onceDataLoaded(this.setViewFromQueryString)
199
+ this.on('click', this.closeInplaceToolbar)
200
+ this.propagate()
201
+ }
197
202
 
198
203
  window.onbeforeunload = () => (this.editEnabled && this.isDirty) || null
199
204
  this.backup()
200
- this.initContextMenu()
201
- this.on('click', this.closeInplaceToolbar)
202
205
  },
203
206
 
204
207
  initSyncEngine: async function () {
@@ -221,8 +224,12 @@ U.Map = L.Map.extend({
221
224
  },
222
225
 
223
226
  render: function (fields) {
224
- const impacts = U.Utils.getImpactsFromSchema(fields)
227
+ if (fields.includes('numberOfConnectedPeers')) {
228
+ this.renderEditToolbar()
229
+ this.propagate()
230
+ }
225
231
 
232
+ const impacts = U.Utils.getImpactsFromSchema(fields)
226
233
  for (const impact of impacts) {
227
234
  switch (impact) {
228
235
  case 'ui':
@@ -230,6 +237,7 @@ U.Map = L.Map.extend({
230
237
  this.renderEditToolbar()
231
238
  this.renderControls()
232
239
  this.browser.redraw()
240
+ this.propagate()
233
241
  break
234
242
  case 'data':
235
243
  this.redrawVisibleDataLayers()
@@ -486,7 +494,7 @@ U.Map = L.Map.extend({
486
494
  loadDataLayers: async function () {
487
495
  this.datalayersLoaded = true
488
496
  this.fire('datalayersloaded')
489
- for (const datalayer of Object.values(this.datalayers)) {
497
+ for (const datalayer of this.datalayers_index) {
490
498
  if (datalayer.showAtLoad()) await datalayer.show()
491
499
  }
492
500
  this.dataloaded = true
@@ -724,6 +732,10 @@ U.Map = L.Map.extend({
724
732
  }
725
733
  },
726
734
 
735
+ hasLayers: function () {
736
+ return Boolean(this.datalayers_index.length)
737
+ },
738
+
727
739
  fitDataBounds: function () {
728
740
  const bounds = this.getLayersBounds()
729
741
  if (!this.hasData() || !bounds.isValid()) return false
@@ -928,6 +940,7 @@ U.Map = L.Map.extend({
928
940
  if (mustReindex) datalayer.reindex()
929
941
  datalayer.redraw()
930
942
  })
943
+ this.propagate()
931
944
  this.fire('postsync')
932
945
  this.isDirty = true
933
946
  },
@@ -991,12 +1004,12 @@ U.Map = L.Map.extend({
991
1004
  if (this.editTools) this.editTools.stopDrawing()
992
1005
  this.resetOptions()
993
1006
  this.datalayers_index = [].concat(this._datalayers_index_bk)
994
- this.dirty_datalayers.slice().forEach((datalayer) => {
1007
+ // Iter over all datalayers, including deleted if any.
1008
+ for (const datalayer of Object.values(this.datalayers)) {
995
1009
  if (datalayer.isDeleted) datalayer.connectToMap()
996
- datalayer.reset()
997
- })
1010
+ if (datalayer.isDirty) datalayer.reset()
1011
+ }
998
1012
  this.ensurePanesOrder()
999
- this.dirty_datalayers = []
1000
1013
  this.initTileLayers()
1001
1014
  this.isDirty = false
1002
1015
  this.onDataLayersChanged()
@@ -1006,25 +1019,6 @@ U.Map = L.Map.extend({
1006
1019
  this._container.classList.toggle('umap-is-dirty', this.isDirty)
1007
1020
  },
1008
1021
 
1009
- addDirtyDatalayer: function (datalayer) {
1010
- if (this.dirty_datalayers.indexOf(datalayer) === -1) {
1011
- this.dirty_datalayers.push(datalayer)
1012
- this.isDirty = true
1013
- }
1014
- },
1015
-
1016
- removeDirtyDatalayer: function (datalayer) {
1017
- if (this.dirty_datalayers.indexOf(datalayer) !== -1) {
1018
- this.dirty_datalayers.splice(this.dirty_datalayers.indexOf(datalayer), 1)
1019
- this.checkDirty()
1020
- }
1021
- },
1022
-
1023
- continueSaving: function () {
1024
- if (this.dirty_datalayers.length) this.dirty_datalayers[0].save()
1025
- else this.fire('saved')
1026
- },
1027
-
1028
1022
  exportOptions: function () {
1029
1023
  const properties = {}
1030
1024
  for (const option of Object.keys(U.SCHEMA)) {
@@ -1054,19 +1048,16 @@ U.Map = L.Map.extend({
1054
1048
  return
1055
1049
  }
1056
1050
  if (data.login_required) {
1057
- window.onLogin = () => this.saveSelf()
1051
+ window.onLogin = () => this.save()
1058
1052
  window.open(data.login_required)
1059
1053
  return
1060
1054
  }
1061
- if (data.user?.id) {
1062
- this.options.user = data.user
1063
- this.renderEditToolbar()
1064
- }
1055
+ this.options.user = data.user
1065
1056
  if (!this.options.umap_id) {
1066
1057
  this.options.umap_id = data.id
1067
1058
  this.permissions.setOptions(data.permissions)
1068
1059
  this.permissions.commit()
1069
- if (data?.permissions?.anonymous_edit_url) {
1060
+ if (data.permissions?.anonymous_edit_url) {
1070
1061
  this.once('saved', () => {
1071
1062
  U.AlertCreation.info(
1072
1063
  L._('Your map has been created with an anonymous account!'),
@@ -1099,21 +1090,44 @@ U.Map = L.Map.extend({
1099
1090
  } else {
1100
1091
  window.location = data.url
1101
1092
  }
1102
- this.permissions.save()
1093
+ return true
1103
1094
  },
1104
1095
 
1105
- save: function () {
1096
+ save: async function () {
1106
1097
  if (!this.isDirty) return
1107
1098
  if (this._default_extent) this._setCenterAndZoom()
1108
1099
  this.backup()
1109
- this.once('saved', () => {
1110
- this.isDirty = false
1111
- })
1112
1100
  if (this.options.editMode === 'advanced') {
1113
1101
  // Only save the map if the user has the rights to do so.
1114
- this.saveSelf()
1115
- } else {
1116
- this.permissions.save()
1102
+ const ok = await this.saveSelf()
1103
+ if (!ok) return
1104
+ }
1105
+ await this.permissions.save()
1106
+ // Iter over all datalayers, including deleted.
1107
+ for (const datalayer of Object.values(this.datalayers)) {
1108
+ if (datalayer.isDirty) await datalayer.save()
1109
+ }
1110
+ this.isDirty = false
1111
+ // Do a blind render for now, as we are not sure what could
1112
+ // have changed, we'll be more subtil when we'll remove the
1113
+ // save action
1114
+ this.render(['name', 'user', 'permissions'])
1115
+ this.fire('saved')
1116
+ },
1117
+
1118
+ propagate: function () {
1119
+ let els = document.querySelectorAll('.map-name')
1120
+ for (const el of els) {
1121
+ el.textContent = this.getDisplayName()
1122
+ }
1123
+ const status = this.permissions.getShareStatusDisplay()
1124
+ els = document.querySelectorAll('.share-status')
1125
+ for (const el of els) {
1126
+ if (status) {
1127
+ el.textContent = L._('Visibility: {status}', {
1128
+ status: status,
1129
+ })
1130
+ }
1117
1131
  }
1118
1132
  },
1119
1133
 
@@ -1585,7 +1599,7 @@ U.Map = L.Map.extend({
1585
1599
  'umap-caption-bar',
1586
1600
  this._controlContainer
1587
1601
  )
1588
- const name = L.DomUtil.create('h3', '', container)
1602
+ const name = L.DomUtil.create('h3', 'map-name', container)
1589
1603
  L.DomEvent.disableClickPropagation(container)
1590
1604
  this.addAuthorLink('span', container)
1591
1605
  if (this.getOption('captionMenus')) {
@@ -1611,11 +1625,6 @@ U.Map = L.Map.extend({
1611
1625
  )
1612
1626
  }
1613
1627
  }
1614
- const setName = function () {
1615
- name.textContent = this.getDisplayName()
1616
- }
1617
- L.bind(setName, this)()
1618
- this.on('postsync', L.bind(setName, this))
1619
1628
  this.onceDatalayersLoaded(function () {
1620
1629
  this.slideshow.renderToolbox(container)
1621
1630
  })
@@ -1653,13 +1662,13 @@ U.Map = L.Map.extend({
1653
1662
  },
1654
1663
 
1655
1664
  clone: async function () {
1656
- if (
1657
- confirm(L._('Are you sure you want to clone this map and all its datalayers?'))
1658
- ) {
1659
- const url = this.urls.get('map_clone', { map_id: this.options.umap_id })
1660
- const [data, response, error] = await this.server.post(url)
1661
- if (data.redirect) window.location = data.redirect
1662
- }
1665
+ this.dialog
1666
+ .confirm(L._('Are you sure you want to clone this map and all its datalayers?'))
1667
+ .then(async () => {
1668
+ const url = this.urls.get('map_clone', { map_id: this.options.umap_id })
1669
+ const [data, response, error] = await this.server.post(url)
1670
+ if (data.redirect) window.location = data.redirect
1671
+ })
1663
1672
  },
1664
1673
 
1665
1674
  removeDataLayers: function () {
@@ -1679,118 +1688,100 @@ U.Map = L.Map.extend({
1679
1688
  this.loader.onAdd(this)
1680
1689
  },
1681
1690
 
1682
- initContextMenu: function () {
1683
- this.contextmenu = new U.ContextMenu(this)
1684
- this.contextmenu.enable()
1685
- },
1686
-
1687
- setContextMenuItems: function (e) {
1688
- let items = []
1689
- if (this._zoom !== this.getMaxZoom()) {
1690
- items.push({
1691
- text: L._('Zoom in'),
1692
- callback: function () {
1693
- this.zoomIn()
1694
- },
1695
- })
1696
- }
1697
- if (this._zoom !== this.getMinZoom()) {
1698
- items.push({
1699
- text: L._('Zoom out'),
1700
- callback: function () {
1701
- this.zoomOut()
1702
- },
1703
- })
1704
- }
1705
- if (e?.relatedTarget) {
1706
- if (e.relatedTarget.getContextMenuItems) {
1707
- items = items.concat(e.relatedTarget.getContextMenuItems(e))
1708
- }
1709
- }
1691
+ getOwnContextMenuItems: function (event) {
1692
+ const items = []
1710
1693
  if (this.hasEditMode()) {
1711
- items.push('-')
1712
1694
  if (this.editEnabled) {
1713
1695
  if (!this.isDirty) {
1714
1696
  items.push({
1715
- text: this.help.displayLabel('STOP_EDIT'),
1716
- callback: this.disableEdit,
1697
+ label: this.help.displayLabel('STOP_EDIT'),
1698
+ action: () => this.disableEdit(),
1717
1699
  })
1718
1700
  }
1719
1701
  if (this.options.enableMarkerDraw) {
1720
1702
  items.push({
1721
- text: this.help.displayLabel('DRAW_MARKER'),
1722
- callback: this.startMarker,
1723
- context: this,
1703
+ label: this.help.displayLabel('DRAW_MARKER'),
1704
+ action: () => this.startMarker(event),
1724
1705
  })
1725
1706
  }
1726
1707
  if (this.options.enablePolylineDraw) {
1727
1708
  items.push({
1728
- text: this.help.displayLabel('DRAW_POLYGON'),
1729
- callback: this.startPolygon,
1730
- context: this,
1709
+ label: this.help.displayLabel('DRAW_POLYGON'),
1710
+ action: () => this.startPolygon(event),
1731
1711
  })
1732
1712
  }
1733
1713
  if (this.options.enablePolygonDraw) {
1734
1714
  items.push({
1735
- text: this.help.displayLabel('DRAW_LINE'),
1736
- callback: this.startPolyline,
1737
- context: this,
1715
+ label: this.help.displayLabel('DRAW_LINE'),
1716
+ action: () => this.startPolyline(event),
1738
1717
  })
1739
1718
  }
1740
1719
  items.push('-')
1741
1720
  items.push({
1742
- text: L._('Help'),
1743
- callback: function () {
1744
- this.help.show('edit')
1745
- },
1721
+ label: L._('Help'),
1722
+ action: () => this.help.show('edit'),
1746
1723
  })
1747
1724
  } else {
1748
1725
  items.push({
1749
- text: this.help.displayLabel('TOGGLE_EDIT'),
1750
- callback: this.enableEdit,
1726
+ label: this.help.displayLabel('TOGGLE_EDIT'),
1727
+ action: () => this.enableEdit(),
1751
1728
  })
1752
1729
  }
1753
1730
  }
1731
+ if (items.length) {
1732
+ items.push('-')
1733
+ }
1754
1734
  items.push(
1755
- '-',
1756
1735
  {
1757
- text: L._('Open browser'),
1758
- callback: () => this.openBrowser('layers'),
1736
+ label: L._('Open browser'),
1737
+ action: () => this.openBrowser('layers'),
1759
1738
  },
1760
1739
  {
1761
- text: L._('Browse data'),
1762
- callback: () => this.openBrowser('data'),
1740
+ label: L._('Browse data'),
1741
+ action: () => this.openBrowser('data'),
1763
1742
  }
1764
1743
  )
1765
1744
  if (this.options.facetKey) {
1766
1745
  items.push({
1767
- text: L._('Filter data'),
1768
- callback: () => this.openBrowser('filters'),
1746
+ label: L._('Filter data'),
1747
+ action: () => this.openBrowser('filters'),
1769
1748
  })
1770
1749
  }
1771
1750
  items.push(
1772
1751
  {
1773
- text: L._('Open caption'),
1774
- callback: this.openCaption,
1752
+ label: L._('Open caption'),
1753
+ action: () => this.openCaption(),
1775
1754
  },
1776
1755
  {
1777
- text: this.help.displayLabel('SEARCH'),
1778
- callback: this.search,
1756
+ label: this.help.displayLabel('SEARCH'),
1757
+ action: () => this.search(),
1779
1758
  }
1780
1759
  )
1760
+ return items
1761
+ },
1762
+
1763
+ getContextMenuItems: function (event) {
1764
+ const items = []
1781
1765
  if (this.options.urls.routing) {
1782
1766
  items.push('-', {
1783
- text: L._('Directions from here'),
1784
- callback: this.openExternalRouting,
1767
+ label: L._('Directions from here'),
1768
+ action: () => this.openExternalRouting(event),
1785
1769
  })
1786
1770
  }
1787
1771
  if (this.options.urls.edit_in_osm) {
1788
1772
  items.push('-', {
1789
- text: L._('Edit in OpenStreetMap'),
1790
- callback: this.editInOSM,
1773
+ label: L._('Edit in OpenStreetMap'),
1774
+ action: () => this.editInOSM(event),
1791
1775
  })
1792
1776
  }
1793
- this.options.contextmenuItems = items
1777
+ return items
1778
+ },
1779
+
1780
+ onContextMenu: function (event) {
1781
+ const items = this.getOwnContextMenuItems(event).concat(
1782
+ this.getContextMenuItems(event)
1783
+ )
1784
+ this.contextmenu.open(event.originalEvent, items)
1794
1785
  },
1795
1786
 
1796
1787
  editInOSM: function (e) {
@@ -1850,7 +1841,7 @@ U.Map = L.Map.extend({
1850
1841
 
1851
1842
  getFeatureById: function (id) {
1852
1843
  let feature
1853
- for (const datalayer of Object.values(this.datalayers)) {
1844
+ for (const datalayer of this.datalayers_index) {
1854
1845
  feature = datalayer.getFeatureById(id)
1855
1846
  if (feature) return feature
1856
1847
  }
@@ -1,6 +1,6 @@
1
1
  const locale = {
2
- "(area: {measure})": "(gorread: {measure})",
3
- "(length: {measure})": "(pellder: {measure})",
2
+ "(area: {measure})": "(area: {measure})",
3
+ "(length: {measure})": "(length: {measure})",
4
4
  "# one hash for main heading": "# un diezenn evit an titl pennañ",
5
5
  "## two hashes for second heading": "## div ziezenn evit an eil titl",
6
6
  "### three hashes for third heading": "### teir diezenn evit an trede titl",
@@ -477,7 +477,6 @@ const locale = {
477
477
  "Search area": "Search area",
478
478
  "Type area name, or let empty to load data in current map view": "Type area name, or let empty to load data in current map view",
479
479
  "Data successfully imported!": "Roadennoù enporzhiet gant berzh!",
480
- "My Dashboard ({username})": "Ma Zaolenn-vourzh ({username})",
481
480
  "Clear data": "Skarzhañ ar roadennoù",
482
481
  "Remove layers": "Lemel ar gwiskadoù",
483
482
  "Categorized": "Dre rummad",
@@ -504,7 +503,17 @@ const locale = {
504
503
  "Property name to compute circles": "Property name to compute circles",
505
504
  "Min circle radius": "Min circle radius",
506
505
  "Max circle radius": "Max circle radius",
507
- "Display the open browser control": "Display the open browser control"
506
+ "Display the open browser control": "Display the open browser control",
507
+ "Copy as GeoJSON": "Copy as GeoJSON",
508
+ "Please zoom in to edit the geometry": "Please zoom in to edit the geometry",
509
+ "New map": "New map",
510
+ "My maps": "My maps",
511
+ "My teams": "My teams",
512
+ "My profile": "My profile",
513
+ "Type new owner's username": "Type new owner's username",
514
+ "Type editor's username": "Type editor's username",
515
+ "Map": "Map",
516
+ "Manage collaborators": "Manage collaborators"
508
517
  }
509
518
  L.registerLocale("br", locale)
510
519
  L.setLocale("br")
@@ -1,6 +1,6 @@
1
1
  {
2
- "(area: {measure})": "(gorread: {measure})",
3
- "(length: {measure})": "(pellder: {measure})",
2
+ "(area: {measure})": "(area: {measure})",
3
+ "(length: {measure})": "(length: {measure})",
4
4
  "# one hash for main heading": "# un diezenn evit an titl pennañ",
5
5
  "## two hashes for second heading": "## div ziezenn evit an eil titl",
6
6
  "### three hashes for third heading": "### teir diezenn evit an trede titl",
@@ -477,7 +477,6 @@
477
477
  "Search area": "Search area",
478
478
  "Type area name, or let empty to load data in current map view": "Type area name, or let empty to load data in current map view",
479
479
  "Data successfully imported!": "Roadennoù enporzhiet gant berzh!",
480
- "My Dashboard ({username})": "Ma Zaolenn-vourzh ({username})",
481
480
  "Clear data": "Skarzhañ ar roadennoù",
482
481
  "Remove layers": "Lemel ar gwiskadoù",
483
482
  "Categorized": "Dre rummad",
@@ -504,5 +503,15 @@
504
503
  "Property name to compute circles": "Property name to compute circles",
505
504
  "Min circle radius": "Min circle radius",
506
505
  "Max circle radius": "Max circle radius",
507
- "Display the open browser control": "Display the open browser control"
506
+ "Display the open browser control": "Display the open browser control",
507
+ "Copy as GeoJSON": "Copy as GeoJSON",
508
+ "Please zoom in to edit the geometry": "Please zoom in to edit the geometry",
509
+ "New map": "New map",
510
+ "My maps": "My maps",
511
+ "My teams": "My teams",
512
+ "My profile": "My profile",
513
+ "Type new owner's username": "Type new owner's username",
514
+ "Type editor's username": "Type editor's username",
515
+ "Map": "Map",
516
+ "Manage collaborators": "Manage collaborators"
508
517
  }
@@ -38,7 +38,7 @@ const locale = {
38
38
  "Attach the map to my account": "Adjunta el mapa al meu compte",
39
39
  "attribution": "atribució",
40
40
  "Auto": "Auto",
41
- "Automatic": "Automatic",
41
+ "Automatic": "Automàtic",
42
42
  "Autostart when map is loaded": "Autostart when map is loaded",
43
43
  "Back to preview": "Tornar a la vista prèvia",
44
44
  "Background overlay url": "URL de superposició del fons",
@@ -102,7 +102,7 @@ const locale = {
102
102
  "Define link to open in a new window on polygon click.": "Define link to open in a new window on polygon click.",
103
103
  "define": "definir",
104
104
  "Delay between two transitions when in play mode": "Delay between two transitions when in play mode",
105
- "Delete layer": "Delete layer",
105
+ "Delete layer": "Suprimeix la capa",
106
106
  "Delete this feature": "Suprimeix aquesta característica",
107
107
  "Delete this shape": "Delete this shape",
108
108
  "Delete this vertex (Alt+Click)": "Delete this vertex (Alt+Click)",
@@ -206,7 +206,7 @@ const locale = {
206
206
  "km": "km",
207
207
  "Label direction": "Direcció de l'etiqueta",
208
208
  "Label key": "Clau d'etiqueta",
209
- "Labels are clickable": "Labels are clickable",
209
+ "Labels are clickable": "Les etiquetes es poden fer clic",
210
210
  "Latest feature": "Darrera característica",
211
211
  "Latitude": "Latitud",
212
212
  "Layer properties": "Layer properties",
@@ -255,15 +255,15 @@ const locale = {
255
255
  "No.": "No.",
256
256
  "None": "Cap",
257
257
  "Number of desired classes (default 5)": "Number of desired classes (default 5)",
258
- "On the bottom": "On the bottom",
259
- "On the left": "On the left",
260
- "On the right": "On the right",
261
- "On the top": "On the top",
258
+ "On the bottom": "A la part inferior",
259
+ "On the left": "A l'esquerra",
260
+ "On the right": "A la dreta",
261
+ "On the top": "a la part superior",
262
262
  "Only visible layers' data": "Només les dades de les capes visibles",
263
263
  "opacity": "opacitat",
264
264
  "Opacity": "Opacitat",
265
265
  "Open current feature on load": "Obrir el element actual en càrregar",
266
- "Open link in…": "Open link in…",
266
+ "Open link in…": "Obriu l'enllaç a…",
267
267
  "Open share & download panel": "Open share & download panel",
268
268
  "Open this map extent in a map editor to provide more accurate data to OpenStreetMap": "Open this map extent in a map editor to provide more accurate data to OpenStreetMap",
269
269
  "OpenStreetMap": "OpenStreetMap",
@@ -319,7 +319,7 @@ const locale = {
319
319
  "Short link": "Enllaç curt",
320
320
  "Show this layer in the caption": "Show this layer in the caption",
321
321
  "Show/hide layer": "Mostra/amaga la capa",
322
- "Side panel": "Side panel",
322
+ "Side panel": "panell lateral",
323
323
  "Simple link: [[http://example.com]]": "Enllaç simple: [[http://exemple.com]]",
324
324
  "Simplify": "Simplificar",
325
325
  "Skipping unknown geometry.type: {type}": "S'està ometent el tipus de geometria desconegut: {type}",
@@ -340,7 +340,7 @@ const locale = {
340
340
  "Text color for the cluster label": "Text color for the cluster label",
341
341
  "Text formatting": "Format del text",
342
342
  "The name of the property to use as feature label (eg.: \"nom\"). You can also use properties inside brackets to use more than one or mix with static content (eg.: \"{name} in {place}\")": "El nom de la propietat que s'utilitzarà com a etiqueta de característica (p. ex.: \"nom\"). També podeu utilitzar propietats entre claudàtors per utilitzar-ne més d'una o barrejar-les amb contingut estàtic (p. ex.: \"{name} in {place}\")",
343
- "The name of the property to use as feature unique identifier.": "The name of the property to use as feature unique identifier.",
343
+ "The name of the property to use as feature unique identifier.": "El nom de la propietat que s'utilitzarà com a identificador únic de la característica",
344
344
  "The zoom and center have been modified.": "L'escala i el centre s'han modificat.",
345
345
  "TMS format": "Format TMS",
346
346
  "To use if remote server doesn't allow cross domain (slower)": "To use if remote server doesn't allow cross domain (slower)",
@@ -422,7 +422,7 @@ const locale = {
422
422
  "Comma separated list of properties to use when filtering features by text input": "Comma separated list of properties to use when filtering features by text input",
423
423
  "Comma separated list of properties to use for filters (eg.: mykey,otherkey). To control label, add it after a | (eg.: mykey|My Key,otherkey|Other Key). To control input field type, add it after another | (eg.: mykey|My Key|checkbox,otherkey|Other Key|datetime). Allowed values for the input field type are checkbox (default), radio, number, date and datetime.": "Comma separated list of properties to use for filters (eg.: mykey,otherkey). To control label, add it after a | (eg.: mykey|My Key,otherkey|Other Key). To control input field type, add it after another | (eg.: mykey|My Key|checkbox,otherkey|Other Key|datetime). Allowed values for the input field type are checkbox (default), radio, number, date and datetime.",
424
424
  "Search keys": "Claus de cerca",
425
- "Filters keys": "Filters keys",
425
+ "Filters keys": "Claus de filtres",
426
426
  "Filter data": "Filter data",
427
427
  "Search map features…": "Buscar elements del mapa…",
428
428
  "Reset all": "Restablir tot",
@@ -456,8 +456,8 @@ const locale = {
456
456
  "key=value or key!=value": "key=value or key!=value",
457
457
  "Are you sure you want to delete this rule?": "Are you sure you want to delete this rule?",
458
458
  "empty rule": "empty rule",
459
- "Conditional style rules": "Conditional style rules",
460
- "Add rule": "Add rule",
459
+ "Conditional style rules": "Regles d'estil condicional",
460
+ "Add rule": "Afegeix una regla",
461
461
  "Browser: data": "Navegador: dades",
462
462
  "Browser: layers": "Navegador: capes",
463
463
  "Browser: filters": "Navegador: filtres",
@@ -477,7 +477,6 @@ const locale = {
477
477
  "Search area": "Search area",
478
478
  "Type area name, or let empty to load data in current map view": "Type area name, or let empty to load data in current map view",
479
479
  "Data successfully imported!": "Data successfully imported!",
480
- "My Dashboard ({username})": "El meu Tauler de control ({username})",
481
480
  "Clear data": "Clear data",
482
481
  "Remove layers": "Remove layers",
483
482
  "Categorized": "Categorized",
@@ -504,7 +503,21 @@ const locale = {
504
503
  "Property name to compute circles": "Property name to compute circles",
505
504
  "Min circle radius": "Min circle radius",
506
505
  "Max circle radius": "Max circle radius",
507
- "Display the open browser control": "Display the open browser control"
506
+ "Display the open browser control": "Display the open browser control",
507
+ "Copy as GeoJSON": "Copy as GeoJSON",
508
+ "Please zoom in to edit the geometry": "Please zoom in to edit the geometry",
509
+ "New map": "New map",
510
+ "My maps": "My maps",
511
+ "My teams": "My teams",
512
+ "My profile": "My profile",
513
+ "Type new owner's username": "Type new owner's username",
514
+ "Type editor's username": "Type editor's username",
515
+ "Map": "Map",
516
+ "Manage collaborators": "Manage collaborators",
517
+ "show/hide all layers": "show/hide all layers",
518
+ "zoom to data extent": "zoom to data extent",
519
+ "download visible data": "download visible data",
520
+ "{connectedPeers} peer(s) currently connected to this map": "{connectedPeers} peer(s) currently connected to this map"
508
521
  }
509
522
  L.registerLocale("ca", locale)
510
523
  L.setLocale("ca")