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
@@ -29,38 +29,51 @@ U.ImportAction = U.BaseAction.extend({
29
29
  },
30
30
  })
31
31
 
32
- U.EditPropertiesAction = U.BaseAction.extend({
32
+ U.EditLayersAction = U.BaseAction.extend({
33
33
  options: {
34
34
  helpMenu: true,
35
- className: 'update-map-settings dark',
36
- tooltip: L._('Edit map properties'),
35
+ className: 'umap-control-browse dark',
36
+ tooltip: L._('Manage layers'),
37
37
  },
38
38
 
39
39
  addHooks: function () {
40
- this.map.edit()
40
+ this.map.editDatalayers()
41
41
  },
42
42
  })
43
43
 
44
- U.ChangeTileLayerAction = U.BaseAction.extend({
44
+ U.EditCaptionAction = U.BaseAction.extend({
45
45
  options: {
46
46
  helpMenu: true,
47
- className: 'dark update-map-tilelayers',
48
- tooltip: L._('Change tilelayers'),
47
+ className: 'umap-control-caption dark',
48
+ tooltip: L._('Edit map name and caption'),
49
49
  },
50
50
 
51
51
  addHooks: function () {
52
- this.map.updateTileLayers()
52
+ this.map.editCaption()
53
53
  },
54
54
  })
55
55
 
56
- U.ManageDatalayersAction = U.BaseAction.extend({
56
+ U.EditPropertiesAction = U.BaseAction.extend({
57
57
  options: {
58
- className: 'dark manage-datalayers',
59
- tooltip: L._('Manage layers'),
58
+ helpMenu: true,
59
+ className: 'update-map-settings dark',
60
+ tooltip: L._('Map advanced properties'),
61
+ },
62
+
63
+ addHooks: function () {
64
+ this.map.edit()
65
+ },
66
+ })
67
+
68
+ U.ChangeTileLayerAction = U.BaseAction.extend({
69
+ options: {
70
+ helpMenu: true,
71
+ className: 'dark update-map-tilelayers',
72
+ tooltip: L._('Change tilelayers'),
60
73
  },
61
74
 
62
75
  addHooks: function () {
63
- this.map.manageDatalayers()
76
+ this.map.updateTileLayers()
64
77
  },
65
78
  })
66
79
 
@@ -279,12 +292,7 @@ U.ContinueLineAction = U.BaseVertexAction.extend({
279
292
  })
280
293
 
281
294
  // Leaflet.Toolbar doesn't allow twice same toolbar class…
282
- U.SettingsToolbar = L.Toolbar.Control.extend({
283
- addTo: function (map) {
284
- if (map.options.editMode !== 'advanced') return
285
- L.Toolbar.Control.prototype.addTo.call(this, map)
286
- },
287
- })
295
+ U.SettingsToolbar = L.Toolbar.Control.extend({})
288
296
  U.DrawToolbar = L.Toolbar.Control.extend({
289
297
  initialize: function (options) {
290
298
  L.Toolbar.Control.prototype.initialize.call(this, options)
@@ -398,26 +406,6 @@ U.EditControl = L.Control.extend({
398
406
  },
399
407
  })
400
408
 
401
- /* Share control */
402
- L.Control.Embed = L.Control.extend({
403
- options: {
404
- position: 'topleft',
405
- },
406
-
407
- onAdd: function (map) {
408
- const container = L.DomUtil.create('div', 'leaflet-control-embed umap-control')
409
- const shareButton = L.DomUtil.createButton(
410
- '',
411
- container,
412
- L._('Share and download'),
413
- map.share.open,
414
- map.share
415
- )
416
- L.DomEvent.on(shareButton, 'dblclick', L.DomEvent.stopPropagation)
417
- return container
418
- },
419
- })
420
-
421
409
  U.MoreControls = L.Control.extend({
422
410
  options: {
423
411
  position: 'topleft',
@@ -476,7 +464,7 @@ U.PermanentCreditsControl = L.Control.extend({
476
464
  },
477
465
 
478
466
  setCredits: function () {
479
- this.paragraphContainer.innerHTML = L.Util.toHTML(this.map.options.permanentCredit)
467
+ this.paragraphContainer.innerHTML = U.Utils.toHTML(this.map.options.permanentCredit)
480
468
  },
481
469
 
482
470
  setBackground: function () {
@@ -488,174 +476,79 @@ U.PermanentCreditsControl = L.Control.extend({
488
476
  },
489
477
  })
490
478
 
491
- U.DataLayersControl = L.Control.extend({
492
- options: {
493
- position: 'topleft',
494
- },
495
-
496
- labels: {
497
- zoomToLayer: L._('Zoom to layer extent'),
498
- toggleLayer: L._('Show/hide layer'),
499
- editLayer: L._('Edit'),
500
- },
501
-
479
+ L.Control.Button = L.Control.extend({
502
480
  initialize: function (map, options) {
503
481
  this.map = map
504
482
  L.Control.prototype.initialize.call(this, options)
505
483
  },
506
484
 
507
- _initLayout: function (map) {
508
- const container = (this._container = L.DomUtil.create(
509
- 'div',
510
- 'leaflet-control-browse umap-control'
511
- )),
512
- actions = L.DomUtil.create('div', 'umap-browse-actions', container)
513
- this._datalayers_container = L.DomUtil.create(
514
- 'ul',
515
- 'umap-browse-datalayers',
516
- actions
517
- )
518
-
519
- L.DomUtil.createButton(
520
- 'umap-browse-link',
521
- actions,
522
- L._('Browse data'),
523
- map.openBrowser,
524
- map
525
- )
485
+ getClassName: function () {
486
+ return this.options.className
487
+ },
526
488
 
527
- const toggleButton = L.DomUtil.createButton(
528
- 'umap-browse-toggle',
489
+ onAdd: function (map) {
490
+ const container = L.DomUtil.create('div', `${this.getClassName()} umap-control`)
491
+ const button = L.DomUtil.createButton(
492
+ '',
529
493
  container,
530
- L._('See data layers')
494
+ this.options.title,
495
+ this.onClick,
496
+ this
531
497
  )
532
- L.DomEvent.on(toggleButton, 'click', L.DomEvent.stop)
533
-
534
- map.whenReady(function () {
535
- this.update()
536
- }, this)
537
-
538
- if (L.Browser.pointer) {
539
- L.DomEvent.disableClickPropagation(container)
540
- L.DomEvent.on(container, 'wheel', L.DomEvent.stopPropagation)
541
- L.DomEvent.on(container, 'MozMousePixelScroll', L.DomEvent.stopPropagation)
542
- }
543
- if (!L.Browser.touch) {
544
- L.DomEvent.on(
545
- container,
546
- {
547
- mouseenter: this.expand,
548
- mouseleave: this.collapse,
549
- },
550
- this
551
- )
552
- } else {
553
- L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation)
554
- L.DomEvent.on(toggleButton, 'click', L.DomEvent.stop).on(
555
- toggleButton,
556
- 'click',
557
- this.expand,
558
- this
559
- )
560
- map.on('click', this.collapse, this)
561
- }
562
-
498
+ L.DomEvent.on(button, 'dblclick', L.DomEvent.stopPropagation)
563
499
  return container
564
500
  },
501
+ })
565
502
 
566
- onAdd: function (map) {
567
- if (!this._container) this._initLayout(map)
568
- if (map.options.datalayersControl === 'expanded') this.expand()
569
- return this._container
503
+ U.DataLayersControl = L.Control.Button.extend({
504
+ options: {
505
+ position: 'topleft',
506
+ className: 'umap-control-browse',
507
+ title: L._('See layers'),
570
508
  },
571
509
 
572
- onRemove: function (map) {
573
- this.collapse()
510
+ onClick: function () {
511
+ this.map.openBrowser()
574
512
  },
513
+ })
575
514
 
576
- update: function () {
577
- if (this._datalayers_container && this._map) {
578
- this._datalayers_container.innerHTML = ''
579
- this.map.eachDataLayerReverse(function (datalayer) {
580
- this.addDataLayer(this._datalayers_container, datalayer)
581
- }, this)
582
- }
515
+ U.CaptionControl = L.Control.Button.extend({
516
+ options: {
517
+ position: 'topleft',
518
+ className: 'umap-control-caption',
519
+ title: L._('About'),
583
520
  },
584
521
 
585
- expand: function () {
586
- L.DomUtil.addClass(this._container, 'expanded')
522
+ onClick: function () {
523
+ this.map.displayCaption()
587
524
  },
525
+ })
588
526
 
589
- collapse: function () {
590
- if (this.map.options.datalayersControl === 'expanded') return
591
- L.DomUtil.removeClass(this._container, 'expanded')
527
+ U.StarControl = L.Control.Button.extend({
528
+ options: {
529
+ position: 'topleft',
530
+ title: L._('Star this map'),
592
531
  },
593
532
 
594
- addDataLayer: function (container, datalayer, draggable) {
595
- const datalayerLi = L.DomUtil.create('li', '', container)
596
- if (draggable)
597
- L.DomUtil.element(
598
- 'i',
599
- { className: 'drag-handle', title: L._('Drag to reorder') },
600
- datalayerLi
601
- )
602
- datalayer.renderToolbox(datalayerLi)
603
- const title = L.DomUtil.add(
604
- 'span',
605
- 'layer-title',
606
- datalayerLi,
607
- datalayer.options.name
608
- )
609
-
610
- datalayerLi.id = `browse_data_toggle_${L.stamp(datalayer)}`
611
- L.DomUtil.classIf(datalayerLi, 'off', !datalayer.isVisible())
612
-
613
- title.textContent = datalayer.options.name
533
+ getClassName: function () {
534
+ const status = this.map.options.starred ? ' starred' : ''
535
+ return `leaflet-control-star umap-control${status}`
614
536
  },
615
537
 
616
- newDataLayer: function () {
617
- const datalayer = this.map.createDataLayer({})
618
- datalayer.edit()
538
+ onClick: function () {
539
+ this.map.star()
619
540
  },
541
+ })
620
542
 
621
- openPanel: function () {
622
- if (!this.map.editEnabled) return
623
- const container = L.DomUtil.create('ul', 'umap-browse-datalayers')
624
- const title = L.DomUtil.create('h3', '', container)
625
- title.textContent = L._('Manage layers')
626
- this.map.eachDataLayerReverse(function (datalayer) {
627
- this.addDataLayer(container, datalayer, true)
628
- }, this)
629
- const orderable = new U.Orderable(container)
630
- orderable.on(
631
- 'drop',
632
- function (e) {
633
- const layer = this.map.datalayers[e.src.dataset.id],
634
- other = this.map.datalayers[e.dst.dataset.id],
635
- minIndex = Math.min(layer.getRank(), other.getRank()),
636
- maxIndex = Math.max(layer.getRank(), other.getRank())
637
- if (e.finalIndex === 0) layer.bringToTop()
638
- else if (e.finalIndex > e.initialIndex) layer.insertBefore(other)
639
- else layer.insertAfter(other)
640
- this.map.eachDataLayerReverse((datalayer) => {
641
- if (datalayer.getRank() >= minIndex && datalayer.getRank() <= maxIndex)
642
- datalayer.isDirty = true
643
- })
644
- this.map.indexDatalayers()
645
- },
646
- this
647
- )
648
-
649
- const bar = L.DomUtil.create('div', 'button-bar', container)
650
- L.DomUtil.createButton(
651
- 'show-on-edit block add-datalayer button',
652
- bar,
653
- L._('Add a layer'),
654
- this.newDataLayer,
655
- this
656
- )
543
+ L.Control.Embed = L.Control.Button.extend({
544
+ options: {
545
+ position: 'topleft',
546
+ title: L._('Share and download'),
547
+ className: 'leaflet-control-embed umap-control',
548
+ },
657
549
 
658
- this.map.ui.openPanel({ data: { html: container }, className: 'dark' })
550
+ onClick: function () {
551
+ this.map.share.open()
659
552
  },
660
553
  })
661
554
 
@@ -667,16 +560,31 @@ U.DataLayer.include({
667
560
  },
668
561
 
669
562
  renderToolbox: function (container) {
670
- const toggle = L.DomUtil.create('i', 'layer-toggle', container),
671
- zoomTo = L.DomUtil.create('i', 'layer-zoom_to', container),
672
- edit = L.DomUtil.create('i', 'layer-edit show-on-edit', container),
673
- table = L.DomUtil.create('i', 'layer-table-edit show-on-edit', container),
674
- remove = L.DomUtil.create('i', 'layer-delete show-on-edit', container)
675
- zoomTo.title = L._('Zoom to layer extent')
676
- toggle.title = L._('Show/hide layer')
677
- edit.title = L._('Edit')
678
- table.title = L._('Edit properties in a table')
679
- remove.title = L._('Delete layer')
563
+ const toggle = L.DomUtil.createButtonIcon(
564
+ container,
565
+ 'icon-eye',
566
+ L._('Show/hide layer')
567
+ )
568
+ const zoomTo = L.DomUtil.createButtonIcon(
569
+ container,
570
+ 'icon-zoom',
571
+ L._('Zoom to layer extent')
572
+ )
573
+ const edit = L.DomUtil.createButtonIcon(
574
+ container,
575
+ 'icon-edit show-on-edit',
576
+ L._('Edit')
577
+ )
578
+ const table = L.DomUtil.createButtonIcon(
579
+ container,
580
+ 'icon-table show-on-edit',
581
+ L._('Edit properties in a table')
582
+ )
583
+ const remove = L.DomUtil.createButtonIcon(
584
+ container,
585
+ 'icon-delete show-on-edit',
586
+ L._('Delete layer')
587
+ )
680
588
  if (this.isReadOnly()) {
681
589
  L.DomUtil.addClass(container, 'readonly')
682
590
  } else {
@@ -689,7 +597,7 @@ U.DataLayer.include({
689
597
  if (!this.isVisible()) return
690
598
  if (!confirm(L._('Are you sure you want to delete this layer?'))) return
691
599
  this._delete()
692
- this.map.ui.closePanel()
600
+ this.map.editPanel.close()
693
601
  },
694
602
  this
695
603
  )
@@ -698,7 +606,6 @@ U.DataLayer.include({
698
606
  L.DomEvent.on(zoomTo, 'click', this.zoomTo, this)
699
607
  L.DomUtil.addClass(container, this.getHidableClass())
700
608
  L.DomUtil.classIf(container, 'off', !this.isVisible())
701
- container.dataset.id = L.stamp(this)
702
609
  },
703
610
 
704
611
  getHidableElements: function () {
@@ -745,82 +652,25 @@ const ControlsMixin = {
745
652
  'search',
746
653
  'fullscreen',
747
654
  'embed',
655
+ 'datalayers',
656
+ 'caption',
748
657
  'locate',
749
658
  'measure',
750
659
  'editinosm',
751
- 'datalayers',
752
660
  'star',
753
661
  'tilelayers',
754
662
  ],
755
663
  _openFacet: function () {
756
- const container = L.DomUtil.create('div', 'umap-facet-search'),
757
- title = L.DomUtil.add('h3', 'umap-filter-title', container, L._('Facet search')),
758
- keys = Object.keys(this.getFacetKeys())
759
-
760
- const knownValues = {}
761
-
762
- keys.forEach((key) => {
763
- knownValues[key] = []
764
- if (!this.facets[key]) this.facets[key] = []
765
- })
766
-
767
- this.eachBrowsableDataLayer((datalayer) => {
768
- datalayer.eachFeature((feature) => {
769
- keys.forEach((key) => {
770
- let value = feature.properties[key]
771
- if (typeof value !== 'undefined' && !knownValues[key].includes(value)) {
772
- knownValues[key].push(value)
773
- }
774
- })
775
- })
776
- })
777
-
778
- const filterFeatures = function () {
779
- let found = false
780
- this.eachBrowsableDataLayer((datalayer) => {
781
- datalayer.resetLayer(true)
782
- if (datalayer.hasDataVisible()) found = true
783
- })
784
- // TODO: display a results counter in the panel instead.
785
- if (!found)
786
- this.ui.alert({ content: L._('No results for these facets'), level: 'info' })
787
- }
788
-
789
- const fields = keys.map((current) => [
790
- `facets.${current}`,
791
- {
792
- handler: 'FacetSearch',
793
- choices: knownValues[current],
794
- label: this.getFacetKeys()[current],
795
- },
796
- ])
797
- const builder = new U.FormBuilder(this, fields, {
798
- makeDirty: false,
799
- callback: filterFeatures,
800
- callbackContext: this,
801
- })
802
- container.appendChild(builder.build())
803
-
804
- this.ui.openPanel({ data: { html: container }, actions: [this._aboutLink()] })
805
- },
806
-
807
- _aboutLink: function () {
808
- const link = L.DomUtil.create('li', '')
809
- L.DomUtil.create('i', 'umap-icon-16 umap-caption', link)
810
- const label = L.DomUtil.create('span', '', link)
811
- label.textContent = label.title = L._('About')
812
- L.DomEvent.on(link, 'click', this.displayCaption, this)
813
- return link
664
+ this.facets.open()
814
665
  },
815
666
 
816
667
  displayCaption: function () {
817
668
  const container = L.DomUtil.create('div', 'umap-caption')
818
- let title = L.DomUtil.create('h3', '', container)
819
- title.textContent = this.options.name
669
+ L.DomUtil.createTitle(container, this.options.name, 'icon-caption')
820
670
  this.permissions.addOwnerLink('h5', container)
821
671
  if (this.options.description) {
822
672
  const description = L.DomUtil.create('div', 'umap-map-description', container)
823
- description.innerHTML = L.Util.toHTML(this.options.description)
673
+ description.innerHTML = U.Utils.toHTML(this.options.description)
824
674
  }
825
675
  const datalayerContainer = L.DomUtil.create('div', 'datalayer-container', container)
826
676
  this.eachVisibleDataLayer((datalayer) => {
@@ -832,7 +682,7 @@ const ControlsMixin = {
832
682
  datalayer.onceLoaded(function () {
833
683
  datalayer.renderLegend(legend)
834
684
  if (datalayer.options.description) {
835
- description.innerHTML = L.Util.toHTML(datalayer.options.description)
685
+ description.innerHTML = U.Utils.toHTML(datalayer.options.description)
836
686
  }
837
687
  })
838
688
  datalayer.renderToolbox(headline)
@@ -846,7 +696,7 @@ const ControlsMixin = {
846
696
  'p',
847
697
  '',
848
698
  credits,
849
- L.Util.toHTML(this.options.longCredit || this.options.shortCredit)
699
+ U.Utils.toHTML(this.options.longCredit || this.options.shortCredit)
850
700
  )
851
701
  }
852
702
  if (this.options.licence) {
@@ -891,21 +741,7 @@ const ControlsMixin = {
891
741
  `,
892
742
  urls
893
743
  )
894
- const browser = L.DomUtil.create('li', '')
895
- L.DomUtil.create('i', 'umap-icon-16 umap-list', browser)
896
- const labelBrowser = L.DomUtil.create('span', '', browser)
897
- labelBrowser.textContent = labelBrowser.title = L._('Browse data')
898
- L.DomEvent.on(browser, 'click', this.openBrowser, this)
899
- const actions = [browser]
900
- if (this.options.facetKey) {
901
- const filter = L.DomUtil.create('li', '')
902
- L.DomUtil.create('i', 'umap-icon-16 umap-add', filter)
903
- const labelFilter = L.DomUtil.create('span', '', filter)
904
- labelFilter.textContent = labelFilter.title = L._('Facet search')
905
- L.DomEvent.on(filter, 'click', this.openFacet, this)
906
- actions.push(filter)
907
- }
908
- this.ui.openPanel({ data: { html: container }, actions: actions })
744
+ this.panel.open({ content: container })
909
745
  },
910
746
 
911
747
  renderEditToolbar: function () {
@@ -981,7 +817,7 @@ const ControlsMixin = {
981
817
  L.DomUtil.createLink(
982
818
  'umap-user',
983
819
  rightContainer,
984
- L._(`My Dashboard <span>({username})</span>`, {
820
+ L._(`My Dashboard ({username})`, {
985
821
  username: this.options.user.name,
986
822
  }),
987
823
  this.options.user.url
@@ -1013,10 +849,7 @@ const ControlsMixin = {
1013
849
  'leaflet-control-edit-disable',
1014
850
  rightContainer,
1015
851
  L.DomUtil.add('span', '', null, L._('View')),
1016
- function (e) {
1017
- this.disableEdit(e)
1018
- this.ui.closePanel()
1019
- },
852
+ this.disableEdit,
1020
853
  this
1021
854
  )
1022
855
  L.DomEvent.on(
@@ -1055,6 +888,48 @@ const ControlsMixin = {
1055
888
  this
1056
889
  )
1057
890
  },
891
+
892
+ editDatalayers: function () {
893
+ if (!this.editEnabled) return
894
+ const container = L.DomUtil.create('div')
895
+ L.DomUtil.createTitle(container, L._('Manage layers'), 'icon-layers')
896
+ const ul = L.DomUtil.create('ul', '', container)
897
+ this.eachDataLayerReverse((datalayer) => {
898
+ const row = L.DomUtil.create('li', 'orderable', ul)
899
+ L.DomUtil.createIcon(row, 'icon-drag', L._('Drag to reorder'))
900
+ datalayer.renderToolbox(row)
901
+ const title = L.DomUtil.add('span', '', row, datalayer.options.name)
902
+ L.DomUtil.classIf(row, 'off', !datalayer.isVisible())
903
+ title.textContent = datalayer.options.name
904
+ row.dataset.id = L.stamp(datalayer)
905
+ })
906
+ const onReorder = (src, dst, initialIndex, finalIndex) => {
907
+ const layer = this.datalayers[src.dataset.id],
908
+ other = this.datalayers[dst.dataset.id],
909
+ minIndex = Math.min(layer.getRank(), other.getRank()),
910
+ maxIndex = Math.max(layer.getRank(), other.getRank())
911
+ if (finalIndex === 0) layer.bringToTop()
912
+ else if (finalIndex > initialIndex) layer.insertBefore(other)
913
+ else layer.insertAfter(other)
914
+ this.eachDataLayerReverse((datalayer) => {
915
+ if (datalayer.getRank() >= minIndex && datalayer.getRank() <= maxIndex)
916
+ datalayer.isDirty = true
917
+ })
918
+ this.indexDatalayers()
919
+ }
920
+ const orderable = new U.Orderable(ul, onReorder)
921
+
922
+ const bar = L.DomUtil.create('div', 'button-bar', container)
923
+ L.DomUtil.createButton(
924
+ 'show-on-edit block add-datalayer button',
925
+ bar,
926
+ L._('Add a layer'),
927
+ this.newDataLayer,
928
+ this
929
+ )
930
+
931
+ this.editPanel.open({ content: container })
932
+ },
1058
933
  }
1059
934
 
1060
935
  /* Used in view mode to define the current tilelayer */
@@ -1077,7 +952,7 @@ U.TileLayerControl = L.Control.IconLayers.extend({
1077
952
  // when the tilelayer is actually added to the map (needs this._tileZoom
1078
953
  // to be defined)
1079
954
  // Fixme when https://github.com/Leaflet/Leaflet/pull/9201 is released
1080
- const icon = L.Util.template(
955
+ const icon = U.Utils.template(
1081
956
  layer.options.url_template,
1082
957
  this.map.demoTileInfos
1083
958
  )
@@ -1124,12 +999,11 @@ U.TileLayerChooser = L.Control.extend({
1124
999
 
1125
1000
  openSwitcher: function (options) {
1126
1001
  const container = L.DomUtil.create('div', 'umap-tilelayer-switcher-container')
1127
- const title = L.DomUtil.create('h3', '', container)
1128
- title.textContent = L._('Change tilelayers')
1002
+ L.DomUtil.createTitle(container, L._('Change tilelayers'), 'icon-tilelayer')
1129
1003
  this._tilelayers_container = L.DomUtil.create('ul', '', container)
1130
1004
  this.buildList(options)
1131
- this.map.ui.openPanel({
1132
- data: { html: container },
1005
+ this.map.editPanel.open({
1006
+ content: container,
1133
1007
  className: options.className,
1134
1008
  })
1135
1009
  },
@@ -1150,7 +1024,7 @@ U.TileLayerChooser = L.Control.extend({
1150
1024
  el = L.DomUtil.create('li', selectedClass, this._tilelayers_container),
1151
1025
  img = L.DomUtil.create('img', '', el),
1152
1026
  name = L.DomUtil.create('div', '', el)
1153
- img.src = L.Util.template(tilelayer.options.url_template, this.map.demoTileInfos)
1027
+ img.src = U.Utils.template(tilelayer.options.url_template, this.map.demoTileInfos)
1154
1028
  img.loading = 'lazy'
1155
1029
  name.textContent = tilelayer.options.name
1156
1030
  L.DomEvent.on(
@@ -1187,7 +1061,7 @@ U.AttributionControl = L.Control.Attribution.extend({
1187
1061
  const shortCredit = this._map.getOption('shortCredit'),
1188
1062
  captionMenus = this._map.getOption('captionMenus')
1189
1063
  if (shortCredit) {
1190
- L.DomUtil.add('span', '', container, ` — ${L.Util.toHTML(shortCredit)}`)
1064
+ L.DomUtil.add('span', '', container, ` — ${U.Utils.toHTML(shortCredit)}`)
1191
1065
  }
1192
1066
  if (captionMenus) {
1193
1067
  const link = L.DomUtil.add('a', '', container, ` — ${L._('About')}`)
@@ -1211,29 +1085,6 @@ U.AttributionControl = L.Control.Attribution.extend({
1211
1085
  },
1212
1086
  })
1213
1087
 
1214
- U.StarControl = L.Control.extend({
1215
- options: {
1216
- position: 'topleft',
1217
- },
1218
-
1219
- onAdd: function (map) {
1220
- const status = map.options.starred ? ' starred' : ''
1221
- const container = L.DomUtil.create(
1222
- 'div',
1223
- `leaflet-control-star umap-control${status}`
1224
- )
1225
- const starMapButton = L.DomUtil.createButton(
1226
- '',
1227
- container,
1228
- L._('Star this map'),
1229
- map.star,
1230
- map
1231
- )
1232
- L.DomEvent.on(starMapButton, 'dblclick', L.DomEvent.stopPropagation)
1233
- return container
1234
- },
1235
- })
1236
-
1237
1088
  /*
1238
1089
  * Take control over L.Control.Locate to be able to
1239
1090
  * call start() before adding the control (and thus the button) to the map.
@@ -1260,7 +1111,7 @@ U.Locate = L.Control.Locate.extend({
1260
1111
  this._map = this.map
1261
1112
  L.Control.Locate.prototype._activate.call(this)
1262
1113
  this._map = null
1263
- }
1114
+ },
1264
1115
  })
1265
1116
 
1266
1117
  U.Search = L.PhotonSearch.extend({
@@ -1316,21 +1167,26 @@ U.Search = L.PhotonSearch.extend({
1316
1167
  },
1317
1168
 
1318
1169
  formatResult: function (feature, el) {
1319
- const self = this
1320
- const tools = L.DomUtil.create('span', 'search-result-tools', el),
1321
- zoom = L.DomUtil.create('i', 'feature-zoom_to', tools),
1322
- edit = L.DomUtil.create('i', 'feature-edit show-on-edit', tools)
1323
- zoom.title = L._('Zoom to this place')
1324
- edit.title = L._('Save this location as new feature')
1170
+ const tools = L.DomUtil.create('span', 'search-result-tools', el)
1171
+ const zoom = L.DomUtil.createButtonIcon(
1172
+ tools,
1173
+ 'icon-zoom',
1174
+ L._('Zoom to this place')
1175
+ )
1176
+ const edit = L.DomUtil.createButtonIcon(
1177
+ tools,
1178
+ 'icon-edit',
1179
+ L._('Save this location as new feature')
1180
+ )
1325
1181
  // We need to use "mousedown" because Leaflet.Photon listen to mousedown
1326
1182
  // on el.
1327
1183
  L.DomEvent.on(zoom, 'mousedown', (e) => {
1328
1184
  L.DomEvent.stop(e)
1329
- self.zoomToFeature(feature)
1185
+ this.zoomToFeature(feature)
1330
1186
  })
1331
1187
  L.DomEvent.on(edit, 'mousedown', (e) => {
1332
1188
  L.DomEvent.stop(e)
1333
- const datalayer = self.map.defaultEditDataLayer()
1189
+ const datalayer = this.map.defaultEditDataLayer()
1334
1190
  const layer = datalayer.geojsonToFeatures(feature)
1335
1191
  layer.isDirty = true
1336
1192
  layer.edit()
@@ -1348,7 +1204,7 @@ U.Search = L.PhotonSearch.extend({
1348
1204
 
1349
1205
  onSelected: function (feature) {
1350
1206
  this.zoomToFeature(feature)
1351
- this.map.ui.closePanel()
1207
+ this.map.panel.close()
1352
1208
  },
1353
1209
  })
1354
1210
 
@@ -1358,6 +1214,7 @@ U.SearchControl = L.Control.extend({
1358
1214
  },
1359
1215
 
1360
1216
  onAdd: function (map) {
1217
+ this.map = map
1361
1218
  const container = L.DomUtil.create('div', 'leaflet-control-search umap-control')
1362
1219
  L.DomEvent.disableClickPropagation(container)
1363
1220
  L.DomUtil.createButton(
@@ -1366,38 +1223,34 @@ U.SearchControl = L.Control.extend({
1366
1223
  L._('Search location'),
1367
1224
  (e) => {
1368
1225
  L.DomEvent.stop(e)
1369
- this.openPanel(map)
1226
+ this.open()
1370
1227
  },
1371
1228
  this
1372
1229
  )
1373
1230
  return container
1374
1231
  },
1375
1232
 
1376
- openPanel: function (map) {
1233
+ open: function () {
1377
1234
  const options = {
1378
1235
  limit: 10,
1379
1236
  noResultLabel: L._('No results'),
1380
1237
  }
1381
- if (map.options.photonUrl) options.url = map.options.photonUrl
1382
- const container = L.DomUtil.create('div', 'umap-search')
1238
+ if (this.map.options.photonUrl) options.url = this.map.options.photonUrl
1239
+ const container = L.DomUtil.create('div', '')
1383
1240
 
1384
- const title = L.DomUtil.create('h3', '', container)
1385
- title.textContent = L._('Search location')
1241
+ L.DomUtil.createTitle(container, L._('Search location'), 'icon-search')
1386
1242
  const input = L.DomUtil.create('input', 'photon-input', container)
1387
1243
  const resultsContainer = L.DomUtil.create('div', 'photon-autocomplete', container)
1388
- this.search = new U.Search(map, input, options)
1244
+ this.search = new U.Search(this.map, input, options)
1389
1245
  const id = Math.random()
1390
1246
  this.search.on('ajax:send', () => {
1391
- map.fire('dataloading', { id: id })
1247
+ this.map.fire('dataloading', { id: id })
1392
1248
  })
1393
1249
  this.search.on('ajax:return', () => {
1394
- map.fire('dataload', { id: id })
1250
+ this.map.fire('dataload', { id: id })
1395
1251
  })
1396
1252
  this.search.resultsContainer = resultsContainer
1397
- map.ui.once('panel:ready', () => {
1398
- input.focus()
1399
- })
1400
- map.ui.openPanel({ data: { html: container } })
1253
+ this.map.panel.open({ content: container }).then(input.focus)
1401
1254
  },
1402
1255
  })
1403
1256