umap-project 2.1.3__py3-none-any.whl → 2.2.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 (200) hide show
  1. umap/__init__.py +1 -1
  2. umap/context_processors.py +1 -0
  3. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/en/LC_MESSAGES/django.po +32 -32
  5. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  8. umap/migrations/0020_alter_tilelayer_url_template.py +19 -0
  9. umap/migrations/0021_remove_map_description.py +16 -0
  10. umap/models.py +8 -6
  11. umap/settings/base.py +1 -0
  12. umap/static/umap/base.css +43 -156
  13. umap/static/umap/content.css +7 -25
  14. umap/static/umap/css/icon.css +112 -0
  15. umap/static/umap/css/panel.css +140 -0
  16. umap/static/umap/img/16-white.svg +5 -1
  17. umap/static/umap/img/16.svg +7 -4
  18. umap/static/umap/img/24-white.svg +3 -1
  19. umap/static/umap/img/24.svg +3 -4
  20. umap/static/umap/img/source/16-white.svg +176 -940
  21. umap/static/umap/img/source/16.svg +8 -5
  22. umap/static/umap/img/source/24-white.svg +5 -3
  23. umap/static/umap/img/source/24.svg +6 -7
  24. umap/static/umap/js/modules/browser.js +97 -73
  25. umap/static/umap/js/modules/dompurify.js +12 -0
  26. umap/static/umap/js/modules/facets.js +149 -0
  27. umap/static/umap/js/modules/global.js +9 -1
  28. umap/static/umap/js/modules/i18n.js +7 -0
  29. umap/static/umap/js/modules/orderable.js +84 -0
  30. umap/static/umap/js/modules/panel.js +76 -0
  31. umap/static/umap/js/modules/request.js +0 -1
  32. umap/static/umap/js/modules/schema.js +324 -223
  33. umap/static/umap/js/modules/urls.js +1 -16
  34. umap/static/umap/js/modules/utils.js +340 -0
  35. umap/static/umap/js/umap.autocomplete.js +40 -25
  36. umap/static/umap/js/umap.controls.js +227 -369
  37. umap/static/umap/js/umap.core.js +77 -366
  38. umap/static/umap/js/umap.datalayer.permissions.js +1 -1
  39. umap/static/umap/js/umap.features.js +62 -42
  40. umap/static/umap/js/umap.forms.js +128 -36
  41. umap/static/umap/js/umap.icon.js +11 -4
  42. umap/static/umap/js/umap.importer.js +78 -57
  43. umap/static/umap/js/umap.js +179 -156
  44. umap/static/umap/js/umap.layer.js +79 -40
  45. umap/static/umap/js/umap.permissions.js +13 -9
  46. umap/static/umap/js/umap.popup.js +26 -30
  47. umap/static/umap/js/umap.share.js +12 -9
  48. umap/static/umap/js/umap.tableeditor.js +4 -6
  49. umap/static/umap/js/umap.ui.js +10 -60
  50. umap/static/umap/locale/am_ET.js +243 -227
  51. umap/static/umap/locale/am_ET.json +21 -9
  52. umap/static/umap/locale/ar.js +243 -227
  53. umap/static/umap/locale/ar.json +21 -9
  54. umap/static/umap/locale/ast.js +243 -227
  55. umap/static/umap/locale/ast.json +21 -9
  56. umap/static/umap/locale/bg.js +243 -227
  57. umap/static/umap/locale/bg.json +21 -9
  58. umap/static/umap/locale/br.js +253 -237
  59. umap/static/umap/locale/br.json +25 -13
  60. umap/static/umap/locale/ca.js +243 -227
  61. umap/static/umap/locale/ca.json +21 -9
  62. umap/static/umap/locale/cs_CZ.js +243 -227
  63. umap/static/umap/locale/cs_CZ.json +21 -9
  64. umap/static/umap/locale/da.js +243 -227
  65. umap/static/umap/locale/da.json +21 -9
  66. umap/static/umap/locale/de.js +243 -227
  67. umap/static/umap/locale/de.json +21 -9
  68. umap/static/umap/locale/el.js +243 -227
  69. umap/static/umap/locale/el.json +21 -9
  70. umap/static/umap/locale/en.js +243 -234
  71. umap/static/umap/locale/en.json +22 -10
  72. umap/static/umap/locale/en_US.json +21 -9
  73. umap/static/umap/locale/es.js +243 -227
  74. umap/static/umap/locale/es.json +21 -9
  75. umap/static/umap/locale/et.js +243 -227
  76. umap/static/umap/locale/et.json +21 -9
  77. umap/static/umap/locale/eu.js +227 -199
  78. umap/static/umap/locale/eu.json +1 -1
  79. umap/static/umap/locale/fa_IR.js +243 -227
  80. umap/static/umap/locale/fa_IR.json +21 -9
  81. umap/static/umap/locale/fi.js +243 -227
  82. umap/static/umap/locale/fi.json +21 -9
  83. umap/static/umap/locale/fr.js +243 -234
  84. umap/static/umap/locale/fr.json +21 -9
  85. umap/static/umap/locale/gl.js +243 -227
  86. umap/static/umap/locale/gl.json +21 -9
  87. umap/static/umap/locale/he.js +243 -227
  88. umap/static/umap/locale/he.json +21 -9
  89. umap/static/umap/locale/hr.js +243 -227
  90. umap/static/umap/locale/hr.json +21 -9
  91. umap/static/umap/locale/hu.js +243 -234
  92. umap/static/umap/locale/hu.json +21 -9
  93. umap/static/umap/locale/id.js +243 -227
  94. umap/static/umap/locale/id.json +21 -9
  95. umap/static/umap/locale/is.js +243 -227
  96. umap/static/umap/locale/is.json +21 -9
  97. umap/static/umap/locale/it.js +243 -234
  98. umap/static/umap/locale/it.json +21 -9
  99. umap/static/umap/locale/ja.js +243 -227
  100. umap/static/umap/locale/ja.json +21 -9
  101. umap/static/umap/locale/ko.js +243 -227
  102. umap/static/umap/locale/ko.json +21 -9
  103. umap/static/umap/locale/lt.js +243 -227
  104. umap/static/umap/locale/lt.json +21 -9
  105. umap/static/umap/locale/ms.js +243 -234
  106. umap/static/umap/locale/ms.json +22 -10
  107. umap/static/umap/locale/nl.js +246 -230
  108. umap/static/umap/locale/nl.json +21 -9
  109. umap/static/umap/locale/no.js +243 -227
  110. umap/static/umap/locale/no.json +21 -9
  111. umap/static/umap/locale/pl.js +243 -227
  112. umap/static/umap/locale/pl.json +21 -9
  113. umap/static/umap/locale/pl_PL.json +21 -9
  114. umap/static/umap/locale/pt.js +243 -227
  115. umap/static/umap/locale/pt.json +21 -9
  116. umap/static/umap/locale/pt_BR.js +243 -227
  117. umap/static/umap/locale/pt_BR.json +21 -9
  118. umap/static/umap/locale/pt_PT.js +243 -227
  119. umap/static/umap/locale/pt_PT.json +21 -9
  120. umap/static/umap/locale/ro.js +243 -227
  121. umap/static/umap/locale/ro.json +21 -9
  122. umap/static/umap/locale/ru.js +243 -227
  123. umap/static/umap/locale/ru.json +21 -9
  124. umap/static/umap/locale/si.js +1 -1
  125. umap/static/umap/locale/si.json +1 -1
  126. umap/static/umap/locale/sk_SK.js +243 -227
  127. umap/static/umap/locale/sk_SK.json +21 -9
  128. umap/static/umap/locale/sl.js +243 -227
  129. umap/static/umap/locale/sl.json +21 -9
  130. umap/static/umap/locale/sr.js +243 -227
  131. umap/static/umap/locale/sr.json +21 -9
  132. umap/static/umap/locale/sv.js +243 -227
  133. umap/static/umap/locale/sv.json +21 -9
  134. umap/static/umap/locale/th_TH.js +243 -227
  135. umap/static/umap/locale/th_TH.json +21 -9
  136. umap/static/umap/locale/tr.js +243 -227
  137. umap/static/umap/locale/tr.json +21 -9
  138. umap/static/umap/locale/uk_UA.js +243 -227
  139. umap/static/umap/locale/uk_UA.json +21 -9
  140. umap/static/umap/locale/vi.js +243 -227
  141. umap/static/umap/locale/vi.json +21 -9
  142. umap/static/umap/locale/vi_VN.json +21 -9
  143. umap/static/umap/locale/zh.js +243 -227
  144. umap/static/umap/locale/zh.json +21 -9
  145. umap/static/umap/locale/zh_CN.json +21 -9
  146. umap/static/umap/locale/zh_TW.Big5.json +21 -9
  147. umap/static/umap/locale/zh_TW.js +243 -234
  148. umap/static/umap/locale/zh_TW.json +21 -9
  149. umap/static/umap/map.css +124 -264
  150. umap/static/umap/test/DataLayer.js +463 -0
  151. umap/static/umap/test/Feature.js +0 -226
  152. umap/static/umap/test/TableEditor.js +104 -0
  153. umap/static/umap/test/Util.js +0 -521
  154. umap/static/umap/test/index.html +0 -1
  155. umap/static/umap/unittests/URLs.js +1 -1
  156. umap/static/umap/unittests/utils.js +610 -0
  157. umap/static/umap/vars.css +9 -0
  158. umap/static/umap/vendors/dompurify/purify.es.mjs +1525 -0
  159. umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +1 -0
  160. umap/static/umap/vendors/iconlayers/iconLayers.js +1 -1
  161. umap/templates/umap/css.html +2 -0
  162. umap/templates/umap/js.html +0 -1
  163. umap/templates/umap/map_detail.html +4 -0
  164. umap/templates/umap/map_table.html +12 -10
  165. umap/templatetags/umap_tags.py +5 -0
  166. umap/tests/integration/conftest.py +12 -1
  167. umap/tests/integration/test_anonymous_owned_map.py +27 -5
  168. umap/tests/integration/test_basics.py +21 -0
  169. umap/tests/integration/test_browser.py +12 -25
  170. umap/tests/integration/test_choropleth.py +1 -1
  171. umap/tests/integration/test_dashboard.py +10 -0
  172. umap/tests/integration/test_datalayer.py +8 -6
  173. umap/tests/integration/test_edit_datalayer.py +24 -19
  174. umap/tests/integration/test_edit_map.py +189 -2
  175. umap/tests/integration/test_edit_marker.py +120 -0
  176. umap/tests/integration/test_edit_polygon.py +122 -0
  177. umap/tests/integration/test_facets_browser.py +104 -14
  178. umap/tests/integration/test_import.py +72 -20
  179. umap/tests/integration/test_map.py +19 -17
  180. umap/tests/integration/test_map_list.py +28 -0
  181. umap/tests/integration/test_owned_map.py +10 -10
  182. umap/tests/integration/test_picto.py +5 -5
  183. umap/tests/integration/test_querystring.py +9 -15
  184. umap/tests/integration/test_slideshow.py +0 -5
  185. umap/tests/integration/test_statics.py +3 -2
  186. umap/tests/integration/test_tableeditor.py +1 -5
  187. umap/tests/integration/test_tilelayer.py +10 -0
  188. umap/tests/integration/test_view_marker.py +64 -0
  189. umap/tests/integration/test_view_polygon.py +59 -0
  190. umap/tests/integration/test_view_polyline.py +51 -0
  191. umap/tests/test_map_views.py +13 -0
  192. {umap_project-2.1.3.dist-info → umap_project-2.2.0.dist-info}/METADATA +12 -12
  193. {umap_project-2.1.3.dist-info → umap_project-2.2.0.dist-info}/RECORD +198 -182
  194. {umap_project-2.1.3.dist-info → umap_project-2.2.0.dist-info}/WHEEL +1 -1
  195. umap/static/umap/vendors/dompurify/purify.min.js +0 -3
  196. umap/static/umap/vendors/dompurify/purify.min.js.map +0 -1
  197. /umap/tests/integration/{test_polygon.py → test_draw_polygon.py} +0 -0
  198. /umap/tests/integration/{test_polyline.py → test_draw_polyline.py} +0 -0
  199. {umap_project-2.1.3.dist-info → umap_project-2.2.0.dist-info}/entry_points.txt +0 -0
  200. {umap_project-2.1.3.dist-info → umap_project-2.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -97,7 +97,7 @@ U.Layer.Cluster = L.MarkerClusterGroup.extend({
97
97
  },
98
98
 
99
99
  getEditableOptions: function () {
100
- if (!L.Util.isObject(this.datalayer.options.cluster)) {
100
+ if (!U.Utils.isObject(this.datalayer.options.cluster)) {
101
101
  this.datalayer.options.cluster = {}
102
102
  }
103
103
  return [
@@ -155,7 +155,7 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
155
155
 
156
156
  initialize: function (datalayer) {
157
157
  this.datalayer = datalayer
158
- if (!L.Util.isObject(this.datalayer.options.choropleth)) {
158
+ if (!U.Utils.isObject(this.datalayer.options.choropleth)) {
159
159
  this.datalayer.options.choropleth = {}
160
160
  }
161
161
  L.FeatureGroup.prototype.initialize.call(
@@ -254,16 +254,18 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
254
254
  },
255
255
 
256
256
  onEdit: function (field, builder) {
257
+ // Only compute the breaks if we're dealing with choropleth
258
+ if (!field.startsWith('options.choropleth')) return
257
259
  // If user touches the breaks, then force manual mode
258
260
  if (field === 'options.choropleth.breaks') {
259
261
  this.datalayer.options.choropleth.mode = 'manual'
260
- builder.helpers['options.choropleth.mode'].fetch()
262
+ if (builder) builder.helpers['options.choropleth.mode'].fetch()
261
263
  }
262
264
  this.computeBreaks()
263
265
  // If user changes the mode or the number of classes,
264
266
  // then update the breaks input value
265
267
  if (field === 'options.choropleth.mode' || field === 'options.choropleth.classes') {
266
- builder.helpers['options.choropleth.breaks'].fetch()
268
+ if (builder) builder.helpers['options.choropleth.breaks'].fetch()
267
269
  }
268
270
  },
269
271
 
@@ -381,7 +383,7 @@ U.Layer.Heat = L.HeatLayer.extend({
381
383
  },
382
384
 
383
385
  getEditableOptions: function () {
384
- if (!L.Util.isObject(this.datalayer.options.heat)) {
386
+ if (!U.Utils.isObject(this.datalayer.options.heat)) {
385
387
  this.datalayer.options.heat = {}
386
388
  }
387
389
  return [
@@ -592,6 +594,32 @@ U.DataLayer = L.Evented.extend({
592
594
  // Automatically, others will be shown manually, and thus will
593
595
  // be in the "forced visibility" mode
594
596
  if (this.autoLoaded()) this.map.on('zoomend', this.onZoomEnd, this)
597
+ this.on('datachanged', this.map.onDataLayersChanged, this.map)
598
+ },
599
+
600
+ render: function (fields, builder) {
601
+ let impacts = U.Utils.getImpactsFromSchema(fields)
602
+
603
+ for (let impact of impacts) {
604
+ switch (impact) {
605
+ case 'ui':
606
+ this.map.onDataLayersChanged()
607
+ break
608
+ case 'data':
609
+ if (fields.includes('options.type')) {
610
+ this.resetLayer()
611
+ }
612
+ this.hide()
613
+ fields.forEach((field) => {
614
+ this.layer.onEdit(field, builder)
615
+ })
616
+ this.show()
617
+ break
618
+ case 'remote-data':
619
+ this.fetchRemoteData()
620
+ break
621
+ }
622
+ }
595
623
  },
596
624
 
597
625
  onMoveEnd: function (e) {
@@ -724,13 +752,13 @@ U.DataLayer = L.Evented.extend({
724
752
  },
725
753
 
726
754
  backupData: function () {
727
- this._geojson_bk = L.Util.CopyJSON(this._geojson)
755
+ this._geojson_bk = U.Utils.CopyJSON(this._geojson)
728
756
  },
729
757
 
730
758
  reindex: function () {
731
759
  const features = []
732
760
  this.eachFeature((feature) => features.push(feature))
733
- L.Util.sortFeatures(features, this.map.getOption('sortKey'))
761
+ U.Utils.sortFeatures(features, this.map.getOption('sortKey'), L.lang)
734
762
  this._index = []
735
763
  for (let i = 0; i < features.length; i++) {
736
764
  this._index.push(L.Util.stamp(features[i]))
@@ -793,16 +821,16 @@ U.DataLayer = L.Evented.extend({
793
821
  },
794
822
 
795
823
  backupOptions: function () {
796
- this._backupOptions = L.Util.CopyJSON(this.options)
824
+ this._backupOptions = U.Utils.CopyJSON(this.options)
797
825
  },
798
826
 
799
827
  resetOptions: function () {
800
- this.options = L.Util.CopyJSON(this._backupOptions)
828
+ this.options = U.Utils.CopyJSON(this._backupOptions)
801
829
  },
802
830
 
803
831
  setOptions: function (options) {
804
832
  delete options.geojson
805
- this.options = L.Util.CopyJSON(U.DataLayer.prototype.options) // Start from fresh.
833
+ this.options = U.Utils.CopyJSON(U.DataLayer.prototype.options) // Start from fresh.
806
834
  this.updateOptions(options)
807
835
  },
808
836
 
@@ -817,14 +845,14 @@ U.DataLayer = L.Evented.extend({
817
845
  this.map.datalayers[id] = this
818
846
  if (L.Util.indexOf(this.map.datalayers_index, this) === -1)
819
847
  this.map.datalayers_index.push(this)
848
+ this.map.onDataLayersChanged()
820
849
  }
821
- this.map.updateDatalayersControl()
822
850
  },
823
851
 
824
852
  _dataUrl: function () {
825
853
  const template = this.map.options.urls.datalayer_view
826
854
 
827
- let url = L.Util.template(template, {
855
+ let url = U.Utils.template(template, {
828
856
  pk: this.umap_id,
829
857
  map_id: this.map.options.umap_id,
830
858
  })
@@ -919,6 +947,17 @@ U.DataLayer = L.Evented.extend({
919
947
  includeLatLon: false,
920
948
  },
921
949
  (err, result) => {
950
+ // csv2geojson fallback to null geometries when it cannot determine
951
+ // lat or lon columns. This is valid geojson, but unwanted from a user
952
+ // point of view.
953
+ if (result && result.features.length) {
954
+ if (result.features[0].geometry === null) {
955
+ err = {
956
+ type: 'Error',
957
+ message: L._('Cannot determine latitude and longitude columns.'),
958
+ }
959
+ }
960
+ }
922
961
  if (err) {
923
962
  let message
924
963
  if (err.type === 'Error') {
@@ -971,7 +1010,7 @@ U.DataLayer = L.Evented.extend({
971
1010
  let latlngs
972
1011
 
973
1012
  if (features) {
974
- L.Util.sortFeatures(features, this.map.getOption('sortKey'))
1013
+ U.Utils.sortFeatures(features, this.map.getOption('sortKey'), L.lang)
975
1014
  for (i = 0, len = features.length; i < len; i++) {
976
1015
  this.geojsonToFeatures(features[i])
977
1016
  }
@@ -1061,7 +1100,7 @@ U.DataLayer = L.Evented.extend({
1061
1100
 
1062
1101
  importFromFile: function (f, type) {
1063
1102
  const reader = new FileReader()
1064
- type = type || L.Util.detectFileType(f)
1103
+ type = type || U.Utils.detectFileType(f)
1065
1104
  reader.readAsText(f)
1066
1105
  reader.onload = (e) => this.importRaw(e.target.result, type)
1067
1106
  },
@@ -1079,21 +1118,21 @@ U.DataLayer = L.Evented.extend({
1079
1118
  },
1080
1119
 
1081
1120
  getDeleteUrl: function () {
1082
- return L.Util.template(this.map.options.urls.datalayer_delete, {
1121
+ return U.Utils.template(this.map.options.urls.datalayer_delete, {
1083
1122
  pk: this.umap_id,
1084
1123
  map_id: this.map.options.umap_id,
1085
1124
  })
1086
1125
  },
1087
1126
 
1088
1127
  getVersionsUrl: function () {
1089
- return L.Util.template(this.map.options.urls.datalayer_versions, {
1128
+ return U.Utils.template(this.map.options.urls.datalayer_versions, {
1090
1129
  pk: this.umap_id,
1091
1130
  map_id: this.map.options.umap_id,
1092
1131
  })
1093
1132
  },
1094
1133
 
1095
1134
  getVersionUrl: function (name) {
1096
- return L.Util.template(this.map.options.urls.datalayer_version, {
1135
+ return U.Utils.template(this.map.options.urls.datalayer_version, {
1097
1136
  pk: this.umap_id,
1098
1137
  map_id: this.map.options.umap_id,
1099
1138
  name: name,
@@ -1112,10 +1151,10 @@ U.DataLayer = L.Evented.extend({
1112
1151
  },
1113
1152
 
1114
1153
  clone: function () {
1115
- const options = L.Util.CopyJSON(this.options)
1154
+ const options = U.Utils.CopyJSON(this.options)
1116
1155
  options.name = L._('Clone of {name}', { name: this.options.name })
1117
1156
  delete options.id
1118
- const geojson = L.Util.CopyJSON(this._geojson),
1157
+ const geojson = U.Utils.CopyJSON(this._geojson),
1119
1158
  datalayer = this.map.createDataLayer(options)
1120
1159
  datalayer.fromGeoJSON(geojson)
1121
1160
  return datalayer
@@ -1126,7 +1165,8 @@ U.DataLayer = L.Evented.extend({
1126
1165
  delete this.map.datalayers[L.stamp(this)]
1127
1166
  this.map.datalayers_index.splice(this.getRank(), 1)
1128
1167
  this.parentPane.removeChild(this.pane)
1129
- this.map.updateDatalayersControl()
1168
+ this.map.onDataLayersChanged()
1169
+ this.off('datachanged', this.map.onDataLayersChanged, this.map)
1130
1170
  this.fire('erase')
1131
1171
  this._leaflet_events_bk = this._leaflet_events
1132
1172
  this.map.off('moveend', this.onMoveEnd, this)
@@ -1186,32 +1226,22 @@ U.DataLayer = L.Evented.extend({
1186
1226
  },
1187
1227
  ],
1188
1228
  ]
1189
- const title = L.DomUtil.add('h3', '', container, L._('Layer properties'))
1229
+ L.DomUtil.createTitle(container, L._('Layer properties'), 'icon-layers')
1190
1230
  let builder = new U.FormBuilder(this, metadataFields, {
1191
1231
  callback: function (e) {
1192
- this.map.updateDatalayersControl()
1232
+ this.map.onDataLayersChanged()
1193
1233
  if (e.helper.field === 'options.type') {
1194
- this.resetLayer()
1195
1234
  this.edit()
1196
1235
  }
1197
1236
  },
1198
1237
  })
1199
1238
  container.appendChild(builder.build())
1200
1239
 
1201
- const redrawCallback = function (e) {
1202
- const field = e.helper.field,
1203
- builder = e.helper.builder
1204
- this.hide()
1205
- this.layer.onEdit(field, builder)
1206
- this.show()
1207
- }
1208
-
1209
1240
  const layerOptions = this.layer.getEditableOptions()
1210
1241
 
1211
1242
  if (layerOptions.length) {
1212
1243
  builder = new U.FormBuilder(this, layerOptions, {
1213
1244
  id: 'datalayer-layer-properties',
1214
- callback: redrawCallback,
1215
1245
  })
1216
1246
  const layerProperties = L.DomUtil.createFieldset(
1217
1247
  container,
@@ -1235,7 +1265,6 @@ U.DataLayer = L.Evented.extend({
1235
1265
 
1236
1266
  builder = new U.FormBuilder(this, shapeOptions, {
1237
1267
  id: 'datalayer-advanced-properties',
1238
- callback: redrawCallback,
1239
1268
  })
1240
1269
  const shapeProperties = L.DomUtil.createFieldset(container, L._('Shape properties'))
1241
1270
  shapeProperties.appendChild(builder.build())
@@ -1251,7 +1280,6 @@ U.DataLayer = L.Evented.extend({
1251
1280
 
1252
1281
  builder = new U.FormBuilder(this, optionsFields, {
1253
1282
  id: 'datalayer-advanced-properties',
1254
- callback: redrawCallback,
1255
1283
  })
1256
1284
  const advancedProperties = L.DomUtil.createFieldset(
1257
1285
  container,
@@ -1269,14 +1297,14 @@ U.DataLayer = L.Evented.extend({
1269
1297
  'options.outlinkTarget',
1270
1298
  'options.interactive',
1271
1299
  ]
1272
- builder = new U.FormBuilder(this, popupFields, { callback: redrawCallback })
1300
+ builder = new U.FormBuilder(this, popupFields)
1273
1301
  const popupFieldset = L.DomUtil.createFieldset(
1274
1302
  container,
1275
1303
  L._('Interaction options')
1276
1304
  )
1277
1305
  popupFieldset.appendChild(builder.build())
1278
1306
 
1279
- if (!L.Util.isObject(this.options.remoteData)) {
1307
+ if (!U.Utils.isObject(this.options.remoteData)) {
1280
1308
  this.options.remoteData = {}
1281
1309
  }
1282
1310
  const remoteDataFields = [
@@ -1335,7 +1363,7 @@ U.DataLayer = L.Evented.extend({
1335
1363
  L._('Delete'),
1336
1364
  function () {
1337
1365
  this._delete()
1338
- this.map.ui.closePanel()
1366
+ this.map.editPanel.close()
1339
1367
  },
1340
1368
  this
1341
1369
  )
@@ -1367,11 +1395,22 @@ U.DataLayer = L.Evented.extend({
1367
1395
  '_blank'
1368
1396
  )
1369
1397
  }
1370
- this.map.ui.openPanel({ data: { html: container }, className: 'dark' })
1398
+ const button = L.DomUtil.create('li', '')
1399
+ L.DomUtil.create('i', 'icon icon-16 icon-back', button)
1400
+ button.title = L._('Back to layers')
1401
+ // Fixme: remove me when this is merged and released
1402
+ // https://github.com/Leaflet/Leaflet/pull/9052
1403
+ L.DomEvent.disableClickPropagation(button)
1404
+ L.DomEvent.on(button, 'click', this.map.editDatalayers, this.map)
1405
+
1406
+ this.map.editPanel.open({
1407
+ content: container,
1408
+ actions: [button],
1409
+ })
1371
1410
  },
1372
1411
 
1373
1412
  getOwnOption: function (option) {
1374
- if (L.Util.usableOption(this.options, option)) return this.options[option]
1413
+ if (U.Utils.usableOption(this.options, option)) return this.options[option]
1375
1414
  },
1376
1415
 
1377
1416
  getOption: function (option, feature) {
@@ -1668,6 +1707,6 @@ L.TileLayer.include({
1668
1707
  },
1669
1708
 
1670
1709
  getAttribution: function () {
1671
- return L.Util.toHTML(this.options.attribution)
1710
+ return U.Utils.toHTML(this.options.attribution)
1672
1711
  },
1673
1712
  })
@@ -57,15 +57,20 @@ U.MapPermissions = L.Class.extend({
57
57
  content: L._('Please save the map first'),
58
58
  level: 'info',
59
59
  })
60
- const container = L.DomUtil.create('div', 'permissions-panel'),
61
- fields = [],
62
- title = L.DomUtil.create('h3', '', container)
60
+ const container = L.DomUtil.create('div', 'permissions-panel')
61
+ const fields = []
62
+ L.DomUtil.createTitle(container, L._('Update permissions'), 'icon-key')
63
63
  if (this.isAnonymousMap()) {
64
64
  if (this.options.anonymous_edit_url) {
65
65
  const helpText = `${L._('Secret edit link:')}<br>${
66
66
  this.options.anonymous_edit_url
67
67
  }`
68
- L.DomUtil.add('p', 'help-text', container, helpText)
68
+ L.DomUtil.element({
69
+ tagName: 'p',
70
+ className: 'help-text',
71
+ innerHTML: helpText,
72
+ parent: container,
73
+ })
69
74
  fields.push([
70
75
  'options.edit_status',
71
76
  {
@@ -104,7 +109,6 @@ U.MapPermissions = L.Class.extend({
104
109
  { handler: 'ManageEditors', label: L._("Map's editors") },
105
110
  ])
106
111
  }
107
- title.textContent = L._('Update permissions')
108
112
  const builder = new U.FormBuilder(this, fields)
109
113
  const form = builder.build()
110
114
  container.appendChild(form)
@@ -128,7 +132,7 @@ U.MapPermissions = L.Class.extend({
128
132
  this.map.eachDataLayer((datalayer) => {
129
133
  datalayer.permissions.edit(container)
130
134
  })
131
- this.map.ui.openPanel({ data: { html: container }, className: 'dark' })
135
+ this.map.editPanel.open({ content: container, className: 'dark' })
132
136
  },
133
137
 
134
138
  attach: async function () {
@@ -139,7 +143,7 @@ U.MapPermissions = L.Class.extend({
139
143
  content: L._('Map has been attached to your account'),
140
144
  level: 'info',
141
145
  })
142
- this.map.ui.closePanel()
146
+ this.map.editPanel.close()
143
147
  }
144
148
  },
145
149
 
@@ -171,13 +175,13 @@ U.MapPermissions = L.Class.extend({
171
175
  },
172
176
 
173
177
  getUrl: function () {
174
- return L.Util.template(this.map.options.urls.map_update_permissions, {
178
+ return U.Utils.template(this.map.options.urls.map_update_permissions, {
175
179
  map_id: this.map.options.umap_id,
176
180
  })
177
181
  },
178
182
 
179
183
  getAttachUrl: function () {
180
- return L.Util.template(this.map.options.urls.map_attach_owner, {
184
+ return U.Utils.template(this.map.options.urls.map_attach_owner, {
181
185
  map_id: this.map.options.umap_id,
182
186
  })
183
187
  },
@@ -54,22 +54,10 @@ U.Popup.Panel = U.Popup.extend({
54
54
  zoomAnimation: false,
55
55
  },
56
56
 
57
- allButton: function () {
58
- const button = L.DomUtil.create('li', '')
59
- L.DomUtil.create('i', 'umap-icon-16 umap-list', button)
60
- const label = L.DomUtil.create('span', '', button)
61
- label.textContent = label.title = L._('See all')
62
- // Fixme: remove me when this is merged and released
63
- // https://github.com/Leaflet/Leaflet/pull/9052
64
- L.DomEvent.disableClickPropagation(button)
65
- L.DomEvent.on(button, 'click', this.feature.map.openBrowser, this.feature.map)
66
- return button
67
- },
68
-
69
57
  onAdd: function (map) {
70
- map.ui.openPanel({
71
- data: { html: this._content },
72
- actions: [this.allButton()],
58
+ map.panel.open({
59
+ content: this._content,
60
+ actions: [U.Browser.backButton(map)],
73
61
  })
74
62
 
75
63
  // fire events as in base class Popup.js:onAdd
@@ -83,7 +71,7 @@ U.Popup.Panel = U.Popup.extend({
83
71
  },
84
72
 
85
73
  onRemove: function (map) {
86
- map.ui.closePanel()
74
+ map.panel.close()
87
75
 
88
76
  // fire events as in base class Popup.js:onRemove
89
77
  map.fire('popupclose', { popup: this })
@@ -124,12 +112,12 @@ U.PopupTemplate.Default = L.Class.extend({
124
112
  let center
125
113
  properties = this.feature.extendedProperties()
126
114
  // Resolve properties inside description
127
- properties.description = L.Util.greedyTemplate(
115
+ properties.description = U.Utils.greedyTemplate(
128
116
  this.feature.properties.description || '',
129
117
  properties
130
118
  )
131
- content = L.Util.greedyTemplate(template, properties)
132
- content = L.Util.toHTML(content, { target: target })
119
+ content = U.Utils.greedyTemplate(template, properties)
120
+ content = U.Utils.toHTML(content, { target: target })
133
121
  container.innerHTML = content
134
122
  return container
135
123
  },
@@ -202,7 +190,11 @@ U.PopupTemplate.Table = U.PopupTemplate.BaseWithTitle.extend({
202
190
  addRow: function (container, key, value) {
203
191
  const tr = L.DomUtil.create('tr', '', container)
204
192
  L.DomUtil.add('th', '', tr, key)
205
- L.DomUtil.add('td', '', tr, this.formatRow(key, value))
193
+ L.DomUtil.element({
194
+ tagName: 'td',
195
+ parent: tr,
196
+ innerHTML: this.formatRow(key, value),
197
+ })
206
198
  },
207
199
 
208
200
  renderBody: function () {
@@ -211,7 +203,7 @@ U.PopupTemplate.Table = U.PopupTemplate.BaseWithTitle.extend({
211
203
  for (const key in this.feature.properties) {
212
204
  if (typeof this.feature.properties[key] === 'object' || key === 'name') continue
213
205
  // TODO, manage links (url, mailto, wikipedia...)
214
- this.addRow(table, key, L.Util.escapeHTML(this.feature.properties[key]).trim())
206
+ this.addRow(table, key, U.Utils.escapeHTML(this.feature.properties[key]).trim())
215
207
  }
216
208
  return table
217
209
  },
@@ -263,7 +255,8 @@ U.PopupTemplate.OSM = U.PopupTemplate.Default.extend({
263
255
 
264
256
  getName: function () {
265
257
  const props = this.feature.properties
266
- if (L.locale && props[`name:${L.locale}`]) return props[`name:${L.locale}`]
258
+ const locale = L.getLocale()
259
+ if (locale && props[`name:${locale}`]) return props[`name:${locale}`]
267
260
  return props.name
268
261
  },
269
262
 
@@ -292,11 +285,12 @@ U.PopupTemplate.OSM = U.PopupTemplate.Default.extend({
292
285
  }
293
286
  }
294
287
  if (props.website) {
295
- L.DomUtil.element(
296
- 'a',
297
- { href: props.website, textContent: props.website },
298
- container
299
- )
288
+ L.DomUtil.element({
289
+ tagName: 'a',
290
+ parent: container,
291
+ href: props.website,
292
+ textContent: props.website,
293
+ })
300
294
  }
301
295
  const phone = props.phone || props['contact:phone']
302
296
  if (phone) {
@@ -304,7 +298,7 @@ U.PopupTemplate.OSM = U.PopupTemplate.Default.extend({
304
298
  'div',
305
299
  '',
306
300
  container,
307
- L.DomUtil.element('a', { href: `tel:${phone}`, textContent: phone })
301
+ L.DomUtil.element({ tagName: 'a', href: `tel:${phone}`, textContent: phone })
308
302
  )
309
303
  }
310
304
  if (props.mobile) {
@@ -312,7 +306,8 @@ U.PopupTemplate.OSM = U.PopupTemplate.Default.extend({
312
306
  'div',
313
307
  '',
314
308
  container,
315
- L.DomUtil.element('a', {
309
+ L.DomUtil.element({
310
+ tagName: 'a',
316
311
  href: `tel:${props.mobile}`,
317
312
  textContent: props.mobile,
318
313
  })
@@ -333,7 +328,8 @@ U.PopupTemplate.OSM = U.PopupTemplate.Default.extend({
333
328
  'div',
334
329
  'osm-link',
335
330
  container,
336
- L.DomUtil.element('a', {
331
+ L.DomUtil.element({
332
+ tagName: 'a',
337
333
  href: `https://www.openstreetmap.org/${id}`,
338
334
  textContent: L._('See on OpenStreetMap'),
339
335
  })
@@ -44,14 +44,17 @@ U.Share = L.Class.extend({
44
44
  },
45
45
 
46
46
  build: function () {
47
- this.container = L.DomUtil.create('div', 'umap-share')
48
- this.title = L.DomUtil.create('h3', '', this.container)
49
- this.title.textContent = L._('Share and download')
47
+ this.container = L.DomUtil.create('div', '')
48
+ this.title = L.DomUtil.createTitle(
49
+ this.container,
50
+ L._('Share and download'),
51
+ 'icon-share'
52
+ )
50
53
 
51
54
  L.DomUtil.createCopiableInput(
52
55
  this.container,
53
56
  L._('Link to view the map'),
54
- window.location.protocol + L.Util.getBaseUrl()
57
+ window.location.protocol + U.Utils.getBaseUrl()
55
58
  )
56
59
 
57
60
  if (this.map.options.shortUrl) {
@@ -84,7 +87,7 @@ U.Share = L.Class.extend({
84
87
  this.container,
85
88
  L._('All data and settings of the map')
86
89
  )
87
- const downloadUrl = L.Util.template(this.map.options.urls.map_download, {
90
+ const downloadUrl = U.Utils.template(this.map.options.urls.map_download, {
88
91
  map_id: this.map.options.umap_id,
89
92
  })
90
93
  const link = L.DomUtil.createLink(
@@ -140,7 +143,7 @@ U.Share = L.Class.extend({
140
143
  }
141
144
  const iframeExporter = new U.IframeExporter(this.map)
142
145
  const buildIframeCode = () => {
143
- iframe.innerHTML = iframeExporter.build()
146
+ iframe.textContent = iframeExporter.build()
144
147
  exportUrl.value = window.location.protocol + iframeExporter.buildUrl()
145
148
  }
146
149
  buildIframeCode()
@@ -156,7 +159,7 @@ U.Share = L.Class.extend({
156
159
 
157
160
  open: function () {
158
161
  if (!this.container) this.build()
159
- this.map.ui.openPanel({ data: { html: this.container } })
162
+ this.map.panel.open({ content: this.container })
160
163
  },
161
164
 
162
165
  format: function (mode) {
@@ -213,7 +216,7 @@ U.IframeExporter = L.Evented.extend({
213
216
 
214
217
  initialize: function (map) {
215
218
  this.map = map
216
- this.baseUrl = L.Util.getBaseUrl()
219
+ this.baseUrl = U.Utils.getBaseUrl()
217
220
  // Use map default, not generic default
218
221
  this.queryString.onLoadPanel = this.map.getOption('onLoadPanel')
219
222
  },
@@ -241,7 +244,7 @@ U.IframeExporter = L.Evented.extend({
241
244
  }
242
245
  const currentView = this.options.currentView ? window.location.hash : ''
243
246
  const queryString = L.extend({}, this.queryString, options)
244
- return `${this.baseUrl}?${L.Util.buildQueryString(queryString)}${currentView}`
247
+ return `${this.baseUrl}?${U.Utils.buildQueryString(queryString)}${currentView}`
245
248
  },
246
249
 
247
250
  build: function () {
@@ -94,13 +94,12 @@ U.TableEditor = L.Class.extend({
94
94
 
95
95
  edit: function () {
96
96
  const id = 'tableeditor:edit'
97
- this.datalayer.map.fire('dataloading', { id: id })
98
97
  this.compileProperties()
99
98
  this.renderHeaders()
100
99
  this.body.innerHTML = ''
101
100
  this.datalayer.eachLayer(this.renderRow, this)
102
101
  const addButton = L.DomUtil.create('li', 'add-property')
103
- L.DomUtil.create('i', 'umap-icon-16 umap-add', addButton)
102
+ L.DomUtil.createIcon(addButton, 'icon-add')
104
103
  const label = L.DomUtil.create('span', '', addButton)
105
104
  label.textContent = label.title = L._('Add a new property')
106
105
  const addProperty = function () {
@@ -110,11 +109,10 @@ U.TableEditor = L.Class.extend({
110
109
  this.edit()
111
110
  }
112
111
  L.DomEvent.on(addButton, 'click', addProperty, this)
113
- this.datalayer.map.ui.openPanel({
114
- data: { html: this.table },
115
- className: 'umap-table-editor fullwidth dark',
112
+ this.datalayer.map.fullPanel.open({
113
+ content: this.table,
114
+ className: 'umap-table-editor',
116
115
  actions: [addButton],
117
116
  })
118
- this.datalayer.map.fire('dataload', { id: id })
119
117
  },
120
118
  })