umap-project 2.1.3__py3-none-any.whl → 2.2.0b0__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 (196) 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 +29 -151
  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 +82 -73
  25. umap/static/umap/js/modules/dompurify.js +12 -0
  26. umap/static/umap/js/modules/facets.js +148 -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.controls.js +183 -330
  36. umap/static/umap/js/umap.core.js +60 -364
  37. umap/static/umap/js/umap.datalayer.permissions.js +1 -1
  38. umap/static/umap/js/umap.features.js +60 -40
  39. umap/static/umap/js/umap.forms.js +111 -25
  40. umap/static/umap/js/umap.icon.js +11 -4
  41. umap/static/umap/js/umap.importer.js +24 -17
  42. umap/static/umap/js/umap.js +170 -145
  43. umap/static/umap/js/umap.layer.js +71 -40
  44. umap/static/umap/js/umap.permissions.js +9 -11
  45. umap/static/umap/js/umap.popup.js +10 -21
  46. umap/static/umap/js/umap.share.js +11 -8
  47. umap/static/umap/js/umap.tableeditor.js +4 -6
  48. umap/static/umap/js/umap.ui.js +0 -51
  49. umap/static/umap/locale/am_ET.js +242 -227
  50. umap/static/umap/locale/am_ET.json +18 -7
  51. umap/static/umap/locale/ar.js +242 -227
  52. umap/static/umap/locale/ar.json +18 -7
  53. umap/static/umap/locale/ast.js +242 -227
  54. umap/static/umap/locale/ast.json +18 -7
  55. umap/static/umap/locale/bg.js +242 -227
  56. umap/static/umap/locale/bg.json +18 -7
  57. umap/static/umap/locale/br.js +252 -237
  58. umap/static/umap/locale/br.json +22 -11
  59. umap/static/umap/locale/ca.js +242 -227
  60. umap/static/umap/locale/ca.json +18 -7
  61. umap/static/umap/locale/cs_CZ.js +242 -227
  62. umap/static/umap/locale/cs_CZ.json +18 -7
  63. umap/static/umap/locale/da.js +242 -227
  64. umap/static/umap/locale/da.json +18 -7
  65. umap/static/umap/locale/de.js +242 -227
  66. umap/static/umap/locale/de.json +18 -7
  67. umap/static/umap/locale/el.js +242 -227
  68. umap/static/umap/locale/el.json +18 -7
  69. umap/static/umap/locale/en.js +242 -234
  70. umap/static/umap/locale/en.json +19 -8
  71. umap/static/umap/locale/en_US.json +18 -7
  72. umap/static/umap/locale/es.js +242 -227
  73. umap/static/umap/locale/es.json +18 -7
  74. umap/static/umap/locale/et.js +242 -227
  75. umap/static/umap/locale/et.json +18 -7
  76. umap/static/umap/locale/eu.js +227 -199
  77. umap/static/umap/locale/eu.json +1 -1
  78. umap/static/umap/locale/fa_IR.js +242 -227
  79. umap/static/umap/locale/fa_IR.json +18 -7
  80. umap/static/umap/locale/fi.js +242 -227
  81. umap/static/umap/locale/fi.json +18 -7
  82. umap/static/umap/locale/fr.js +242 -234
  83. umap/static/umap/locale/fr.json +18 -7
  84. umap/static/umap/locale/gl.js +242 -227
  85. umap/static/umap/locale/gl.json +18 -7
  86. umap/static/umap/locale/he.js +242 -227
  87. umap/static/umap/locale/he.json +18 -7
  88. umap/static/umap/locale/hr.js +242 -227
  89. umap/static/umap/locale/hr.json +18 -7
  90. umap/static/umap/locale/hu.js +242 -234
  91. umap/static/umap/locale/hu.json +18 -7
  92. umap/static/umap/locale/id.js +242 -227
  93. umap/static/umap/locale/id.json +18 -7
  94. umap/static/umap/locale/is.js +242 -227
  95. umap/static/umap/locale/is.json +18 -7
  96. umap/static/umap/locale/it.js +242 -234
  97. umap/static/umap/locale/it.json +18 -7
  98. umap/static/umap/locale/ja.js +242 -227
  99. umap/static/umap/locale/ja.json +18 -7
  100. umap/static/umap/locale/ko.js +242 -227
  101. umap/static/umap/locale/ko.json +18 -7
  102. umap/static/umap/locale/lt.js +242 -227
  103. umap/static/umap/locale/lt.json +18 -7
  104. umap/static/umap/locale/ms.js +242 -234
  105. umap/static/umap/locale/ms.json +19 -8
  106. umap/static/umap/locale/nl.js +245 -230
  107. umap/static/umap/locale/nl.json +18 -7
  108. umap/static/umap/locale/no.js +242 -227
  109. umap/static/umap/locale/no.json +18 -7
  110. umap/static/umap/locale/pl.js +242 -227
  111. umap/static/umap/locale/pl.json +18 -7
  112. umap/static/umap/locale/pl_PL.json +18 -7
  113. umap/static/umap/locale/pt.js +242 -227
  114. umap/static/umap/locale/pt.json +18 -7
  115. umap/static/umap/locale/pt_BR.js +242 -227
  116. umap/static/umap/locale/pt_BR.json +18 -7
  117. umap/static/umap/locale/pt_PT.js +242 -227
  118. umap/static/umap/locale/pt_PT.json +18 -7
  119. umap/static/umap/locale/ro.js +242 -227
  120. umap/static/umap/locale/ro.json +18 -7
  121. umap/static/umap/locale/ru.js +242 -227
  122. umap/static/umap/locale/ru.json +18 -7
  123. umap/static/umap/locale/si.js +1 -1
  124. umap/static/umap/locale/si.json +1 -1
  125. umap/static/umap/locale/sk_SK.js +242 -227
  126. umap/static/umap/locale/sk_SK.json +18 -7
  127. umap/static/umap/locale/sl.js +242 -227
  128. umap/static/umap/locale/sl.json +18 -7
  129. umap/static/umap/locale/sr.js +242 -227
  130. umap/static/umap/locale/sr.json +18 -7
  131. umap/static/umap/locale/sv.js +242 -227
  132. umap/static/umap/locale/sv.json +18 -7
  133. umap/static/umap/locale/th_TH.js +242 -227
  134. umap/static/umap/locale/th_TH.json +18 -7
  135. umap/static/umap/locale/tr.js +242 -227
  136. umap/static/umap/locale/tr.json +18 -7
  137. umap/static/umap/locale/uk_UA.js +242 -227
  138. umap/static/umap/locale/uk_UA.json +18 -7
  139. umap/static/umap/locale/vi.js +242 -227
  140. umap/static/umap/locale/vi.json +18 -7
  141. umap/static/umap/locale/vi_VN.json +18 -7
  142. umap/static/umap/locale/zh.js +242 -227
  143. umap/static/umap/locale/zh.json +18 -7
  144. umap/static/umap/locale/zh_CN.json +18 -7
  145. umap/static/umap/locale/zh_TW.Big5.json +18 -7
  146. umap/static/umap/locale/zh_TW.js +242 -234
  147. umap/static/umap/locale/zh_TW.json +18 -7
  148. umap/static/umap/map.css +114 -265
  149. umap/static/umap/test/DataLayer.js +463 -0
  150. umap/static/umap/test/Feature.js +0 -226
  151. umap/static/umap/test/TableEditor.js +104 -0
  152. umap/static/umap/test/Util.js +0 -521
  153. umap/static/umap/test/index.html +0 -1
  154. umap/static/umap/unittests/URLs.js +1 -1
  155. umap/static/umap/unittests/utils.js +610 -0
  156. umap/static/umap/vars.css +9 -0
  157. umap/static/umap/vendors/dompurify/purify.es.mjs +1525 -0
  158. umap/static/umap/vendors/iconlayers/iconLayers.js +1 -1
  159. umap/templates/umap/css.html +2 -0
  160. umap/templates/umap/js.html +0 -1
  161. umap/templates/umap/map_detail.html +4 -0
  162. umap/templates/umap/map_table.html +12 -10
  163. umap/templatetags/umap_tags.py +5 -0
  164. umap/tests/integration/conftest.py +12 -1
  165. umap/tests/integration/test_anonymous_owned_map.py +6 -5
  166. umap/tests/integration/test_browser.py +12 -25
  167. umap/tests/integration/test_choropleth.py +1 -1
  168. umap/tests/integration/test_dashboard.py +10 -0
  169. umap/tests/integration/test_datalayer.py +8 -6
  170. umap/tests/integration/test_edit_datalayer.py +24 -19
  171. umap/tests/integration/test_edit_map.py +182 -2
  172. umap/tests/integration/test_edit_marker.py +120 -0
  173. umap/tests/integration/test_edit_polygon.py +122 -0
  174. umap/tests/integration/test_facets_browser.py +104 -14
  175. umap/tests/integration/test_import.py +70 -20
  176. umap/tests/integration/test_map.py +19 -17
  177. umap/tests/integration/test_map_list.py +28 -0
  178. umap/tests/integration/test_owned_map.py +10 -10
  179. umap/tests/integration/test_picto.py +5 -5
  180. umap/tests/integration/test_querystring.py +9 -15
  181. umap/tests/integration/test_slideshow.py +0 -5
  182. umap/tests/integration/test_statics.py +3 -2
  183. umap/tests/integration/test_tableeditor.py +1 -5
  184. umap/tests/integration/test_view_marker.py +64 -0
  185. umap/tests/integration/test_view_polygon.py +59 -0
  186. umap/tests/integration/test_view_polyline.py +51 -0
  187. umap/tests/test_map_views.py +13 -0
  188. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/METADATA +8 -8
  189. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/RECORD +194 -178
  190. umap/static/umap/vendors/dompurify/purify.min.js +0 -3
  191. umap/static/umap/vendors/dompurify/purify.min.js.map +0 -1
  192. /umap/tests/integration/{test_polygon.py → test_draw_polygon.py} +0 -0
  193. /umap/tests/integration/{test_polyline.py → test_draw_polyline.py} +0 -0
  194. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/WHEEL +0 -0
  195. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/entry_points.txt +0 -0
  196. {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.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,14 @@ U.DataLayer = L.Evented.extend({
1367
1395
  '_blank'
1368
1396
  )
1369
1397
  }
1370
- this.map.ui.openPanel({ data: { html: container }, className: 'dark' })
1398
+ this.map.editPanel.open({
1399
+ content: container,
1400
+ actions: [U.Browser.backButton(this.map)],
1401
+ })
1371
1402
  },
