umap-project 3.4.0b1__py3-none-any.whl → 3.4.2__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.
Files changed (202) hide show
  1. umap/__init__.py +1 -1
  2. umap/context_processors.py +1 -1
  3. umap/locale/da/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/da/LC_MESSAGES/django.po +20 -16
  5. umap/locale/en/LC_MESSAGES/django.po +18 -14
  6. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/es/LC_MESSAGES/django.po +20 -16
  8. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  9. umap/locale/fr/LC_MESSAGES/django.po +18 -14
  10. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  11. umap/locale/pl/LC_MESSAGES/django.po +72 -71
  12. umap/migrations/0018_datalayer_uuid.py +1 -1
  13. umap/models.py +7 -3
  14. umap/settings/local.py.sample +1 -1
  15. umap/static/umap/content.css +0 -3
  16. umap/static/umap/css/bar.css +9 -6
  17. umap/static/umap/css/form.css +27 -11
  18. umap/static/umap/css/popup.css +1 -0
  19. umap/static/umap/js/components/base.js +1 -1
  20. umap/static/umap/js/components/copiable.js +47 -0
  21. umap/static/umap/js/modules/autocomplete.js +31 -58
  22. umap/static/umap/js/modules/browser.js +8 -8
  23. umap/static/umap/js/modules/data/features.js +33 -36
  24. umap/static/umap/js/modules/data/fields.js +446 -0
  25. umap/static/umap/js/modules/data/layer.js +76 -93
  26. umap/static/umap/js/modules/domutils.js +24 -4
  27. umap/static/umap/js/modules/filters.js +20 -47
  28. umap/static/umap/js/modules/form/fields.js +4 -4
  29. umap/static/umap/js/modules/formatter.js +9 -1
  30. umap/static/umap/js/modules/help.js +13 -14
  31. umap/static/umap/js/modules/i18n.js +1 -1
  32. umap/static/umap/js/modules/importer.js +18 -27
  33. umap/static/umap/js/modules/importers/banfr.js +0 -1
  34. umap/static/umap/js/modules/importers/cadastrefr.js +19 -19
  35. umap/static/umap/js/modules/importers/communesfr.js +7 -8
  36. umap/static/umap/js/modules/importers/datasets.js +14 -14
  37. umap/static/umap/js/modules/importers/geodatamine.js +20 -22
  38. umap/static/umap/js/modules/importers/opendata.js +10 -0
  39. umap/static/umap/js/modules/importers/overpass.js +19 -18
  40. umap/static/umap/js/modules/managers.js +1 -265
  41. umap/static/umap/js/modules/permissions.js +5 -3
  42. umap/static/umap/js/modules/rendering/controls.js +6 -4
  43. umap/static/umap/js/modules/rendering/icon.js +5 -9
  44. umap/static/umap/js/modules/rendering/layers/base.js +1 -1
  45. umap/static/umap/js/modules/rendering/layers/classified.js +16 -11
  46. umap/static/umap/js/modules/rendering/layers/heat.js +27 -21
  47. umap/static/umap/js/modules/rendering/map.js +22 -22
  48. umap/static/umap/js/modules/rendering/popup.js +6 -3
  49. umap/static/umap/js/modules/rendering/template.js +31 -37
  50. umap/static/umap/js/modules/rendering/ui.js +1 -2
  51. umap/static/umap/js/modules/rules.js +34 -41
  52. umap/static/umap/js/modules/schema.js +0 -7
  53. umap/static/umap/js/modules/share.js +36 -69
  54. umap/static/umap/js/modules/slideshow.js +3 -3
  55. umap/static/umap/js/modules/tableeditor.js +0 -1
  56. umap/static/umap/js/modules/ui/bar.js +51 -32
  57. umap/static/umap/js/modules/ui/dialog.js +10 -1
  58. umap/static/umap/js/modules/ui/panel.js +28 -23
  59. umap/static/umap/js/modules/ui/tooltip.js +1 -1
  60. umap/static/umap/js/modules/umap.js +84 -84
  61. umap/static/umap/js/modules/utils.js +13 -4
  62. umap/static/umap/js/umap.controls.js +33 -14
  63. umap/static/umap/locale/am_ET.js +19 -8
  64. umap/static/umap/locale/am_ET.json +19 -8
  65. umap/static/umap/locale/ar.js +19 -8
  66. umap/static/umap/locale/ar.json +19 -8
  67. umap/static/umap/locale/ast.js +19 -8
  68. umap/static/umap/locale/ast.json +19 -8
  69. umap/static/umap/locale/bg.js +19 -8
  70. umap/static/umap/locale/bg.json +19 -8
  71. umap/static/umap/locale/br.js +20 -9
  72. umap/static/umap/locale/br.json +20 -9
  73. umap/static/umap/locale/ca.js +19 -8
  74. umap/static/umap/locale/ca.json +19 -8
  75. umap/static/umap/locale/cs_CZ.js +20 -9
  76. umap/static/umap/locale/cs_CZ.json +20 -9
  77. umap/static/umap/locale/da.js +54 -43
  78. umap/static/umap/locale/da.json +54 -43
  79. umap/static/umap/locale/de.js +44 -33
  80. umap/static/umap/locale/de.json +44 -33
  81. umap/static/umap/locale/el.js +20 -9
  82. umap/static/umap/locale/el.json +20 -9
  83. umap/static/umap/locale/en.js +20 -9
  84. umap/static/umap/locale/en.json +20 -9
  85. umap/static/umap/locale/en_US.json +19 -8
  86. umap/static/umap/locale/es.js +55 -44
  87. umap/static/umap/locale/es.json +55 -44
  88. umap/static/umap/locale/et.js +20 -9
  89. umap/static/umap/locale/et.json +20 -9
  90. umap/static/umap/locale/eu.js +25 -14
  91. umap/static/umap/locale/eu.json +25 -14
  92. umap/static/umap/locale/fa_IR.js +20 -9
  93. umap/static/umap/locale/fa_IR.json +20 -9
  94. umap/static/umap/locale/fi.js +19 -8
  95. umap/static/umap/locale/fi.json +19 -8
  96. umap/static/umap/locale/fr.js +21 -10
  97. umap/static/umap/locale/fr.json +21 -10
  98. umap/static/umap/locale/gl.js +147 -136
  99. umap/static/umap/locale/gl.json +147 -136
  100. umap/static/umap/locale/he.js +19 -8
  101. umap/static/umap/locale/he.json +19 -8
  102. umap/static/umap/locale/hr.js +19 -8
  103. umap/static/umap/locale/hr.json +19 -8
  104. umap/static/umap/locale/hu.js +62 -51
  105. umap/static/umap/locale/hu.json +62 -51
  106. umap/static/umap/locale/id.js +19 -8
  107. umap/static/umap/locale/id.json +19 -8
  108. umap/static/umap/locale/is.js +20 -9
  109. umap/static/umap/locale/is.json +20 -9
  110. umap/static/umap/locale/it.js +20 -9
  111. umap/static/umap/locale/it.json +20 -9
  112. umap/static/umap/locale/ja.js +19 -8
  113. umap/static/umap/locale/ja.json +19 -8
  114. umap/static/umap/locale/ko.js +19 -8
  115. umap/static/umap/locale/ko.json +19 -8
  116. umap/static/umap/locale/lt.js +19 -8
  117. umap/static/umap/locale/lt.json +19 -8
  118. umap/static/umap/locale/ms.js +20 -9
  119. umap/static/umap/locale/ms.json +20 -9
  120. umap/static/umap/locale/nl.js +20 -9
  121. umap/static/umap/locale/nl.json +20 -9
  122. umap/static/umap/locale/no.js +19 -8
  123. umap/static/umap/locale/no.json +19 -8
  124. umap/static/umap/locale/pl.js +56 -45
  125. umap/static/umap/locale/pl.json +56 -45
  126. umap/static/umap/locale/pl_PL.json +19 -8
  127. umap/static/umap/locale/pt.js +20 -9
  128. umap/static/umap/locale/pt.json +20 -9
  129. umap/static/umap/locale/pt_BR.js +19 -8
  130. umap/static/umap/locale/pt_BR.json +19 -8
  131. umap/static/umap/locale/pt_PT.js +19 -8
  132. umap/static/umap/locale/pt_PT.json +19 -8
  133. umap/static/umap/locale/ro.js +19 -8
  134. umap/static/umap/locale/ro.json +19 -8
  135. umap/static/umap/locale/ru.js +19 -8
  136. umap/static/umap/locale/ru.json +19 -8
  137. umap/static/umap/locale/si.js +1 -1
  138. umap/static/umap/locale/si.json +1 -1
  139. umap/static/umap/locale/sk_SK.js +19 -8
  140. umap/static/umap/locale/sk_SK.json +19 -8
  141. umap/static/umap/locale/sl.js +19 -8
  142. umap/static/umap/locale/sl.json +19 -8
  143. umap/static/umap/locale/sr.js +19 -8
  144. umap/static/umap/locale/sr.json +19 -8
  145. umap/static/umap/locale/sv.js +19 -8
  146. umap/static/umap/locale/sv.json +19 -8
  147. umap/static/umap/locale/th_TH.js +19 -8
  148. umap/static/umap/locale/th_TH.json +19 -8
  149. umap/static/umap/locale/tr.js +19 -8
  150. umap/static/umap/locale/tr.json +19 -8
  151. umap/static/umap/locale/uk_UA.js +19 -8
  152. umap/static/umap/locale/uk_UA.json +19 -8
  153. umap/static/umap/locale/vi.js +19 -8
  154. umap/static/umap/locale/vi.json +19 -8
  155. umap/static/umap/locale/vi_VN.json +19 -8
  156. umap/static/umap/locale/zh.js +19 -8
  157. umap/static/umap/locale/zh.json +19 -8
  158. umap/static/umap/locale/zh_CN.json +19 -8
  159. umap/static/umap/locale/zh_TW.Big5.json +19 -8
  160. umap/static/umap/locale/zh_TW.js +53 -42
  161. umap/static/umap/locale/zh_TW.json +53 -42
  162. umap/static/umap/map.css +8 -7
  163. umap/static/umap/unittests/utils.js +7 -7
  164. umap/templates/umap/content_footer.html +1 -0
  165. umap/templates/umap/css.html +0 -2
  166. umap/templates/umap/js.html +1 -3
  167. umap/templates/umap/login_popup_end.html +2 -2
  168. umap/tests/integration/conftest.py +11 -2
  169. umap/tests/integration/test_anonymous_owned_map.py +2 -2
  170. umap/tests/integration/test_conditional_rules.py +107 -52
  171. umap/tests/integration/test_draw_polygon.py +4 -0
  172. umap/tests/integration/test_draw_polyline.py +11 -0
  173. umap/tests/integration/test_edit_datalayer.py +1 -1
  174. umap/tests/integration/test_fields.py +19 -0
  175. umap/tests/integration/test_filters.py +6 -7
  176. umap/tests/integration/test_iframe.py +1 -1
  177. umap/tests/integration/test_import.py +23 -0
  178. umap/tests/integration/test_map.py +2 -2
  179. umap/tests/integration/test_map_preview.py +1 -1
  180. umap/tests/integration/test_owned_map.py +2 -2
  181. umap/tests/integration/test_picto.py +1 -1
  182. umap/tests/integration/test_popup.py +31 -0
  183. umap/tests/integration/test_remote_data.py +4 -4
  184. umap/tests/integration/test_save.py +1 -1
  185. umap/tests/integration/test_search.py +41 -0
  186. umap/tests/integration/test_share.py +2 -2
  187. umap/tests/integration/test_team.py +1 -1
  188. umap/tests/integration/test_websocket_sync.py +69 -20
  189. umap/tests/test_dashboard.py +1 -1
  190. umap/tests/test_statics.py +2 -2
  191. umap/tests/test_utils.py +4 -1
  192. umap/tests/test_views.py +1 -1
  193. umap/utils.py +3 -2
  194. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/METADATA +17 -17
  195. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/RECORD +198 -199
  196. umap/static/umap/js/umap.core.js +0 -93
  197. umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.css +0 -46
  198. umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.js +0 -240
  199. umap/static/umap/vendors/editinosm/edit-in-osm.png +0 -0
  200. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/WHEEL +0 -0
  201. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/entry_points.txt +0 -0
  202. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,8 +1,3 @@
