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
@@ -56,6 +56,11 @@ U.Map = L.Map.extend({
56
56
  if (geojson.geometry) this.options.center = this.latLng(geojson.geometry)
57
57
  this.urls = new U.URLs(this.options.urls)
58
58
 
59
+ this.panel = new U.Panel(this)
60
+ if (this.hasEditMode()) {
61
+ this.editPanel = new U.EditPanel(this)
62
+ this.fullPanel = new U.FullPanel(this)
63
+ }
59
64
  this.ui = new U.UI(this._container)
60
65
  this.ui.on('dataloading', (e) => this.fire('dataloading', e))
61
66
  this.ui.on('dataload', (e) => this.fire('dataload', e))
@@ -69,6 +74,7 @@ U.Map = L.Map.extend({
69
74
  this.options.zoomControl = zoomControl !== undefined ? zoomControl : true
70
75
  this.options.fullscreenControl =
71
76
  fullscreenControl !== undefined ? fullscreenControl : true
77
+
72
78
  this.datalayersFromQueryString = L.Util.queryString('datalayers')
73
79
  if (this.datalayersFromQueryString) {
74
80
  this.datalayersFromQueryString = this.datalayersFromQueryString
@@ -100,17 +106,19 @@ U.Map = L.Map.extend({
100
106
  this.options.slideshow &&
101
107
  this.options.slideshow.delay &&
102
108
  this.options.slideshow.active === undefined
103
- )
109
+ ) {
104
110
  this.options.slideshow.active = true
105
- if (this.options.advancedFilterKey)
111
+ }
112
+ if (this.options.advancedFilterKey) {
106
113
  this.options.facetKey = this.options.advancedFilterKey
114
+ delete this.options.advancedFilterKey
115
+ }
107
116
 
108
117
  // Global storage for retrieving datalayers and features
109
118
  this.datalayers = {}
110
119
  this.datalayers_index = []
111
120
  this.dirty_datalayers = []
112
121
  this.features_index = {}
113
- this.facets = {}
114
122
 
115
123
  // Needed for actions labels
116
124
  this.help = new U.Help(this)
@@ -138,14 +146,9 @@ U.Map = L.Map.extend({
138
146
  }
139
147
  delete this.options.displayDataBrowserOnLoad
140
148
  }
141
-
142
- this.ui.on(
143
- 'panel:closed',
144
- function () {
145
- this.invalidateSize({ pan: false })
146
- },
147
- this
148
- )
149
+ if (this.options.datalayersControl === 'expanded') {
150
+ this.options.onLoadPanel = 'datalayers'
151
+ }
149
152
 
150
153
  let isDirty = false // self status
151
154
  try {
@@ -195,30 +198,29 @@ U.Map = L.Map.extend({
195
198
 
196
199
  this.slideshow = new U.Slideshow(this, this.options.slideshow)
197
200
  this.permissions = new U.MapPermissions(this)
198
- this.initCaptionBar()
199
201
  if (this.hasEditMode()) {
200
202
  this.editTools = new U.Editable(this)
201
- this.ui.on(
202
- 'panel:closed panel:open',
203
- function () {
204
- this.editedFeature = null
205
- },
206
- this
207
- )
208
203
  this.renderEditToolbar()
209
204
  }
210
205
  this.initShortcuts()
211
206
  this.onceDataLoaded(function () {
212
- if (L.Util.queryString('share')) this.share.open()
213
- else if (this.options.onLoadPanel === 'databrowser') this.openBrowser()
214
- else if (this.options.onLoadPanel === 'caption') this.displayCaption()
215
- else if (
216
- this.options.onLoadPanel === 'facet' ||
217
- this.options.onLoadPanel === 'datafilters'
218
- )
219
- this.openFacet()
220
207
  const slug = L.Util.queryString('feature')
221
208
  if (slug && this.features_index[slug]) this.features_index[slug].view()
209
+ if (this.options.noControl) return
210
+ this.initCaptionBar()
211
+ if (L.Util.queryString('share')) {
212
+ this.share.open()
213
+ } else if (this.options.onLoadPanel === 'databrowser') {
214
+ this.openBrowser('expanded')
215
+ } else if (this.options.onLoadPanel === 'datalayers') {
216
+ this.openBrowser('condensed')
217
+ } else if (this.options.onLoadPanel === 'caption') {
218
+ this.panel.mode = 'condensed'
219
+ this.displayCaption()
220
+ } else if (['facet', 'datafilters'].includes(this.options.onLoadPanel)) {
221
+ this.panel.mode = 'expanded'
222
+ this.openFacet()
223
+ }
222
224
  if (L.Util.queryString('edit')) {
223
225
  if (this.hasEditMode()) this.enableEdit()
224
226
  // Sometimes users share the ?edit link by mistake, let's remove
@@ -241,6 +243,44 @@ U.Map = L.Map.extend({
241
243
  this.on('click contextmenu.show', this.closeInplaceToolbar)
242
244
  },
243
245
 
246
+ render: function (fields) {
247
+ let impacts = U.Utils.getImpactsFromSchema(fields)
248
+
249
+ for (let impact of impacts) {
250
+ switch (impact) {
251
+ case 'ui':
252
+ this.initCaptionBar()
253
+ this.renderEditToolbar()
254
+ this.renderControls()
255
+ this.facets.redraw()
256
+ break
257
+ case 'data':
258
+ this.redrawVisibleDataLayers()
259
+ break
260
+ case 'datalayer-index':
261
+ this.reindexDataLayers()
262
+ break
263
+ case 'background':
264
+ this.initTileLayers()
265
+ break
266
+ case 'bounds':
267
+ this.handleLimitBounds()
268
+ break
269
+ }
270
+ }
271
+ },
272
+
273
+ reindexDataLayers: function () {
274
+ this.eachDataLayer((datalayer) => datalayer.reindex())
275
+ this.onDataLayersChanged()
276
+ },
277
+
278
+ redrawVisibleDataLayers: function () {
279
+ this.eachVisibleDataLayer((datalayer) => {
280
+ datalayer.redraw()
281
+ })
282
+ },
283
+
244
284
  setOptionsFromQueryString: function (options) {
245
285
  // This is not an editable option
246
286
  L.Util.setFromQueryString(options, 'editMode')
@@ -264,10 +304,12 @@ U.Map = L.Map.extend({
264
304
  // Specific case for datalayersControl
265
305
  // which accepts "expanded" value, on top of true/false/null
266
306
  if (L.Util.queryString('datalayersControl') === 'expanded') {
267
- L.Util.setFromQueryString(options, 'datalayersControl')
307
+ options.onLoadPanel = 'datalayers'
268
308
  }
269
309
  },
270
310
 
311
+ // Merge the given schema with the default one
312
+ // Missing keys inside the schema are merged with the default ones.
271
313
  overrideSchema: function (schema) {
272
314
  for (const [key, extra] of Object.entries(schema)) {
273
315
  U.SCHEMA[key] = L.extend({}, U.SCHEMA[key], extra)
@@ -282,22 +324,25 @@ U.Map = L.Map.extend({
282
324
  new U.EditControl(this).addTo(this)
283
325
 
284
326
  new U.DrawToolbar({ map: this }).addTo(this)
285
-
286
327
  const editActions = [
287
- U.ImportAction,
328
+ U.EditCaptionAction,
288
329
  U.EditPropertiesAction,
289
- U.ManageDatalayersAction,
330
+ U.EditLayersAction,
290
331
  U.ChangeTileLayerAction,
291
332
  U.UpdateExtentAction,
292
333
  U.UpdatePermsAction,
334
+ U.ImportAction,
293
335
  ]
294
- new U.SettingsToolbar({ actions: editActions }).addTo(this)
336
+ if (this.options.editMode === 'advanced') {
337
+ new U.SettingsToolbar({ actions: editActions }).addTo(this)
338
+ }
295
339
  }
296
340
  this._controls.zoom = new L.Control.Zoom({
297
341
  zoomInTitle: L._('Zoom in'),
298
342
  zoomOutTitle: L._('Zoom out'),
299
343
  })
300
344
  this._controls.datalayers = new U.DataLayersControl(this)
345
+ this._controls.caption = new U.CaptionControl(this)
301
346
  this._controls.locate = new U.Locate(this, {
302
347
  strings: {
303
348
  title: L._('Center map on your location'),
@@ -333,6 +378,7 @@ U.Map = L.Map.extend({
333
378
  if (this.options.scrollWheelZoom) this.scrollWheelZoom.enable()
334
379
  else this.scrollWheelZoom.disable()
335
380
  this.browser = new U.Browser(this)
381
+ this.facets = new U.Facets(this)
336
382
  this.importer = new U.Importer(this)
337
383
  this.drop = new U.DropControl(this)
338
384
  this.share = new U.Share(this)
@@ -420,7 +466,11 @@ U.Map = L.Map.extend({
420
466
  if (!pane.dataset || !pane.dataset.id) continue
421
467
  this.datalayers_index.push(this.datalayers[pane.dataset.id])
422
468
  }
423
- this.updateDatalayersControl()
469
+ this.onDataLayersChanged()
470
+ },
471
+
472
+ onDataLayersChanged: function () {
473
+ if (this.browser) this.browser.update()
424
474
  },
425
475
 
426
476
  ensurePanesOrder: function () {
@@ -449,10 +499,6 @@ U.Map = L.Map.extend({
449
499
  return this
450
500
  },
451
501
 
452
- updateDatalayersControl: function () {
453
- if (this._controls.datalayers) this._controls.datalayers.update()
454
- },
455
-
456
502
  backupOptions: function () {
457
503
  this._backupOptions = L.extend({}, this.options)
458
504
  this._backupOptions.tilelayer = L.extend({}, this.options.tilelayer)
@@ -476,8 +522,13 @@ U.Map = L.Map.extend({
476
522
  L.DomEvent.stop(e)
477
523
  this.search()
478
524
  } else if (e.keyCode === U.Keys.ESC) {
479
- if (this.help.visible()) this.help.hide()
480
- else this.ui.closePanel()
525
+ if (this.help.visible()) {
526
+ this.help.hide()
527
+ } else {
528
+ this.panel.close()
529
+ this.editPanel?.close()
530
+ this.fullPanel?.close()
531
+ }
481
532
  }
482
533
 
483
534
  if (!this.hasEditMode()) return
@@ -489,7 +540,6 @@ U.Map = L.Map.extend({
489
540
  } else if (key === U.Keys.E && modifierKey && this.editEnabled && !this.isDirty) {
490
541
  L.DomEvent.stop(e)
491
542
  this.disableEdit()
492
- this.ui.closePanel()
493
543
  }
494
544
  if (key === U.Keys.S && modifierKey) {
495
545
  L.DomEvent.stop(e)
@@ -668,7 +718,7 @@ U.Map = L.Map.extend({
668
718
  if (datalayer) {
669
719
  const feature = datalayer.getFeatureByIndex(-1)
670
720
  if (feature) {
671
- feature.zoomTo()
721
+ feature.zoomTo({ callback: this.options.noControl ? null : feature.view })
672
722
  return
673
723
  }
674
724
  }
@@ -727,12 +777,17 @@ U.Map = L.Map.extend({
727
777
  return new U.DataLayer(this, datalayer)
728
778
  },
729
779
 
780
+ newDataLayer: function () {
781
+ const datalayer = this.createDataLayer({})
782
+ datalayer.edit()
783
+ },
784
+
730
785
  getDefaultOption: function (option) {
731
786
  return U.SCHEMA[option] && U.SCHEMA[option].default
732
787
  },
733
788
 
734
789
  getOption: function (option) {
735
- if (L.Util.usableOption(this.options, option)) return this.options[option]
790
+ if (U.Utils.usableOption(this.options, option)) return this.options[option]
736
791
  return this.getDefaultOption(option)
737
792
  },
738
793
 
@@ -764,10 +819,6 @@ U.Map = L.Map.extend({
764
819
  })
765
820
  },
766
821
 
767
- manageDatalayers: function () {
768
- if (this._controls.datalayers) this._controls.datalayers.openPanel()
769
- },
770
-
771
822
  toGeoJSON: function () {
772
823
  let features = []
773
824
  this.eachDataLayer((datalayer) => {
@@ -789,7 +840,7 @@ U.Map = L.Map.extend({
789
840
  },
790
841
 
791
842
  processFileToImport: function (file, layer, type) {
792
- type = type || L.Util.detectFileType(file)
843
+ type = type || U.Utils.detectFileType(file)
793
844
  if (!type) {
794
845
  this.ui.alert({
795
846
  content: L._('Unable to detect format of file {filename}', {
@@ -856,7 +907,8 @@ U.Map = L.Map.extend({
856
907
  }
857
908
  },
858
909
 
859
- openBrowser: function () {
910
+ openBrowser: function (mode) {
911
+ if (mode) this.panel.mode = mode
860
912
  this.onceDatalayersLoaded(function () {
861
913
  this.browser.open()
862
914
  })
@@ -911,9 +963,9 @@ U.Map = L.Map.extend({
911
963
  })
912
964
  this.ensurePanesOrder()
913
965
  this.dirty_datalayers = []
914
- this.updateDatalayersControl()
915
966
  this.initTileLayers()
916
967
  this.isDirty = false
968
+ this.onDataLayersChanged()
917
969
  },
918
970
 
919
971
  checkDirty: function () {
@@ -1014,7 +1066,7 @@ U.Map = L.Map.extend({
1014
1066
  else window.location = data.url
1015
1067
  alert.content = data.info || alert.content
1016
1068
  this.once('saved', () => this.ui.alert(alert))
1017
- this.ui.closePanel()
1069
+ this.editPanel.close()
1018
1070
  this.permissions.save()
1019
1071
  }
1020
1072
  },
@@ -1127,13 +1179,7 @@ U.Map = L.Map.extend({
1127
1179
  'options.captionBar',
1128
1180
  'options.captionMenus',
1129
1181
  ])
1130
- builder = new U.FormBuilder(this, UIFields, {
1131
- callback: function () {
1132
- this.renderControls()
1133
- this.initCaptionBar()
1134
- },
1135
- callbackContext: this,
1136
- })
1182
+ builder = new U.FormBuilder(this, UIFields)
1137
1183
  const controlsOptions = L.DomUtil.createFieldset(
1138
1184
  container,
1139
1185
  L._('User interface options')
@@ -1156,14 +1202,7 @@ U.Map = L.Map.extend({
1156
1202
  'options.dashArray',
1157
1203
  ]
1158
1204
 
1159
- builder = new U.FormBuilder(this, shapeOptions, {
1160
- callback: function (e) {
1161
- if (this._controls.miniMap) this.renderControls()
1162
- this.eachVisibleDataLayer((datalayer) => {
1163
- datalayer.redraw()
1164
- })
1165
- },
1166
- })
1205
+ builder = new U.FormBuilder(this, shapeOptions)
1167
1206
  const defaultShapeProperties = L.DomUtil.createFieldset(
1168
1207
  container,
1169
1208
  L._('Default shape properties')
@@ -1199,9 +1238,9 @@ U.Map = L.Map.extend({
1199
1238
  [
1200
1239
  'options.facetKey',
1201
1240
  {
1202
- handler: 'Input',
1241
+ handler: 'BlurInput',
1203
1242
  helpEntries: 'facetKey',
1204
- placeholder: L._('Example: key1,key2,key3'),
1243
+ placeholder: L._('Example: key1,key2|Label 2,key3|Label 3|checkbox'),
1205
1244
  label: L._('Facet keys'),
1206
1245
  },
1207
1246
  ],
@@ -1216,14 +1255,7 @@ U.Map = L.Map.extend({
1216
1255
  ],
1217
1256
  ]
1218
1257
 
1219
- builder = new U.FormBuilder(this, optionsFields, {
1220
- callback: function (e) {
1221
- this.initCaptionBar()
1222
- if (e.helper.field === 'options.sortKey') {
1223
- this.eachDataLayer((datalayer) => datalayer.reindex())
1224
- }
1225
- },
1226
- })
1258
+ builder = new U.FormBuilder(this, optionsFields)
1227
1259
  const defaultProperties = L.DomUtil.createFieldset(
1228
1260
  container,
1229
1261
  L._('Default properties')
@@ -1241,20 +1273,7 @@ U.Map = L.Map.extend({
1241
1273
  'options.labelInteractive',
1242
1274
  'options.outlinkTarget',
1243
1275
  ]
1244
- builder = new U.FormBuilder(this, popupFields, {
1245
- callback: function (e) {
1246
- if (
1247
- e.helper.field === 'options.popupTemplate' ||
1248
- e.helper.field === 'options.popupContentTemplate' ||
1249
- e.helper.field === 'options.popupShape' ||
1250
- e.helper.field === 'options.outlinkTarget'
1251
- )
1252
- return
1253
- this.eachVisibleDataLayer((datalayer) => {
1254
- datalayer.redraw()
1255
- })
1256
- },
1257
- })
1276
+ builder = new U.FormBuilder(this, popupFields)
1258
1277
  const popupFieldset = L.DomUtil.createFieldset(
1259
1278
  container,
1260
1279
  L._('Default interaction options')
@@ -1263,7 +1282,7 @@ U.Map = L.Map.extend({
1263
1282
  },
1264
1283
 
1265
1284
  _editTilelayer: function (container) {
1266
- if (!L.Util.isObject(this.options.tilelayer)) {
1285
+ if (!U.Utils.isObject(this.options.tilelayer)) {
1267
1286
  this.options.tilelayer = {}
1268
1287
  }
1269
1288
  const tilelayerFields = [
@@ -1308,15 +1327,12 @@ U.Map = L.Map.extend({
1308
1327
  container,
1309
1328
  L._('Custom background')
1310
1329
  )
1311
- builder = new U.FormBuilder(this, tilelayerFields, {
1312
- callback: this.initTileLayers,
1313
- callbackContext: this,
1314
- })
1330
+ builder = new U.FormBuilder(this, tilelayerFields)
1315
1331
  customTilelayer.appendChild(builder.build())
1316
1332
  },
1317
1333
 
1318
1334
  _editOverlay: function (container) {
1319
- if (!L.Util.isObject(this.options.overlay)) {
1335
+ if (!U.Utils.isObject(this.options.overlay)) {
1320
1336
  this.options.overlay = {}
1321
1337
  }
1322
1338
  const overlayFields = [
@@ -1359,15 +1375,12 @@ U.Map = L.Map.extend({
1359
1375
  ['options.overlay.tms', { handler: 'Switch', label: L._('TMS format') }],
1360
1376
  ]
1361
1377
  const overlay = L.DomUtil.createFieldset(container, L._('Custom overlay'))
1362
- builder = new U.FormBuilder(this, overlayFields, {
1363
- callback: this.initTileLayers,
1364
- callbackContext: this,
1365
- })
1378
+ builder = new U.FormBuilder(this, overlayFields)
1366
1379
  overlay.appendChild(builder.build())
1367
1380
  },
1368
1381
 
1369
1382
  _editBounds: function (container) {
1370
- if (!L.Util.isObject(this.options.limitBounds)) {
1383
+ if (!U.Utils.isObject(this.options.limitBounds)) {
1371
1384
  this.options.limitBounds = {}
1372
1385
  }
1373
1386
  const limitBounds = L.DomUtil.createFieldset(container, L._('Limit bounds'))
@@ -1389,10 +1402,7 @@ U.Map = L.Map.extend({
1389
1402
  { handler: 'BlurFloatInput', placeholder: L._('max East') },
1390
1403
  ],
1391
1404
  ]
1392
- const boundsBuilder = new U.FormBuilder(this, boundsFields, {
1393
- callback: this.handleLimitBounds,
1394
- callbackContext: this,
1395
- })
1405
+ const boundsBuilder = new U.FormBuilder(this, boundsFields)
1396
1406
  limitBounds.appendChild(boundsBuilder.build())
1397
1407
  const boundsButtons = L.DomUtil.create('div', 'button-bar half', limitBounds)
1398
1408
  L.DomUtil.createButton(
@@ -1453,7 +1463,6 @@ U.Map = L.Map.extend({
1453
1463
  ]
1454
1464
  const slideshowHandler = function () {
1455
1465
  this.slideshow.setOptions(this.options.slideshow)
1456
- this.renderControls()
1457
1466
  }
1458
1467
  const slideshowBuilder = new U.FormBuilder(this, slideshowFields, {
1459
1468
  callback: slideshowHandler,
@@ -1462,22 +1471,6 @@ U.Map = L.Map.extend({
1462
1471
  slideshow.appendChild(slideshowBuilder.build())
1463
1472
  },
1464
1473
 
1465
- _editCredits: function (container) {
1466
- const credits = L.DomUtil.createFieldset(container, L._('Credits'))
1467
- const creditsFields = [
1468
- 'options.licence',
1469
- 'options.shortCredit',
1470
- 'options.longCredit',
1471
- 'options.permanentCredit',
1472
- 'options.permanentCreditBackground',
1473
- ]
1474
- const creditsBuilder = new U.FormBuilder(this, creditsFields, {
1475
- callback: this.renderControls,
1476
- callbackContext: this,
1477
- })
1478
- credits.appendChild(creditsBuilder.build())
1479
- },
1480
-
1481
1474
  _advancedActions: function (container) {
1482
1475
  const advancedActions = L.DomUtil.createFieldset(container, L._('Advanced actions'))
1483
1476
  const advancedButtons = L.DomUtil.create('div', 'button-bar half', advancedActions)
@@ -1520,18 +1513,37 @@ U.Map = L.Map.extend({
1520
1513
  )
1521
1514
  },
1522
1515
 
1523
- edit: function () {
1516
+ editCaption: function () {
1524
1517
  if (!this.editEnabled) return
1525
1518
  if (this.options.editMode !== 'advanced') return
1526
1519
  const container = L.DomUtil.create('div', 'umap-edit-container'),
1527
1520
  metadataFields = ['options.name', 'options.description'],
1528
1521
  title = L.DomUtil.create('h3', '', container)
1529
- title.textContent = L._('Edit map properties')
1522
+ title.textContent = L._('Edit map details')
1530
1523
  const builder = new U.FormBuilder(this, metadataFields, {
1531
1524
  className: 'map-metadata',
1532
1525
  })
1533
1526
  const form = builder.build()
1534
1527
  container.appendChild(form)
1528
+
1529
+ const credits = L.DomUtil.createFieldset(container, L._('Credits'))
1530
+ const creditsFields = [
1531
+ 'options.licence',
1532
+ 'options.shortCredit',
1533
+ 'options.longCredit',
1534
+ 'options.permanentCredit',
1535
+ 'options.permanentCreditBackground',
1536
+ ]
1537
+ const creditsBuilder = new U.FormBuilder(this, creditsFields)
1538
+ credits.appendChild(creditsBuilder.build())
1539
+ this.editPanel.open({ content: container })
1540
+ },
1541
+
1542
+ edit: function () {
1543
+ if (!this.editEnabled) return
1544
+ if (this.options.editMode !== 'advanced') return
1545
+ const container = L.DomUtil.create('div')
1546
+ L.DomUtil.createTitle(container, L._('Map advanced properties'), 'icon-settings')
1535
1547
  this._editControls(container)
1536
1548
  this._editShapeProperties(container)
1537
1549
  this._editDefaultProperties(container)
@@ -1540,10 +1552,9 @@ U.Map = L.Map.extend({
1540
1552
  this._editOverlay(container)
1541
1553
  this._editBounds(container)
1542
1554
  this._editSlideshow(container)
1543
- this._editCredits(container)
1544
1555
  this._advancedActions(container)
1545
1556
 
1546
- this.ui.openPanel({ data: { html: container }, className: 'dark' })
1557
+ this.editPanel.open({ content: container, className: 'dark' })
1547
1558
  },
1548
1559
 
1549
1560
  enableEdit: function () {
@@ -1560,6 +1571,8 @@ U.Map = L.Map.extend({
1560
1571
  this.editedFeature = null
1561
1572
  this.editEnabled = false
1562
1573
  this.fire('edit:disabled')
1574
+ this.editPanel.close()
1575
+ this.fullPanel.close()
1563
1576
  },
1564
1577
 
1565
1578
  hasEditMode: function () {
@@ -1591,8 +1604,7 @@ U.Map = L.Map.extend({
1591
1604
  'umap-open-browser-link flat',
1592
1605
  container,
1593
1606
  L._('Browse data'),
1594
- this.openBrowser,
1595
- this
1607
+ () => this.openBrowser('expanded')
1596
1608
  )
1597
1609
  if (this.options.facetKey) {
1598
1610
  L.DomUtil.createButton(
@@ -1617,8 +1629,7 @@ U.Map = L.Map.extend({
1617
1629
  askForReset: function (e) {
1618
1630
  if (!confirm(L._('Are you sure you want to cancel your changes?'))) return
1619
1631
  this.reset()
1620
- this.disableEdit(e)
1621
- this.ui.closePanel()
1632
+ this.disableEdit()
1622
1633
  },
1623
1634
 
1624
1635
  startMarker: function () {
@@ -1734,10 +1745,17 @@ U.Map = L.Map.extend({
1734
1745
  })
1735
1746
  }
1736
1747
  }
1737
- items.push('-', {
1738
- text: L._('Browse data'),
1739
- callback: this.openBrowser,
1740
- })
1748
+ items.push(
1749
+ '-',
1750
+ {
1751
+ text: L._('See layers'),
1752
+ callback: () => this.openBrowser('condensed'),
1753
+ },
1754
+ {
1755
+ text: L._('Browse data'),
1756
+ callback: () => this.openBrowser('expanded'),
1757
+ }
1758
+ )
1741
1759
  if (this.options.facetKey) {
1742
1760
  items.push({
1743
1761
  text: L._('Facet search'),
@@ -1760,14 +1778,29 @@ U.Map = L.Map.extend({
1760
1778
  callback: this.openExternalRouting,
1761
1779
  })
1762
1780
  }
1781
+ if (this.options.urls.edit_in_osm) {
1782
+ items.push('-', {
1783
+ text: L._('Edit in OpenStreetMap'),
1784
+ callback: this.editInOSM,
1785
+ })
1786
+ }
1763
1787
  this.options.contextmenuItems = items
1764
1788
  },
1765
1789
 
1790
+ editInOSM: function (e) {
1791
+ const url = this.urls.get('edit_in_osm', {
1792
+ lat: e.latlng.lat,
1793
+ lng: e.latlng.lng,
1794
+ zoom: Math.max(this.getZoom(), 16),
1795
+ })
1796
+ if (url) window.open(url)
1797
+ },
1798
+
1766
1799
  openExternalRouting: function (e) {
1767
1800
  const url = this.urls.get('routing', {
1768
1801
  lat: e.latlng.lat,
1769
1802
  lng: e.latlng.lng,
1770
- locale: L.locale,
1803
+ locale: L.getLocale(),
1771
1804
  zoom: this.getZoom(),
1772
1805
  })
1773
1806
  if (url) window.open(url)
@@ -1796,12 +1829,12 @@ U.Map = L.Map.extend({
1796
1829
  },
1797
1830
 
1798
1831
  localizeUrl: function (url) {
1799
- return L.Util.greedyTemplate(url, this.getGeoContext(), true)
1832
+ return U.Utils.greedyTemplate(url, this.getGeoContext(), true)
1800
1833
  },
1801
1834
 
1802
1835
  proxyUrl: function (url, ttl) {
1803
1836
  if (this.options.urls.ajax_proxy) {
1804
- url = L.Util.greedyTemplate(this.options.urls.ajax_proxy, {
1837
+ url = U.Utils.greedyTemplate(this.options.urls.ajax_proxy, {
1805
1838
  url: encodeURIComponent(url),
1806
1839
  ttl: ttl,
1807
1840
  })
@@ -1815,21 +1848,13 @@ U.Map = L.Map.extend({
1815
1848
  },
1816
1849
 
1817
1850
  search: function () {
1818
- if (this._controls.search) this._controls.search.openPanel(this)
1851
+ if (this._controls.search) this._controls.search.open()
1819
1852
  },
1820
1853
 
1821
1854
  getFilterKeys: function () {
1822
1855
  return (this.options.filterKey || this.options.sortKey || 'name').split(',')
1823
1856
  },
1824
1857
 
1825
- getFacetKeys: function () {
1826
- return (this.options.facetKey || '').split(',').reduce((acc, curr) => {
1827
- const els = curr.split('|')
1828
- acc[els[0]] = els[1] || els[0]
1829
- return acc
1830
- }, {})
1831
- },
1832
-
1833
1858
  getLayersBounds: function () {
1834
1859
  const bounds = new L.latLngBounds()
1835
1860
  this.eachBrowsableDataLayer((d) => {