1372
1403
 
1373
1404
  getOwnOption: function (option) {
1374
- if (L.Util.usableOption(this.options, option)) return this.options[option]
1405
+ if (U.Utils.usableOption(this.options, option)) return this.options[option]
1375
1406
  },
1376
1407
 
1377
1408
  getOption: function (option, feature) {
@@ -1668,6 +1699,6 @@ L.TileLayer.include({
1668
1699
  },
1669
1700
 
1670
1701
  getAttribution: function () {
1671
- return L.Util.toHTML(this.options.attribution)
1702
+ return U.Utils.toHTML(this.options.attribution)
1672
1703
  },
1673
1704
  })
@@ -57,14 +57,13 @@ 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
- const helpText = `${L._('Secret edit link:')}<br>${
66
- this.options.anonymous_edit_url
67
- }`
65
+ const helpText = `${L._('Secret edit link:')}<br>${this.options.anonymous_edit_url
66
+ }`
68
67
  L.DomUtil.add('p', 'help-text', container, helpText)
69
68
  fields.push([
70
69
  'options.edit_status',
@@ -104,7 +103,6 @@ U.MapPermissions = L.Class.extend({
104
103
  { handler: 'ManageEditors', label: L._("Map's editors") },
105
104
  ])
106
105
  }
107
- title.textContent = L._('Update permissions')
108
106
  const builder = new U.FormBuilder(this, fields)
109
107
  const form = builder.build()
110
108
  container.appendChild(form)
@@ -128,7 +126,7 @@ U.MapPermissions = L.Class.extend({
128
126
  this.map.eachDataLayer((datalayer) => {
129
127
  datalayer.permissions.edit(container)
130
128
  })
131
- this.map.ui.openPanel({ data: { html: container }, className: 'dark' })
129
+ this.map.editPanel.open({ content: container, className: 'dark' })
132
130
  },
133
131
 
134
132
  attach: async function () {
@@ -139,7 +137,7 @@ U.MapPermissions = L.Class.extend({
139
137
  content: L._('Map has been attached to your account'),
140
138
  level: 'info',
141
139
  })
142
- this.map.ui.closePanel()
140
+ this.map.editPanel.close()
143
141
  }
144
142
  },
145
143
 
@@ -171,13 +169,13 @@ U.MapPermissions = L.Class.extend({
171
169
  },
172
170
 
173
171
  getUrl: function () {
174
- return L.Util.template(this.map.options.urls.map_update_permissions, {
172
+ return U.Utils.template(this.map.options.urls.map_update_permissions, {
175
173
  map_id: this.map.options.umap_id,
176
174
  })
177
175
  },
178
176
 
179
177
  getAttachUrl: function () {
180
- return L.Util.template(this.map.options.urls.map_attach_owner, {
178
+ return U.Utils.template(this.map.options.urls.map_attach_owner, {
181
179
  map_id: this.map.options.umap_id,
182
180
  })
183
181
  },
@@ -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
  },
@@ -211,7 +199,7 @@ U.PopupTemplate.Table = U.PopupTemplate.BaseWithTitle.extend({
211
199
  for (const key in this.feature.properties) {
212
200
  if (typeof this.feature.properties[key] === 'object' || key === 'name') continue
213
201
  // TODO, manage links (url, mailto, wikipedia...)
214
- this.addRow(table, key, L.Util.escapeHTML(this.feature.properties[key]).trim())
202
+ this.addRow(table, key, U.Utils.escapeHTML(this.feature.properties[key]).trim())
215
203
  }
216
204
  return table
217
205
  },
@@ -263,7 +251,8 @@ U.PopupTemplate.OSM = U.PopupTemplate.Default.extend({
263
251
 
264
252
  getName: function () {
265
253
  const props = this.feature.properties
266
- if (L.locale && props[`name:${L.locale}`]) return props[`name:${L.locale}`]
254
+ const locale = L.getLocale()
255
+ if (locale && props[`name:${locale}`]) return props[`name:${locale}`]
267
256
  return props.name
268
257
  },
269
258
 
@@ -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(
@@ -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
  })
@@ -13,63 +13,12 @@ U.UI = L.Evented.extend({
13
13
  L.DomEvent.on(this.container, 'contextmenu', L.DomEvent.stopPropagation) // Do not activate our custom context menu.
14
14
  L.DomEvent.on(this.container, 'wheel', L.DomEvent.stopPropagation)
15
15
  L.DomEvent.on(this.container, 'MozMousePixelScroll', L.DomEvent.stopPropagation)
16
- this._panel = L.DomUtil.create('div', '', this.container)
17
- this._panel.id = 'umap-ui-container'
18
16
  this._alert = L.DomUtil.create('div', 'with-transition', this.container)
19
17
  this._alert.id = 'umap-alert-container'
20
18
  this._tooltip = L.DomUtil.create('div', '', this.container)
21
19
  this._tooltip.id = 'umap-tooltip-container'
22
20
  },
23
21
 
24
- resetPanelClassName: function () {
25
- this._panel.className = 'with-transition'
26
- },
27
-
28
- openPanel: function (e) {
29
- this.fire('panel:open')
30
- // We reset all because we can't know which class has been added
31
- // by previous ui processes...
32
- this.resetPanelClassName()
33
- this._panel.innerHTML = ''
34
- const actionsContainer = L.DomUtil.create('ul', 'toolbox', this._panel)
35
- const body = L.DomUtil.create('div', 'body', this._panel)
36
- if (e.data.html.nodeType && e.data.html.nodeType === 1)
37
- body.appendChild(e.data.html)
38
- else body.innerHTML = e.data.html
39
- const closeLink = L.DomUtil.create('li', 'umap-close-link', actionsContainer)
40
- L.DomUtil.add('i', 'umap-close-icon', closeLink)
41
- const label = L.DomUtil.create('span', '', closeLink)
42
- label.title = label.textContent = L._('Close')
43
- if (e.actions) {
44
- for (let i = 0; i < e.actions.length; i++) {
45
- actionsContainer.appendChild(e.actions[i])
46
- }
47
- }
48
- if (e.className) L.DomUtil.addClass(this._panel, e.className)
49
- if (L.DomUtil.hasClass(this.parent, 'umap-ui')) {
50
- // Already open.
51
- this.fire('panel:ready')
52
- } else {
53
- L.DomEvent.once(
54
- this._panel,
55
- 'transitionend',
56
- function (e) {
57
- this.fire('panel:ready')
58
- },
59
- this
60
- )
61
- L.DomUtil.addClass(this.parent, 'umap-ui')
62
- }
63
- L.DomEvent.on(closeLink, 'click', this.closePanel, this)
64
- },
65
-
66
- closePanel: function () {
67
- if (L.DomUtil.hasClass(this.parent, 'umap-ui')) {
68
- L.DomUtil.removeClass(this.parent, 'umap-ui')
69
- this.fire('panel:closed')
70
- }
71
- },
72
-
73
22
  alert: function (e) {
74
23
  if (L.DomUtil.hasClass(this.parent, 'umap-alert')) this.ALERTS.push(e)
75
24
  else this.popAlert(e)