1
- import {
2
- DomUtil,
3
- Util as LeafletUtil,
4
- latLngBounds,
5
- } from '../../vendors/leaflet/leaflet-src.esm.js'
6
1
  import {
7
2
  uMapAlert as Alert,
8
3
  uMapAlertCreation as AlertCreation,
@@ -10,6 +5,7 @@ import {
10
5
  import Browser from './browser.js'
11
6
  import Caption from './caption.js'
12
7
  import { DataLayer } from './data/layer.js'
8
+ import { Fields } from './data/fields.js'
13
9
  import { Filters, migrateLegacyFilters } from './filters.js'
14
10
  import { MutatingForm } from './form/builder.js'
15
11
  import { Formatter } from './formatter.js'
@@ -33,7 +29,7 @@ import Tooltip from './ui/tooltip.js'
33
29
  import URLs from './urls.js'
34
30
  import * as Utils from './utils.js'
35
31
  import * as DOMUtils from './domutils.js'
36
- import { DataLayerManager, FieldManager } from './managers.js'
32
+ import { DataLayerManager } from './managers.js'
37
33
  import { Importer as OpenRouteService } from './importers/openrouteservice.js'
38
34
 
39
35
  export default class Umap {
@@ -133,7 +129,7 @@ export default class Umap {
133
129
  this.contextmenu = new ContextMenu()
134
130
  this.server = new ServerRequest()
135
131
  this.request = new Request()
136
- this.fields = new FieldManager(this, this.dialog)
132
+ this.fields = new Fields(this, this.dialog)
137
133
  this.filters = new Filters(this, this)
138
134
  this.browser = new Browser(this, this._leafletMap)
139
135
  this.caption = new Caption(this, this._leafletMap)
@@ -260,15 +256,6 @@ export default class Umap {
260
256
  return window.self !== window.top
261
257
  }
262
258
 
263
- get fieldKeys() {
264
- return Array.from(
265
- new Set([
266
- ...this.fields.keys(),
267
- ...this.datalayers.active().reduce((acc, dl) => acc.concat(dl.fieldKeys), []),
268
- ])
269
- )
270
- }
271
-
272
259
  setPropertiesFromQueryString() {
273
260
  const asBoolean = (key) => {
274
261
  const value = this.searchParams.get(key)
@@ -389,6 +376,10 @@ export default class Umap {
389
376
  }
390
377
 
391
378
  hasFilters() {
379
+ return this.filters.size || this.datalayers.active().some((d) => d.filters.size)
380
+ }
381
+
382
+ hasActiveFilters() {
392
383
  return (
393
384
  this.filters.isActive() ||
394
385
  this.datalayers.active().some((d) => d.filters.isActive())
@@ -676,7 +667,7 @@ export default class Umap {
676
667
  const parent = this._leafletMap.getPane('overlayPane')
677
668
  const datalayers = Object.values(this.datalayers)
678
669
  .filter((datalayer) => !datalayer._isDeleted)
679
- .sort((datalayer1, datalayer2) => datalayer1.rank > datalayer2.rank)
670
+ .sort((datalayer1, datalayer2) => datalayer1.rank - datalayer2.rank)
680
671
  for (const datalayer of datalayers) {
681
672
  const child = parent.querySelector(`[data-id="${datalayer.id}"]`)
682
673
  parent.appendChild(child)
@@ -768,14 +759,19 @@ export default class Umap {
768
759
  editCaption() {
769
760
  if (!this.editEnabled) return
770
761
  if (this.properties.editMode !== 'advanced') return
771
- const container = DomUtil.create('div')
762
+ const container = DOMUtils.loadTemplate(`
763
+ <div>
764
+ <h3>
765
+ <i class="icon icon-16 icon-info"></i>
766
+ ${translate('Edit map details')}
767
+ </h3>
768
+ </div>
769
+ `)
772
770
  const metadataFields = [
773
771
  'properties.name',
774
772
  'properties.description',
775
773
  'properties.is_template',
776
774
  ]
777
-
778
- DomUtil.createTitle(container, translate('Edit map details'), 'icon-info')
779
775
  const builder = new MutatingForm(this, metadataFields, {
780
776
  className: 'map-metadata',
781
777
  umap: this,
@@ -783,13 +779,13 @@ export default class Umap {
783
779
  const form = builder.build()
784
780
  container.appendChild(form)
785
781
 
786
- const tags = DomUtil.createFieldset(container, translate('Tags'))
782
+ const tags = DOMUtils.createFieldset(container, translate('Tags'))
787
783
  const tagsFields = ['properties.tags']
788
784
  const tagsBuilder = new MutatingForm(this, tagsFields, {
789
785
  umap: this,
790
786
  })
791
787
  tags.appendChild(tagsBuilder.build())
792
- const credits = DomUtil.createFieldset(container, translate('Credits'))
788
+ const credits = DOMUtils.createFieldset(container, translate('Credits'))
793
789
  const creditsFields = [
794
790
  'properties.licence',
795
791
  'properties.shortCredit',
@@ -805,7 +801,11 @@ export default class Umap {
805
801
  editCenter() {
806
802
  if (!this.editEnabled) return
807
803
  if (this.properties.editMode !== 'advanced') return
808
- const container = DomUtil.create('div')
804
+ const container = DOMUtils.loadTemplate(`
805
+ <div>
806
+ <h3><i class="icon icon-16 icon-zoom"></i>${translate('Edit map default view')}</h3>
807
+ </div>
808
+ `)
809
809
  const metadataFields = [
810
810
  ['properties.zoom', { handler: 'IntInput', label: translate('Default zoom') }],
811
811
  [
@@ -819,13 +819,12 @@ export default class Umap {
819
819
  'properties.defaultView',
820
820
  ]
821
821
 
822
- DomUtil.createTitle(container, translate('Edit map default view'), 'icon-zoom')
823
822
  const builder = new MutatingForm(this, metadataFields, {
824
823
  className: 'map-metadata',
825
824
  umap: this,
826
825
  })
827
826
  const form = builder.build()
828
- const button = Utils.loadTemplate(
827
+ const button = DOMUtils.loadTemplate(
829
828
  `<button type="button">${translate('Use current center and zoom')}</button>`
830
829
  )
831
830
  button.addEventListener('click', () => {
@@ -854,7 +853,7 @@ export default class Umap {
854
853
  'properties.layerSwitcher',
855
854
  ])
856
855
  const builder = new MutatingForm(this, UIFields, { umap: this })
857
- const controlsOptions = DomUtil.createFieldset(
856
+ const controlsOptions = DOMUtils.createFieldset(
858
857
  container,
859
858
  translate('User interface options')
860
859
  )
@@ -878,7 +877,7 @@ export default class Umap {
878
877
  ]
879
878
 
880
879
  const builder = new MutatingForm(this, shapeOptions, { umap: this })
881
- const defaultShapeProperties = DomUtil.createFieldset(
880
+ const defaultShapeProperties = DOMUtils.createFieldset(
882
881
  container,
883
882
  translate('Default shape properties')
884
883
  )
@@ -896,7 +895,7 @@ export default class Umap {
896
895
  ]
897
896
 
898
897
  const builder = new MutatingForm(this, shapeOptions, { umap: this })
899
- const defaultShapeProperties = DomUtil.createFieldset(
898
+ const defaultShapeProperties = DOMUtils.createFieldset(
900
899
  container,
901
900
  translate('Default properties')
902
901
  )
@@ -914,7 +913,7 @@ export default class Umap {
914
913
  'properties.outlinkTarget',
915
914
  ]
916
915
  const builder = new MutatingForm(this, popupFields, { umap: this })
917
- const popupFieldset = DomUtil.createFieldset(
916
+ const popupFieldset = DOMUtils.createFieldset(
918
917
  container,
919
918
  translate('Default interaction options')
920
919
  )
@@ -966,7 +965,7 @@ export default class Umap {
966
965
  { handler: 'Switch', label: translate('TMS format') },
967
966
  ],
968
967
  ]
969
- const customTilelayer = DomUtil.createFieldset(
968
+ const customTilelayer = DOMUtils.createFieldset(
970
969
  container,
971
970
  translate('Custom background')
972
971
  )
@@ -1017,7 +1016,7 @@ export default class Umap {
1017
1016
  ],
1018
1017
  ['properties.overlay.tms', { handler: 'Switch', label: translate('TMS format') }],
1019
1018
  ]
1020
- const overlay = DomUtil.createFieldset(container, translate('Custom overlay'))
1019
+ const overlay = DOMUtils.createFieldset(container, translate('Custom overlay'))
1021
1020
  const builder = new MutatingForm(this, overlayFields, { umap: this })
1022
1021
  overlay.appendChild(builder.build())
1023
1022
  }
@@ -1026,7 +1025,7 @@ export default class Umap {
1026
1025
  if (!Utils.isObject(this.properties.limitBounds)) {
1027
1026
  this.properties.limitBounds = {}
1028
1027
  }
1029
- const limitBounds = DomUtil.createFieldset(container, translate('Limit bounds'))
1028
+ const limitBounds = DOMUtils.createFieldset(container, translate('Limit bounds'))
1030
1029
  const boundsFields = [
1031
1030
  [
1032
1031
  'properties.limitBounds.south',
@@ -1047,28 +1046,29 @@ export default class Umap {
1047
1046
  ]
1048
1047
  const boundsBuilder = new MutatingForm(this, boundsFields, { umap: this })
1049
1048
  limitBounds.appendChild(boundsBuilder.build())
1050
- const boundsButtons = DomUtil.create('div', 'button-bar half', limitBounds)
1051
- DomUtil.createButton(
1052
- 'button',
1053
- boundsButtons,
1054
- translate('Use current bounds'),
1055
- () => {
1056
- const bounds = this._leafletMap.getBounds()
1057
- const oldLimitBounds = { ...this.properties.limitBounds }
1058
- this.properties.limitBounds.south = LeafletUtil.formatNum(bounds.getSouth())
1059
- this.properties.limitBounds.west = LeafletUtil.formatNum(bounds.getWest())
1060
- this.properties.limitBounds.north = LeafletUtil.formatNum(bounds.getNorth())
1061
- this.properties.limitBounds.east = LeafletUtil.formatNum(bounds.getEast())
1062
- boundsBuilder.fetchAll()
1063
- this.sync.update(
1064
- 'properties.limitBounds',
1065
- this.properties.limitBounds,
1066
- oldLimitBounds
1067
- )
1068
- this._leafletMap.handleLimitBounds()
1069
- }
1070
- )
1071
- DomUtil.createButton('button', boundsButtons, translate('Empty'), () => {
1049
+ const [boundsButtons, { current, empty }] = DOMUtils.loadTemplateWithRefs(`
1050
+ <div class="button-bar half">
1051
+ <button type="button" data-ref="current">${translate('Use current bounds')}</button>
1052
+ <button type="button" data-ref="empty">${translate('Empty')}</button>
1053
+ </div>
1054
+ `)
1055
+ limitBounds.appendChild(boundsButtons)
1056
+ current.addEventListener('click', () => {
1057
+ const bounds = this._leafletMap.getBounds()
1058
+ const oldLimitBounds = { ...this.properties.limitBounds }
1059
+ this.properties.limitBounds.south = bounds.getSouth().toFixed(6)
1060
+ this.properties.limitBounds.west = bounds.getWest().toFixed(6)
1061
+ this.properties.limitBounds.north = bounds.getNorth().toFixed(6)
1062
+ this.properties.limitBounds.east = bounds.getEast().toFixed(6)
1063
+ boundsBuilder.fetchAll()
1064
+ this.sync.update(
1065
+ 'properties.limitBounds',
1066
+ this.properties.limitBounds,
1067
+ oldLimitBounds
1068
+ )
1069
+ this._leafletMap.handleLimitBounds()
1070
+ })
1071
+ empty.addEventListener('click', () => {
1072
1072
  const oldLimitBounds = { ...this.properties.limitBounds }
1073
1073
  this.properties.limitBounds.south = null
1074
1074
  this.properties.limitBounds.west = null
@@ -1085,7 +1085,7 @@ export default class Umap {
1085
1085
  }
1086
1086
 
1087
1087
  _editSlideshow(container) {
1088
- const slideshow = DomUtil.createFieldset(container, translate('Slideshow'))
1088
+ const slideshow = DOMUtils.createFieldset(container, translate('Slideshow'))
1089
1089
  const slideshowFields = [
1090
1090
  [
1091
1091
  'properties.slideshow.active',
@@ -1118,7 +1118,10 @@ export default class Umap {
1118
1118
  }
1119
1119
 
1120
1120
  _editSync(container) {
1121
- const sync = DomUtil.createFieldset(container, translate('Real-time collaboration'))
1121
+ const sync = DOMUtils.createFieldset(
1122
+ container,
1123
+ translate('Real-time collaboration')
1124
+ )
1122
1125
  const builder = new MutatingForm(this, ['properties.syncEnabled'], {
1123
1126
  umap: this,
1124
1127
  })
@@ -1126,7 +1129,7 @@ export default class Umap {
1126
1129
  }
1127
1130
 
1128
1131
  _advancedActions(container) {
1129
- const advancedActions = DomUtil.createFieldset(
1132
+ const advancedActions = DOMUtils.createFieldset(
1130
1133
  container,
1131
1134
  translate('Advanced actions')
1132
1135
  )
@@ -1150,7 +1153,7 @@ export default class Umap {
1150
1153
  </div>
1151
1154
  `
1152
1155
  const [bar, { del, clear, empty, clone, download }] =
1153
- Utils.loadTemplateWithRefs(tpl)
1156
+ DOMUtils.loadTemplateWithRefs(tpl)
1154
1157
  advancedActions.appendChild(bar)
1155
1158
  if (this.permissions.isOwner()) {
1156
1159
  del.hidden = false
@@ -1167,12 +1170,11 @@ export default class Umap {
1167
1170
  edit() {
1168
1171
  if (!this.editEnabled) return
1169
1172
  if (this.properties.editMode !== 'advanced') return
1170
- const container = DomUtil.create('div')
1171
- DomUtil.createTitle(
1172
- container,
1173
- translate('Map advanced properties'),
1174
- 'icon-settings'
1175
- )
1173
+ const container = DOMUtils.loadTemplate(`
1174
+ <div>
1175
+ <h3><i class="icon icon-16 icon-settings"></i>${translate('Map advanced properties')}</h3>
1176
+ </div>
1177
+ `)
1176
1178
  this._editControls(container)
1177
1179
  this._editShapeProperties(container)
1178
1180
  this._editDefaultKeys(container)
@@ -1224,7 +1226,7 @@ export default class Umap {
1224
1226
  if (error) {
1225
1227
  return
1226
1228
  }
1227
- // TOOD: map.save may not always be the first call during save process
1229
+ // TODO: map.save may not always be the first call during save process
1228
1230
  // since SAVEMANAGER refactor
1229
1231
  if (data.login_required) {
1230
1232
  this.askForLogin().then(() => this.saveAll())
@@ -1457,7 +1459,7 @@ export default class Umap {
1457
1459
  }
1458
1460
 
1459
1461
  // This method does a targeted update of the UI,
1460
- // it whould be merged with `render`` method and the
1462
+ // it would be merged with `render`` method and the
1461
1463
  // SCHEMA at some point
1462
1464
  propagate(fields = []) {
1463
1465
  const impacts = {
@@ -1604,9 +1606,11 @@ export default class Umap {
1604
1606
  else if (finalIndex > initialIndex) movedLayer.insertBefore(targetLayer)
1605
1607
  else movedLayer.insertAfter(targetLayer)
1606
1608
  this.sync.startBatch()
1607
- this.datalayers.reverse().map((datalayer) => {
1609
+ this.datalayers.reverse().map(async (datalayer) => {
1608
1610
  const rank = datalayer.getDOMOrder()
1609
1611
  if (rank >= minIndex && rank <= maxIndex) {
1612
+ // TODO allow to save only metadata instead of force loading data
1613
+ if (!datalayer.isLoaded()) await datalayer.fetchData()
1610
1614
  const oldRank = datalayer.rank
1611
1615
  datalayer.rank = rank
1612
1616
  datalayer.sync.update('options.rank', rank, oldRank)
@@ -1618,14 +1622,13 @@ export default class Umap {
1618
1622
  }
1619
1623
  const orderable = new Orderable(ul, onReorder)
1620
1624
 
1621
- const bar = DomUtil.create('div', 'button-bar', container)
1622
- DomUtil.createButton(
1623
- 'show-on-edit block add-datalayer button',
1624
- bar,
1625
- translate('Add a layer'),
1626
- this.newDataLayer,
1627
- this
1628
- )
1625
+ const [bar, { button }] = DOMUtils.loadTemplateWithRefs(`
1626
+ <div class="button-bar">
1627
+ <button type="button" class="show-on-edit block add-datalayer" data-ref="button">${translate('Add a layer')}</button>
1628
+ </div>
1629
+ `)
1630
+ button.addEventListener('click', () => this.newDataLayer())
1631
+ container.appendChild(bar)
1629
1632
 
1630
1633
  this.editPanel.open({ content: container, highlight: 'layers' })
1631
1634
  }
@@ -1733,6 +1736,7 @@ export default class Umap {
1733
1736
  const fields = Object.keys(importedData.properties).map(
1734
1737
  (field) => `properties.${field}`
1735
1738
  )
1739
+ this.fields.pull()
1736
1740
  this.filters.load()
1737
1741
  this.render(fields)
1738
1742
  this._leafletMap._setDefaultCenter()
@@ -1785,16 +1789,12 @@ export default class Umap {
1785
1789
  await this.server.post(sendLink, {}, formData)
1786
1790
  }
1787
1791
 
1788
- getLayersBounds() {
1789
- const bounds = new latLngBounds()
1790
- this.datalayers.browsable().map((d) => {
1791
- if (d.isVisible()) bounds.extend(d.layer.getBounds())
1792
- })
1793
- return bounds
1794
- }
1795
-
1796
1792
  fitDataBounds() {
1797
- const bounds = this.getLayersBounds()
1793
+ const layers = this.datalayers
1794
+ .browsable()
1795
+ .filter((d) => d.isVisible())
1796
+ .map((d) => d.layer)
1797
+ const bounds = this._leafletMap.getLayersBounds(layers)
1798
1798
  if (!this.hasData() || !bounds.isValid()) return false
1799
1799
  this._leafletMap.fitBounds(bounds)
1800
1800
  }
@@ -40,7 +40,7 @@ function _getPropertyName(field) {
40
40
  * Return an array of unique impacts.
41
41
  *
42
42
  * @param {fields} list[fields]
43
- * @param object schema object. If ommited, global U.SCHEMA will be used.
43
+ * @param object schema object. If omitted, global U.SCHEMA will be used.
44
44
  * @returns Array[string]
45
45
  */
46
46
  export function getImpactsFromSchema(fields, schema) {
@@ -177,15 +177,15 @@ export function toHTML(r, options) {
177
177
  // iframe
178
178
  r = r.replace(
179
179
  /{{{(https?[^|{]*)}}}/g,
180
- '<div><iframe frameborder="0" src="$1" width="100%" height="300px"></iframe></div>'
180
+ '<div><iframe allowfullscreen src="$1" style="width: 100%; height: 300px; border: 0;"></iframe></div>'
181
181
  )
182
182
  r = r.replace(
183
183
  /{{{(https?[^|{]*)\|(\d*)(px)?}}}/g,
184
- '<div><iframe frameborder="0" src="$1" width="100%" height="$2px"></iframe></div>'
184
+ '<div><iframe allowfullscreen src="$1" style="width: 100%; height: $2px; border: 0;"></iframe></div>'
185
185
  )
186
186
  r = r.replace(
187
187
  /{{{(https?[^|{]*)\|(\d*)(px)?\*(\d*)(px)?}}}/g,
188
- '<div><iframe frameborder="0" src="$1" width="$4px" height="$2px"></iframe></div>'
188
+ '<div><iframe allowfullscreen src="$1" style="width: $4px; height: $2px; border: 0;"></iframe></div>'
189
189
  )
190
190
 
191
191
  // images
@@ -681,3 +681,12 @@ export const COLORS = [
681
681
  'Ivory',
682
682
  'White',
683
683
  ]
684
+
685
+ export const LatLngIsValid = (latlng) => {
686
+ return (
687
+ Number.isFinite(latlng.lat) &&
688
+ Math.abs(latlng.lat) <= 90 &&
689
+ Number.isFinite(latlng.lng) &&
690
+ Math.abs(latlng.lng) <= 180
691
+ )
692
+ }
@@ -45,14 +45,12 @@ U.TileLayerControl = L.Control.IconLayers.extend({
45
45
  const lastRow = this._container.querySelector(
46
46
  '.leaflet-iconLayers-layersRow:last-child'
47
47
  )
48
- const button = L.DomUtil.element({
49
- tagName: 'button',
50
- className:
51
- 'leaflet-iconLayers-layerCell leaflet-iconLayers-layerCell-plus button',
52
- textContent: '+',
53
- parent: lastRow,
54
- })
55
- L.DomEvent.on(button, 'click', () =>
48
+ const button = document.createElement('button')
49
+ button.className =
50
+ 'leaflet-iconLayers-layerCell leaflet-iconLayers-layerCell-plus button'
51
+ button.textContent = '+'
52
+ lastRow.appendChild(button)
53
+ button.addEventListener('click', () =>
56
54
  this.map._controls.tilelayersChooser.openSwitcher()
57
55
  )
58
56
  },
@@ -130,7 +128,7 @@ U.Search = L.PhotonSearch.extend({
130
128
  this.hide()
131
129
  const { lat, lng } = pattern.exec(this.input.value).groups
132
130
  const latlng = L.latLng(lat, lng)
133
- if (latlng.isValid()) {
131
+ if (U.Utils.LatLngIsValid(latlng)) {
134
132
  this.reverse.doReverse(latlng)
135
133
  } else {
136
134
  U.Alert.error(L._('Invalid latitude or longitude'))
@@ -175,8 +173,8 @@ U.Search = L.PhotonSearch.extend({
175
173
  if (!osm_type || !osm_id) return
176
174
  const importer = this.map._umap.importer
177
175
  importer.build()
178
- importer.format = 'osm'
179
- importer.url = `https://www.openstreetmap.org/api/0.6/${osm_type}/${osm_id}/full`
176
+ importer.format = 'geojson'
177
+ importer.raw = await this.getOSMObject(osm_type, osm_id)
180
178
  importer.submit()
181
179
  })
182
180
  el.appendChild(tools)
@@ -197,6 +195,18 @@ U.Search = L.PhotonSearch.extend({
197
195
  })
198
196
  },
199
197
 
198
+ async getOSMObject(osm_type, osm_id) {
199
+ const url = `https://www.openstreetmap.org/api/0.6/${osm_type}/${osm_id}/full`
200
+ const response = await this.map._umap.request.get(url)
201
+ if (response?.ok) {
202
+ const data = await this.map._umap.formatter.fromOSM(await response.text())
203
+ data.features = data.features.filter(
204
+ (feature) => feature.properties.id === `${osm_type}/${osm_id}`
205
+ )
206
+ return JSON.stringify(data)
207
+ }
208
+ },
209
+
200
210
  setChoice: function (choice) {
201
211
  choice = choice || this.RESULTS[this.CURRENT]
202
212
  if (choice) {
@@ -230,7 +240,8 @@ L.Control.MiniMap.include({
230
240
 
231
241
  L.Control.Loading.include({
232
242
  onAdd: function (map) {
233
- this._container = L.DomUtil.create('div', 'umap-loader', map._controlContainer)
243
+ this._container = document.createElement('div')
244
+ this._container.classList.add('umap-loader')
234
245
  map.on('baselayerchange', this._layerAdd, this)
235
246
  this._addMapListeners(map)
236
247
  this._map = map
@@ -252,9 +263,10 @@ U.Editable = L.Editable.extend({
252
263
  this.on('editable:drawing:click editable:drawing:move', this.drawingTooltip)
253
264
  // Layer for items added by users
254
265
  this.on('editable:drawing:cancel', (event) => {
255
- if (event.layer instanceof U.LeafletMarker) event.layer.feature.del()
266
+ this.resetButtons()
256
267
  })
257
268
  this.on('editable:drawing:commit', function (event) {
269
+ this.resetButtons()
258
270
  if (this._umap.editedFeature !== event.layer) {
259
271
  const promise = event.layer.feature.edit(event)
260
272
  if (event.layer.feature.isRoute?.()) {
@@ -278,6 +290,13 @@ U.Editable = L.Editable.extend({
278
290
  this.on('editable:vertex:rawclick', this.onVertexRawClick)
279
291
  },
280
292
 
293
+ resetButtons: () => {
294
+ const buttons = document.querySelectorAll('.umap-edit-bar .drawing-tool')
295
+ for (const button of buttons) {
296
+ button.classList.remove('on')
297
+ }
298
+ },
299
+
281
300
  startRoute: function (latlng) {
282
301
  const feature = this.createLineString()
283
302
  feature.askForRouteSettings().then(async () => {
@@ -402,7 +421,7 @@ U.Editable = L.Editable.extend({
402
421
  // (eg. line has only one drawn point)
403
422
  // So let's check if the layer has no more shape
404
423
  event.layer.feature.pullGeometry(false)
405
- if (!event.layer.feature.hasGeom()) {
424
+ if (!event.layer.feature.hasGeom() || event.layer instanceof U.LeafletMarker) {
406
425
  event.layer.feature.del()
407
426
  } else {
408
427
  event.layer.feature.onCommit()
@@ -70,7 +70,7 @@ const locale = {
70
70
  "color": "ከለር",
71
71
  "Comma separated list of numbers, including min and max values.": "Comma separated list of numbers, including min and max values.",
72
72
  "Comma separated list of properties to use for sorting features. To reverse the sort, put a minus sign (-) before. Eg. mykey,-otherkey.": "Comma separated list of properties to use for sorting features. To reverse the sort, put a minus sign (-) before. Eg. mykey,-otherkey.",
73
- "Comma, tab or semi-colon separated values. SRS WGS84 is implied. Only Point geometries are imported. The import will look at the column headers for any mention of «lat» and «lon» at the begining of the header, case insensitive. All other column are imported as properties.": "በኮማ፣ታብ፣ግማሽኮለን የተከፋፈሉ ውጤቶች። SRSWG84 ተመላክቷል። የነጥብ ጂኦሜትሪዎች ብቻ መጥተዋል። የማምጣት ሂደቱ የኮለምን ሄደሮችን በማሰስ «ላቲትዩድ» እና «ሎንጊትዩድ» የሚሉትን ቃላት መኖር ከመጀመሪያው በመነሳት ያጣራል። ሁሉም ኮለምኖች እንደባህርይ መጥተዋል።",
73
+ "Comma, tab or semi-colon separated values. SRS WGS84 is implied. Only Point geometries are imported. The import will look at the column headers for any mention of «lat» and «lon» at the beginning of the header, case insensitive. All other column are imported as properties.": "Comma, tab or semi-colon separated values. SRS WGS84 is implied. Only Point geometries are imported. The import will look at the column headers for any mention of «lat» and «lon» at the beginning of the header, case insensitive. All other column are imported as properties.",
74
74
  "Congratulations, your map has been created!": "Congratulations, your map has been created!",
75
75
  "Continue line": "መስመሩን ቀጥል",
76
76
  "Coordinates": "ኮርዲኔቶች",
@@ -99,7 +99,6 @@ const locale = {
99
99
  "Delete this vertex (Alt+Click)": "Delete this vertex (Alt+Click)",
100
100
  "Delete": "ሰርዝ",
101
101
  "description": "መገለጫ",
102
- "Direct link": "Direct link",
103
102
  "Directions from here": "ከዚህ የሚነሱ አቅጣጫዎች",
104
103
  "Display label": "Display label",
105
104
  "Display measure": "Display measure",
@@ -135,7 +134,6 @@ const locale = {
135
134
  "Edit this feature": "ይህንን ፊቸር አርም",
136
135
  "Edit": "አርም",
137
136
  "Embed and link options": "Embed and link options",
138
- "Embed the map": "ካርታውን አካትት",
139
137
  "Emoji & Character": "Emoji & Character",
140
138
  "Empty": "ባዶ",
141
139
  "Equidistant": "Equidistant",
@@ -159,7 +157,6 @@ const locale = {
159
157
  "Go to \"{coords}\"": "Go to \"{coords}\"",
160
158
  "Go to the homepage": "Go to the homepage",
161
159
  "Go to «{feature}»": "ወደ «{feature}» ተመለስ",
162
- "Heatmap intensity property": "የሙቀት ካርታ ኢንቴንሲቲ ባህርይ",
163
160
  "Heatmap radius": "የሙቀት ካርታ ራዲየስ",
164
161
  "Heatmap": "የሙቀት ካርታ",
165
162
  "height": "ቁመት",
@@ -255,7 +252,6 @@ const locale = {
255
252
  "Open share & download panel": "Open share & download panel",
256
253
  "Open this map extent in a map editor to provide more accurate data to OpenStreetMap": "ለOpernStreetMap ይበልጥ ትክክል ይሆነ መረጃ ለመስጠ የካርታውን ኤክስቴንት በካርታ ማረሚያ ክፈት",
257
254
  "OpenStreetMap": "OpenStreetMap",
258
- "Optional intensity property for heatmap": "ለሙቀት ካርታው ባህርይ አማራጭ ኢንቴንሲቲ",
259
255
  "Optional. Same as color if not set.": "አማራጭ፣ ካልተመረጠለት እንደቀለሙ የሚሆን",
260
256
  "Optional.": "Optional.",
261
257
  "Override clustering radius (default 80)": "የራዲየስ ክለስተሪንግ አልፈህ ሂድ (ዲፎልት 80)",
@@ -297,7 +293,6 @@ const locale = {
297
293
  "settings": "settings",
298
294
  "Shape properties": "Shape properties",
299
295
  "Share and download": "Share and download",
300
- "Share this link to open a customized map view": "Share this link to open a customized map view",
301
296
  "Short credits": "አጭር ክሬዲት",
302
297
  "Short link": "Short link",
303
298
  "Show this layer in the caption": "Show this layer in the caption",
@@ -631,7 +626,6 @@ const locale = {
631
626
  "Are you sure you want to delete this field on all the data?": "Are you sure you want to delete this field on all the data?",
632
627
  "Anonymous map": "Anonymous map",
633
628
  "Edit filter for this field": "Edit filter for this field",
634
- "Fields, filters and keys": "Fields, filters and keys",
635
629
  "Hey, you created a map without an account!": "Hey, you created a map without an account!",
636
630
  "This map is anonymous, do you want to attach it to your account?": "This map is anonymous, do you want to attach it to your account?",
637
631
  "The map has been upgraded to latest version, please save it.": "The map has been upgraded to latest version, please save it.",
@@ -641,7 +635,24 @@ const locale = {
641
635
  "Wikipedia contributors": "Wikipedia contributors",
642
636
  "See on Wikipedia": "See on Wikipedia",
643
637
  "Anonymous map: update who can see and edit it": "Anonymous map: update who can see and edit it",
644
- "Login": "Login"
638
+ "Login": "Login",
639
+ "Manage filters": "Manage filters",
640
+ "Map (all layers)": "Map (all layers)",
641
+ "Add a filter for this field": "Add a filter for this field",
642
+ "Short text": "Short text",
643
+ "Text": "Text",
644
+ "Number": "Number",
645
+ "Date": "Date",
646
+ "Date and time": "Date and time",
647
+ "List of values": "List of values",
648
+ "Yes / No": "Yes / No",
649
+ "Select field to compute intensity": "Select field to compute intensity",
650
+ "Optional intensity field to compute heatmap": "Optional intensity field to compute heatmap",
651
+ "All layers": "All layers",
652
+ "Comma separated list of values": "Comma separated list of values",
653
+ "Share": "Share",
654
+ "Customized link": "Customized link",
655
+ "Iframe": "Iframe"
645
656
  }
646
657
  L.registerLocale("am_ET", locale)
647
658
  L.setLocale("am_ET")