umap-project 3.4.0b3__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 (185) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/da/LC_MESSAGES/django.mo +0 -0
  3. umap/locale/da/LC_MESSAGES/django.po +18 -14
  4. umap/locale/en/LC_MESSAGES/django.po +5 -1
  5. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/es/LC_MESSAGES/django.po +20 -16
  7. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/fr/LC_MESSAGES/django.po +18 -14
  9. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/pl/LC_MESSAGES/django.po +72 -71
  11. umap/static/umap/content.css +0 -3
  12. umap/static/umap/css/bar.css +9 -6
  13. umap/static/umap/css/form.css +25 -9
  14. umap/static/umap/css/popup.css +1 -0
  15. umap/static/umap/js/components/copiable.js +47 -0
  16. umap/static/umap/js/modules/autocomplete.js +31 -58
  17. umap/static/umap/js/modules/browser.js +4 -4
  18. umap/static/umap/js/modules/data/features.js +32 -35
  19. umap/static/umap/js/modules/data/fields.js +189 -23
  20. umap/static/umap/js/modules/data/layer.js +72 -87
  21. umap/static/umap/js/modules/domutils.js +21 -1
  22. umap/static/umap/js/modules/filters.js +13 -40
  23. umap/static/umap/js/modules/form/fields.js +4 -4
  24. umap/static/umap/js/modules/formatter.js +9 -1
  25. umap/static/umap/js/modules/help.js +12 -13
  26. umap/static/umap/js/modules/importer.js +17 -26
  27. umap/static/umap/js/modules/importers/banfr.js +0 -1
  28. umap/static/umap/js/modules/importers/cadastrefr.js +19 -19
  29. umap/static/umap/js/modules/importers/communesfr.js +7 -8
  30. umap/static/umap/js/modules/importers/datasets.js +14 -14
  31. umap/static/umap/js/modules/importers/geodatamine.js +20 -22
  32. umap/static/umap/js/modules/importers/opendata.js +10 -0
  33. umap/static/umap/js/modules/importers/overpass.js +19 -18
  34. umap/static/umap/js/modules/managers.js +1 -1
  35. umap/static/umap/js/modules/permissions.js +5 -3
  36. umap/static/umap/js/modules/rendering/controls.js +2 -2
  37. umap/static/umap/js/modules/rendering/icon.js +5 -9
  38. umap/static/umap/js/modules/rendering/layers/base.js +1 -1
  39. umap/static/umap/js/modules/rendering/layers/classified.js +15 -10
  40. umap/static/umap/js/modules/rendering/layers/heat.js +1 -0
  41. umap/static/umap/js/modules/rendering/map.js +22 -22
  42. umap/static/umap/js/modules/rendering/popup.js +6 -3
  43. umap/static/umap/js/modules/rendering/template.js +28 -34
  44. umap/static/umap/js/modules/rendering/ui.js +1 -2
  45. umap/static/umap/js/modules/rules.js +34 -41
  46. umap/static/umap/js/modules/schema.js +0 -7
  47. umap/static/umap/js/modules/share.js +36 -69
  48. umap/static/umap/js/modules/slideshow.js +3 -3
  49. umap/static/umap/js/modules/tableeditor.js +0 -1
  50. umap/static/umap/js/modules/ui/bar.js +51 -32
  51. umap/static/umap/js/modules/ui/panel.js +26 -21
  52. umap/static/umap/js/modules/ui/tooltip.js +1 -1
  53. umap/static/umap/js/modules/umap.js +75 -80
  54. umap/static/umap/js/modules/utils.js +12 -3
  55. umap/static/umap/js/umap.controls.js +33 -14
  56. umap/static/umap/locale/am_ET.js +6 -4
  57. umap/static/umap/locale/am_ET.json +6 -4
  58. umap/static/umap/locale/ar.js +6 -4
  59. umap/static/umap/locale/ar.json +6 -4
  60. umap/static/umap/locale/ast.js +6 -4
  61. umap/static/umap/locale/ast.json +6 -4
  62. umap/static/umap/locale/bg.js +6 -4
  63. umap/static/umap/locale/bg.json +6 -4
  64. umap/static/umap/locale/br.js +19 -8
  65. umap/static/umap/locale/br.json +19 -8
  66. umap/static/umap/locale/ca.js +6 -4
  67. umap/static/umap/locale/ca.json +6 -4
  68. umap/static/umap/locale/cs_CZ.js +7 -5
  69. umap/static/umap/locale/cs_CZ.json +7 -5
  70. umap/static/umap/locale/da.js +8 -6
  71. umap/static/umap/locale/da.json +8 -6
  72. umap/static/umap/locale/de.js +38 -36
  73. umap/static/umap/locale/de.json +38 -36
  74. umap/static/umap/locale/el.js +7 -5
  75. umap/static/umap/locale/el.json +7 -5
  76. umap/static/umap/locale/en.js +7 -5
  77. umap/static/umap/locale/en.json +7 -5
  78. umap/static/umap/locale/en_US.json +6 -4
  79. umap/static/umap/locale/es.js +19 -17
  80. umap/static/umap/locale/es.json +19 -17
  81. umap/static/umap/locale/et.js +7 -5
  82. umap/static/umap/locale/et.json +7 -5
  83. umap/static/umap/locale/eu.js +23 -21
  84. umap/static/umap/locale/eu.json +23 -21
  85. umap/static/umap/locale/fa_IR.js +7 -5
  86. umap/static/umap/locale/fa_IR.json +7 -5
  87. umap/static/umap/locale/fi.js +6 -4
  88. umap/static/umap/locale/fi.json +6 -4
  89. umap/static/umap/locale/fr.js +8 -6
  90. umap/static/umap/locale/fr.json +8 -6
  91. umap/static/umap/locale/gl.js +147 -145
  92. umap/static/umap/locale/gl.json +147 -145
  93. umap/static/umap/locale/he.js +6 -4
  94. umap/static/umap/locale/he.json +6 -4
  95. umap/static/umap/locale/hr.js +6 -4
  96. umap/static/umap/locale/hr.json +6 -4
  97. umap/static/umap/locale/hu.js +7 -5
  98. umap/static/umap/locale/hu.json +7 -5
  99. umap/static/umap/locale/id.js +6 -4
  100. umap/static/umap/locale/id.json +6 -4
  101. umap/static/umap/locale/is.js +7 -5
  102. umap/static/umap/locale/is.json +7 -5
  103. umap/static/umap/locale/it.js +7 -5
  104. umap/static/umap/locale/it.json +7 -5
  105. umap/static/umap/locale/ja.js +6 -4
  106. umap/static/umap/locale/ja.json +6 -4
  107. umap/static/umap/locale/ko.js +6 -4
  108. umap/static/umap/locale/ko.json +6 -4
  109. umap/static/umap/locale/lt.js +6 -4
  110. umap/static/umap/locale/lt.json +6 -4
  111. umap/static/umap/locale/ms.js +7 -5
  112. umap/static/umap/locale/ms.json +7 -5
  113. umap/static/umap/locale/nl.js +7 -5
  114. umap/static/umap/locale/nl.json +7 -5
  115. umap/static/umap/locale/no.js +6 -4
  116. umap/static/umap/locale/no.json +6 -4
  117. umap/static/umap/locale/pl.js +53 -51
  118. umap/static/umap/locale/pl.json +53 -51
  119. umap/static/umap/locale/pl_PL.json +6 -4
  120. umap/static/umap/locale/pt.js +7 -5
  121. umap/static/umap/locale/pt.json +7 -5
  122. umap/static/umap/locale/pt_BR.js +6 -4
  123. umap/static/umap/locale/pt_BR.json +6 -4
  124. umap/static/umap/locale/pt_PT.js +6 -4
  125. umap/static/umap/locale/pt_PT.json +6 -4
  126. umap/static/umap/locale/ro.js +6 -4
  127. umap/static/umap/locale/ro.json +6 -4
  128. umap/static/umap/locale/ru.js +6 -4
  129. umap/static/umap/locale/ru.json +6 -4
  130. umap/static/umap/locale/sk_SK.js +6 -4
  131. umap/static/umap/locale/sk_SK.json +6 -4
  132. umap/static/umap/locale/sl.js +6 -4
  133. umap/static/umap/locale/sl.json +6 -4
  134. umap/static/umap/locale/sr.js +6 -4
  135. umap/static/umap/locale/sr.json +6 -4
  136. umap/static/umap/locale/sv.js +6 -4
  137. umap/static/umap/locale/sv.json +6 -4
  138. umap/static/umap/locale/th_TH.js +6 -4
  139. umap/static/umap/locale/th_TH.json +6 -4
  140. umap/static/umap/locale/tr.js +6 -4
  141. umap/static/umap/locale/tr.json +6 -4
  142. umap/static/umap/locale/uk_UA.js +6 -4
  143. umap/static/umap/locale/uk_UA.json +6 -4
  144. umap/static/umap/locale/vi.js +6 -4
  145. umap/static/umap/locale/vi.json +6 -4
  146. umap/static/umap/locale/vi_VN.json +6 -4
  147. umap/static/umap/locale/zh.js +6 -4
  148. umap/static/umap/locale/zh.json +6 -4
  149. umap/static/umap/locale/zh_CN.json +6 -4
  150. umap/static/umap/locale/zh_TW.Big5.json +6 -4
  151. umap/static/umap/locale/zh_TW.js +20 -18
  152. umap/static/umap/locale/zh_TW.json +20 -18
  153. umap/static/umap/map.css +5 -4
  154. umap/static/umap/unittests/utils.js +7 -7
  155. umap/templates/umap/content_footer.html +1 -0
  156. umap/templates/umap/css.html +0 -2
  157. umap/templates/umap/js.html +1 -3
  158. umap/tests/integration/conftest.py +3 -2
  159. umap/tests/integration/test_anonymous_owned_map.py +1 -1
  160. umap/tests/integration/test_conditional_rules.py +106 -51
  161. umap/tests/integration/test_draw_polygon.py +4 -0
  162. umap/tests/integration/test_draw_polyline.py +11 -0
  163. umap/tests/integration/test_edit_datalayer.py +1 -1
  164. umap/tests/integration/test_fields.py +19 -0
  165. umap/tests/integration/test_iframe.py +1 -1
  166. umap/tests/integration/test_import.py +23 -0
  167. umap/tests/integration/test_map.py +2 -2
  168. umap/tests/integration/test_owned_map.py +2 -2
  169. umap/tests/integration/test_popup.py +31 -0
  170. umap/tests/integration/test_remote_data.py +4 -4
  171. umap/tests/integration/test_search.py +41 -0
  172. umap/tests/integration/test_share.py +2 -2
  173. umap/tests/integration/test_team.py +1 -1
  174. umap/tests/integration/test_websocket_sync.py +6 -1
  175. umap/tests/test_utils.py +4 -1
  176. umap/utils.py +1 -0
  177. {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/METADATA +15 -15
  178. {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/RECORD +181 -183
  179. umap/static/umap/js/umap.core.js +0 -93
  180. umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.css +0 -46
  181. umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.js +0 -240
  182. umap/static/umap/vendors/editinosm/edit-in-osm.png +0 -0
  183. {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/WHEEL +0 -0
  184. {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/entry_points.txt +0 -0
  185. {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,9 +1,9 @@
1
1
  // FIXME: this module should not depend on Leaflet
2
2
  import {
3
3
  DomEvent,
4
- DomUtil,
5
4
  GeoJSON,
6
5
  stamp,
6
+ SVG,
7
7
  } from '../../../vendors/leaflet/leaflet-src.esm.js'
8
8
  import {
9
9
  uMapAlert as Alert,
@@ -19,6 +19,7 @@ import { Heat } from '../rendering/layers/heat.js'
19
19
  import * as Schema from '../schema.js'
20
20
  import TableEditor from '../tableeditor.js'
21
21
  import * as Utils from '../utils.js'
22
+ import * as DOMUtils from '../domutils.js'
22
23
  import { LineString, Point, Polygon } from './features.js'
23
24
  import Rules from '../rules.js'
24
25
  import { FeatureManager } from '../managers.js'
@@ -50,7 +51,7 @@ export class DataLayer {
50
51
  this.parentPane = this._leafletMap.getPane('overlayPane')
51
52
  this.pane = this._leafletMap.createPane(`datalayer${stamp(this)}`, this.parentPane)
52
53
  // FIXME: should be on layer
53
- this.renderer = L.svg({ pane: this.pane })
54
+ this.renderer = new SVG({ pane: this.pane })
54
55
  this.defaultProperties = {
55
56
  displayOnLoad: true,
56
57
  inCaption: true,
@@ -84,17 +85,15 @@ export class DataLayer {
84
85
  }
85
86
  this.connectToMap()
86
87
  this.permissions = new DataLayerPermissions(this._umap, this)
87
- this.rules = new Rules(umap, this)
88
88
 
89
89
  this._needsFetch = this.createdOnServer || this.isRemoteLayer()
90
+ this.fields = new Fields(this, this._umap.dialog)
91
+ this.filters = new Filters(this, this._umap)
92
+ this.rules = new Rules(umap, this)
93
+
90
94
  if (!this.createdOnServer) {
91
95
  if (this.showAtLoad()) this.show()
92
96
  }
93
- if (!this._needsFetch && !this._umap.fields.size) {
94
- this.properties.fields = getDefaultFields()
95
- }
96
- this.fields = new Fields(this, this._umap.dialog)
97
- this.filters = new Filters(this, this._umap)
98
97
 
99
98
  // Only layers that are displayed on load must be hidden/shown
100
99
  // Automatically, others will be shown manually, and thus will
@@ -146,12 +145,6 @@ export class DataLayer {
146
145
  this.properties.rank = value
147
146
  }
148
147
 
149
- get fieldKeys() {
150
- // Needed to get a similar API from layer and uMap, but
151
- // uMap would return concat of all datalayers fields
152
- return Array.from(this.fields.keys())
153
- }
154
-
155
148
  get sortKey() {
156
149
  return this.getProperty('sortKey') || U.DEFAULT_LABEL_KEY
157
150
  }
@@ -230,27 +223,28 @@ export class DataLayer {
230
223
  }
231
224
 
232
225
  showAtLoad() {
233
- return this.autoLoaded && this.showAtZoom()
226
+ return this.autoVisibility && this.showAtZoom()
234
227
  }
235
228
 
236
- get autoLoaded() {
237
- if (this._autoLoaded === undefined) {
229
+ get autoVisibility() {
230
+ if (this._autoVisibility === undefined) {
238
231
  if (this._umap.datalayersFromQueryString) {
239
232
  const datalayerIds = this._umap.datalayersFromQueryString
240
- this._autoLoaded = datalayerIds.includes(this.id.toString())
233
+ this._autoVisibility = datalayerIds.includes(this.id.toString())
241
234
  if (this.properties.old_id) {
242
- this._autoLoaded =
243
- this._autoLoaded || datalayerIds.includes(this.properties.old_id.toString())
235
+ this._autoVisibility =
236
+ this._autoVisibility ||
237
+ datalayerIds.includes(this.properties.old_id.toString())
244
238
  }
245
239
  } else {
246
- this._autoLoaded = this.properties.displayOnLoad
240
+ this._autoVisibility = this.properties.displayOnLoad
247
241
  }
248
242
  }
249
- return this._autoLoaded
243
+ return this._autoVisibility
250
244
  }
251
245
 
252
- set autoLoaded(value) {
253
- this._autoLoaded = value
246
+ set autoVisibility(value) {
247
+ this._autoVisibility = value
254
248
  }
255
249
 
256
250
  insertBefore(other) {
@@ -451,6 +445,10 @@ export class DataLayer {
451
445
  this._umap.featuresIndex[feature.getSlug()] = feature
452
446
  // TODO: quid for remote data ?
453
447
  this.inferFields(feature)
448
+ if (!this.fields.size && !this._umap.fields.size) {
449
+ this.properties.fields = getDefaultFields()
450
+ this.fields.pull()
451
+ }
454
452
  try {
455
453
  this.showFeature(feature)
456
454
  } catch (error) {
@@ -527,12 +525,10 @@ export class DataLayer {
527
525
  this.features.forEach((feature) => callback(feature))
528
526
  }
529
527
 
530
- sortedValues(property) {
531
- return this.features
532
- .all()
533
- .map((feature) => feature.properties[property])
534
- .filter((val, idx, arr) => arr.indexOf(val) === idx)
535
- .sort(Utils.naturalSort)
528
+ sortedValues(key) {
529
+ const field = this.fields.get(key) || this._umap.fields.get(key)
530
+ if (!field) return []
531
+ return field.values(this.features.all()).sort(Utils.naturalSort)
536
532
  }
537
533
 
538
534
  addData(geojson, sync) {
@@ -777,7 +773,11 @@ export class DataLayer {
777
773
  },
778
774
  ],
779
775
  ]
780
- DomUtil.createTitle(container, translate('Layer properties'), 'icon-layers')
776
+ container.appendChild(
777
+ DOMUtils.loadTemplate(`
778
+ <h3><i class="icon icon-16 icon-layers"></i>${translate('Layer properties')}</h3>
779
+ `)
780
+ )
781
781
  const builder = new MutatingForm(this, metadataFields)
782
782
  builder.on('set', ({ detail }) => {
783
783
  this._umap.onDataLayersChanged()
@@ -823,7 +823,7 @@ export class DataLayer {
823
823
  const builder = new MutatingForm(this, fields, {
824
824
  id: 'datalayer-advanced-properties',
825
825
  })
826
- const shapeFieldset = DomUtil.createFieldset(
826
+ const shapeFieldset = DOMUtils.createFieldset(
827
827
  container,
828
828
  translate('Shape properties')
829
829
  )
@@ -848,7 +848,7 @@ export class DataLayer {
848
848
  this.reindex()
849
849
  }
850
850
  })
851
- const advancedFieldset = DomUtil.createFieldset(
851
+ const advancedFieldset = DOMUtils.createFieldset(
852
852
  container,
853
853
  translate('Advanced properties')
854
854
  )
@@ -867,7 +867,7 @@ export class DataLayer {
867
867
  'properties.interactive',
868
868
  ]
869
869
  const builder = new MutatingForm(this, fields)
870
- const popupFieldset = DomUtil.createFieldset(
870
+ const popupFieldset = DOMUtils.createFieldset(
871
871
  container,
872
872
  translate('Interaction options')
873
873
  )
@@ -885,7 +885,7 @@ export class DataLayer {
885
885
  'properties.textPathPosition',
886
886
  ]
887
887
  const builder = new MutatingForm(this, fields)
888
- const fieldset = DomUtil.createFieldset(container, translate('Line decoration'))
888
+ const fieldset = DOMUtils.createFieldset(container, translate('Line decoration'))
889
889
  fieldset.appendChild(builder.build())
890
890
  }
891
891
 
@@ -935,23 +935,21 @@ export class DataLayer {
935
935
  fields.push('properties.remoteData.ttl')
936
936
  }
937
937
 
938
- const remoteDataContainer = DomUtil.createFieldset(
938
+ const remoteDataContainer = DOMUtils.createFieldset(
939
939
  container,
940
940
  translate('Remote data')
941
941
  )
942
942
  const builder = new MutatingForm(this, fields)
943
943
  remoteDataContainer.appendChild(builder.build())
944
- DomUtil.createButton(
945
- 'button umap-verify',
946
- remoteDataContainer,
947
- translate('Verify remote URL'),
948
- () => this.fetchRemoteData(true),
949
- this
950
- )
944
+ const button = DOMUtils.loadTemplate(`
945
+ <button class="umap-verify" type="button">${translate('Verify remote URL')}</button>
946
+ `)
947
+ button.addEventListener('click', () => this.fetchRemoteData(true))
948
+ remoteDataContainer.appendChild(button)
951
949
  }
952
950
 
953
951
  _buildAdvancedActions(container) {
954
- const advancedActions = DomUtil.createFieldset(
952
+ const advancedActions = DOMUtils.createFieldset(
955
953
  container,
956
954
  translate('Advanced actions')
957
955
  )
@@ -991,7 +989,7 @@ export class DataLayer {
991
989
  if (!this._umap.editEnabled) {
992
990
  return
993
991
  }
994
- const container = DomUtil.create('div', 'umap-layer-properties-container')
992
+ const container = document.createElement('div')
995
993
  this._editMetadata(container)
996
994
  this._editLayerProperties(container)
997
995
  this._editShapeProperties(container)
@@ -1008,15 +1006,13 @@ export class DataLayer {
1008
1006
 
1009
1007
  this._buildAdvancedActions(container)
1010
1008
 
1011
- const backButton = DomUtil.createButtonIcon(
1012
- undefined,
1013
- 'icon-back',
1014
- translate('Back to layers')
1015
- )
1009
+ const backButton = DOMUtils.loadTemplate(`
1010
+ <button class="icon icon-16 icon-back" type="button" title="${translate('Back to layers')}"></button>
1011
+ `)
1016
1012
  // Fixme: remove me when this is merged and released
1017
1013
  // https://github.com/Leaflet/Leaflet/pull/9052
1018
1014
  DomEvent.disableClickPropagation(backButton)
1019
- DomEvent.on(backButton, 'click', this._umap.editDatalayers, this._umap)
1015
+ backButton.addEventListener('click', () => this._umap.editDatalayers())
1020
1016
 
1021
1017
  return this._umap.editPanel.open({
1022
1018
  content: container,
@@ -1067,14 +1063,14 @@ export class DataLayer {
1067
1063
  button.addEventListener('click', () => this.restore(data.ref))
1068
1064
  }
1069
1065
 
1070
- const versionsContainer = DomUtil.createFieldset(container, translate('Versions'), {
1071
- async callback() {
1066
+ const versionsContainer = DOMUtils.createFieldset(container, translate('Versions'))
1067
+ versionsContainer.closest('details').addEventListener('toggle', async (event) => {
1068
+ if (event.target.open) {
1072
1069
  const [{ versions }, response, error] = await this._umap.server.get(
1073
1070
  this.getVersionsUrl()
1074
1071
  )
1075
1072
  if (!error) versions.forEach(appendVersion)
1076
- },
1077
- context: this,
1073
+ }
1078
1074
  })
1079
1075
  }
1080
1076
 
@@ -1124,7 +1120,7 @@ export class DataLayer {
1124
1120
  // From now on, do not try to how/hide
1125
1121
  // automatically this layer, as user
1126
1122
  // has taken control on this.
1127
- this.autoLoaded = false
1123
+ this.autoVisibility = false
1128
1124
  let display = force
1129
1125
  if (force === undefined) {
1130
1126
  if (!this.isVisible()) display = true
@@ -1345,7 +1341,10 @@ export class DataLayer {
1345
1341
  rules.set(rule.condition, rule)
1346
1342
  }
1347
1343
  for (const rule of this._umap.rules) {
1348
- if (!rules.has(rule.condition) && this.fields.has(rule.key)) {
1344
+ if (
1345
+ !rules.has(rule.condition) &&
1346
+ (this.fields.has(rule.field.key) || this._umap.fields.has(rule.field.key))
1347
+ ) {
1349
1348
  rules.set(rule.condition, rule)
1350
1349
  }
1351
1350
  }
@@ -1364,31 +1363,17 @@ export class DataLayer {
1364
1363
  }
1365
1364
 
1366
1365
  renderToolbox(container) {
1367
- const toggle = DomUtil.createButtonIcon(
1368
- container,
1369
- 'icon-eye',
1370
- translate('Show/hide layer')
1371
- )
1372
- const table = DomUtil.createButtonIcon(
1373
- container,
1374
- 'icon-table show-on-edit',
1375
- translate('Edit properties in a table')
1376
- )
1377
- const zoomTo = DomUtil.createButtonIcon(
1378
- container,
1379
- 'icon-zoom',
1380
- translate('Zoom to layer extent')
1381
- )
1382
- const edit = DomUtil.createButtonIcon(
1383
- container,
1384
- 'icon-edit show-on-edit',
1385
- translate('Edit')
1386
- )
1387
- const remove = DomUtil.createButtonIcon(
1388
- container,
1389
- 'icon-delete show-on-edit',
1390
- translate('Delete layer')
1391
- )
1366
+ const [span, { toggle, table, zoomTo, edit, remove }] =
1367
+ DOMUtils.loadTemplateWithRefs(`
1368
+ <span>
1369
+ <button class="icon icon-16 icon-eye" title="${translate('Show/hide layer')}" type="button" data-ref="toggle"></button>
1370
+ <button class="icon icon-16 icon-table show-on-edit" title="${translate('Edit properties in a table')}" type="button" data-ref="table"></button>
1371
+ <button class="icon icon-16 icon-zoom" title="${translate('Zoom to layer extent')}" type="button" data-ref="zoomTo"></button>
1372
+ <button class="icon icon-16 icon-edit show-on-edit" title="${translate('Edit')}" type="button" data-ref="edit"></button>
1373
+ <button class="icon icon-16 icon-delete show-on-edit" title="${translate('Delete layer')}" type="button" data-ref="remove"></button>
1374
+ </span>
1375
+ `)
1376
+ container.appendChild(span)
1392
1377
  if (this.isReadOnly()) {
1393
1378
  container.classList.add('readonly')
1394
1379
  } else {
@@ -1412,7 +1397,7 @@ export class DataLayer {
1412
1397
  propagateDelete() {
1413
1398
  const els = this.getHidableElements()
1414
1399
  for (const el of els) {
1415
- DomUtil.remove(el)
1400
+ el.remove()
1416
1401
  }
1417
1402
  }
1418
1403
 
@@ -1425,15 +1410,15 @@ export class DataLayer {
1425
1410
 
1426
1411
  propagateHide() {
1427
1412
  const els = this.getHidableElements()
1428
- for (let i = 0; i < els.length; i++) {
1429
- DomUtil.addClass(els[i], 'off')
1413
+ for (const el of els) {
1414
+ el.classList.add('off')
1430
1415
  }
1431
1416
  }
1432
1417
 
1433
1418
  propagateShow() {
1434
1419
  const els = this.getHidableElements()
1435
- for (let i = 0; i < els.length; i++) {
1436
- DomUtil.removeClass(els[i], 'off')
1420
+ for (const el of els) {
1421
+ el.classList.remove('off')
1437
1422
  }
1438
1423
  }
1439
1424
  }
@@ -32,7 +32,7 @@ export const copyToClipboard = (textToCopy) => {
32
32
  tooltip.open({ content: translate('✅ Copied!'), duration: 5000 })
33
33
  }
34
34
 
35
- export const copiableInput = (parent, label, value) => {
35
+ export const copiableInput = (parent, label, value = '') => {
36
36
  const [container, { input, button }] = Utils.loadTemplateWithRefs(`
37
37
  <div class="copiable-input">
38
38
  <label>${label}<input type="text" readOnly value="${value}" data-ref=input /></label>
@@ -107,3 +107,23 @@ export const contrastedColor = (el, bgcolor) => {
107
107
  if (bgcolor) CACHE_CONTRAST[bgcolor] = out
108
108
  return out
109
109
  }
110
+
111
+ export const createFieldset = (parent, title, options) => {
112
+ options = options || {}
113
+ const [details, { summary, fieldset }] = loadTemplateWithRefs(`
114
+ <details class="${options.className || ''}">
115
+ <summary data-ref="summary"><h4>${title}</h4></summary>
116
+ <fieldset data-ref="fieldset"></fieldset>
117
+ </details>
118
+ `)
119
+ details.open = options.on === true
120
+ parent.appendChild(details)
121
+ if (options.icon) {
122
+ const icon = loadTemplate(`<i class="icon icon-16 ${options.icon}"></i>`)
123
+ summary.insertBefore(icon, summary.firstChild)
124
+ }
125
+ return fieldset
126
+ }
127
+
128
+ export const loadTemplateWithRefs = Utils.loadTemplateWithRefs
129
+ export const loadTemplate = Utils.loadTemplate
@@ -6,27 +6,6 @@ import { Fields } from './form/fields.js'
6
6
 
7
7
  const EMPTY_VALUE = translate('<empty value>')
8
8
 
9
- const getParser = (type) => {
10
- switch (type) {
11
- case 'Number':
12
- return Number.parseFloat
13
- case 'Datetime':
14
- return (v) => new Date(v)
15
- case 'Date':
16
- return Utils.parseNaiveDate
17
- case 'Boolean':
18
- return Boolean
19
- case 'Enum':
20
- return (v) => {
21
- if (!v) return [EMPTY_VALUE]
22
- return String(v || '')
23
- .split(',')
24
- .map((s) => s.trim())
25
- }
26
- default:
27
- return (v) => String(v || '')
28
- }
29
- }
30
9
  const Widgets = {}
31
10
 
32
11
  class BaseWidget {
@@ -73,13 +52,13 @@ Widgets.MinMax = class extends BaseWidget {
73
52
  return this.userData.min !== undefined || this.userData.max !== undefined
74
53
  }
75
54
  getFormField(field) {
76
- if (field.type === 'Number') {
55
+ if (field.TYPE === 'Number') {
77
56
  return 'FilterByNumber'
78
57
  }
79
- if (field.type === 'Date') {
58
+ if (field.TYPE === 'Date') {
80
59
  return 'FilterByDate'
81
60
  }
82
- if (field.type === 'Datetime') {
61
+ if (field.TYPE === 'Datetime') {
83
62
  return 'FilterByDateTime'
84
63
  }
85
64
  return super.getFormField(field)
@@ -186,16 +165,15 @@ export class Filters {
186
165
  // and max values.
187
166
  computeInitialData() {
188
167
  const initialData = Object.fromEntries(
189
- this.available.keys().map((name) => [name, {}])
168
+ Array.from(this.available.keys()).map((name) => [name, {}])
190
169
  )
191
170
 
192
171
  for (const [name, filter] of this.available.entries()) {
193
172
  const field = this._parent.fields.get(name)
194
173
  if (!field) continue
195
- const parser = getParser(field.type)
196
174
  this._parent.eachFeature((feature) => {
197
175
  let value = feature.properties[name]
198
- value = parser(value)
176
+ value = field.parse(value)
199
177
  filter.computeInitialData(initialData[name], value)
200
178
  })
201
179
  }
@@ -228,14 +206,8 @@ export class Filters {
228
206
  }
229
207
 
230
208
  load() {
231
- let filters = this._parent.properties.filters || []
232
- // TMP fix for dev server to update map created before changing
233
- // filters to be an array
234
- if (typeof filters === 'object' && !Array.isArray(filters) && filters !== null) {
235
- filters = Object.entries(filters).map(([fieldKey, props]) => {
236
- return { fieldKey, ...props }
237
- })
238
- }
209
+ let filters = this._parent.properties.filters
210
+ if (!Array.isArray(filters)) filters = []
239
211
  for (const filter of filters) {
240
212
  this._add({ ...filter })
241
213
  }
@@ -377,9 +349,9 @@ export class Filters {
377
349
  createFilterForm(fieldKey) {
378
350
  let widget = 'Checkbox'
379
351
  const field = this._parent.fields.get(fieldKey)
380
- if (['Number', 'Date', 'Datetime'].includes(field?.type)) {
352
+ if (['Number', 'Date', 'Datetime'].includes(field?.TYPE)) {
381
353
  widget = 'MinMax'
382
- } else if (field?.type === 'Boolean') {
354
+ } else if (field?.TYPE === 'Boolean') {
383
355
  widget = 'Switch'
384
356
  }
385
357
  const properties = {
@@ -392,7 +364,9 @@ export class Filters {
392
364
  ? [fieldKey]
393
365
  : [
394
366
  '',
395
- ...this._parent.fieldKeys.filter((fieldKey) => !this.available.has(fieldKey)),
367
+ ...Array.from(this._parent.fields.keys()).filter(
368
+ (fieldKey) => !this.available.has(fieldKey)
369
+ ),
396
370
  ]
397
371
  const metadata = [
398
372
  [
@@ -474,8 +448,7 @@ export class Filters {
474
448
  // This field may only exist on another layer.
475
449
  if (!field) continue
476
450
  let value = feature.properties[fieldKey]
477
- const parser = getParser(field.type)
478
- value = parser(value)
451
+ value = field.parse(value)
479
452
  if (obj.match(value)) return true
480
453
  }
481
454
  return false
@@ -746,7 +746,7 @@ Fields.PropertyInput = class extends Fields.BlurInput {
746
746
  super.build()
747
747
  const autocomplete = new AutocompleteDatalist(this.input)
748
748
  // Will be used on Umap and DataLayer
749
- const properties = this.builder.obj.fieldKeys
749
+ const properties = Array.from(this.builder.obj.fields.keys())
750
750
  autocomplete.suggestions = properties
751
751
  }
752
752
  }
@@ -1217,7 +1217,7 @@ Fields.ManageOwner = class extends Fields.Base {
1217
1217
  super.build()
1218
1218
  const options = {
1219
1219
  className: 'edit-owner',
1220
- on_select: L.bind(this.onSelect, this),
1220
+ on_select: (choice) => this.onSelect(choice),
1221
1221
  placeholder: translate("Type new owner's username"),
1222
1222
  }
1223
1223
  this.autocomplete = new AjaxAutocomplete(this.container, options)
@@ -1248,8 +1248,8 @@ Fields.ManageEditors = class extends Fields.Base {
1248
1248
  super.build()
1249
1249
  const options = {
1250
1250
  className: 'edit-editors',
1251
- on_select: L.bind(this.onSelect, this),
1252
- on_unselect: L.bind(this.onUnselect, this),
1251
+ on_select: (choice) => this.onSelect(choice),
1252
+ on_unselect: (choice) => this.onUnselect(choice),
1253
1253
  placeholder: translate("Type editor's username"),
1254
1254
  }
1255
1255
  this.autocomplete = new AjaxAutocompleteMultiple(this.container, options)
@@ -71,7 +71,15 @@ export class Formatter {
71
71
  } catch (e) {
72
72
  src = this.toDom(str)
73
73
  }
74
- return osmtogeojson(src, { flatProperties: true })
74
+ const data = osmtogeojson(src, { flatProperties: true })
75
+ // FIXME: make a PR to osmtogeojson when it's more active
76
+ // cf https://github.com/umap-project/umap/issues/3072
77
+ for (const feature of data.features || []) {
78
+ const [osm_type, osm_id] = feature.properties.id.split('/')
79
+ feature.properties.osm_id = osm_id
80
+ feature.properties.osm_type = osm_type
81
+ }
82
+ return data
75
83
  }
76
84
 
77
85
  fromCSV(str, callback) {
@@ -1,7 +1,7 @@
1
- import { DomEvent, DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js'
2
1
  import { translate } from './i18n.js'
3
2
  import Dialog from './ui/dialog.js'
4
3
  import * as Utils from './utils.js'
4
+ import * as DOMUtils from './domutils.js'
5
5
 
6
6
  const SHORTCUTS = {
7
7
  DRAW_MARKER: {
@@ -209,15 +209,15 @@ export default class Help {
209
209
  }
210
210
 
211
211
  show(entries) {
212
- const container = DomUtil.add('div')
213
- DomUtil.createTitle(container, translate('Help'))
212
+ const container = DOMUtils.loadTemplate(`
213
+ <div>
214
+ <h3><i class="icon icon-16 icon-help"></i> ${translate('Help')}</h3>
215
+ </div>
216
+ `)
214
217
  for (const name of entries) {
215
- DomUtil.element({
216
- tagName: 'div',
217
- className: 'umap-help-entry',
218
- parent: container,
219
- innerHTML: ENTRIES[name],
220
- })
218
+ container.appendChild(
219
+ DOMUtils.loadTemplate(`<div class="umap-help-entry">${ENTRIES[name]}</div>`)
220
+ )
221
221
  }
222
222
  this.dialog.open({ template: container })
223
223
  }
@@ -253,11 +253,10 @@ export default class Help {
253
253
  }
254
254
 
255
255
  button(container, entries) {
256
- const button = DomUtil.createButton(
257
- 'umap-help-button',
258
- container,
259
- translate('Help')
256
+ const button = DOMUtils.loadTemplate(
257
+ `<button class="umap-help-button" type="button">${translate('Help')}</button>`
260
258
  )
259
+ container.appendChild(button)
261
260
  button.addEventListener('click', () => this.show(entries))
262
261
  return button
263
262
  }
@@ -1,13 +1,10 @@
1
- import {
2
- DomEvent,
3
- DomUtil,
4
- LatLngBounds,
5
- } from '../../vendors/leaflet/leaflet-src.esm.js'
1
+ import { LatLngBounds } from '../../vendors/leaflet/leaflet-src.esm.js'
6
2
  import { uMapAlert as Alert } from '../components/alerts/alert.js'
7
3
  import { translate } from './i18n.js'
8
4
  import { SCHEMA } from './schema.js'
9
5
  import Dialog from './ui/dialog.js'
10
6
  import * as Utils from './utils.js'
7
+ import * as DOMUtils from './domutils.js'
11
8
 
12
9
  const TEMPLATE = `
13
10
  <div class="umap-import">
@@ -203,18 +200,15 @@ export default class Importer extends Utils.WithTemplate {
203
200
  button.toggleAttribute('hidden', false)
204
201
  }
205
202
  for (const type of this.TYPES) {
206
- DomUtil.element({
207
- tagName: 'option',
208
- parent: this.qs('[name=format]'),
209
- value: type,
210
- textContent: type,
211
- })
203
+ this.qs('[name=format]').appendChild(
204
+ DOMUtils.loadTemplate(`<option value="${type}">${type}</option>`)
205
+ )
212
206
  }
213
207
  this._umap.help.parse(this.container)
214
208
  this.qs('[name=submit]').addEventListener('click', () => this.submit())
215
- DomEvent.on(this.qs('[type=file]'), 'change', this.onFileChange, this)
209
+ this.qs('[type=file]').addEventListener('change', () => this.onFileChange())
216
210
  for (const element of this.container.querySelectorAll('[onchange]')) {
217
- DomEvent.on(element, 'change', this.onChange, this)
211
+ element.addEventListener('change', () => this.onChange())
218
212
  }
219
213
  }
220
214
 
@@ -253,21 +247,18 @@ export default class Importer extends Utils.WithTemplate {
253
247
  layerSelect.innerHTML = ''
254
248
  this._umap.datalayers.reverse().map((datalayer) => {
255
249
  if (datalayer.isLoaded() && !datalayer.isRemoteLayer()) {
256
- DomUtil.element({
257
- tagName: 'option',
258
- parent: layerSelect,
259
- textContent: datalayer.getName(),
260
- value: datalayer.id,
261
- })
250
+ layerSelect.appendChild(
251
+ DOMUtils.loadTemplate(
252
+ `<option value="${datalayer.id}">${datalayer.getName()}</option>`
253
+ )
254
+ )
262
255
  }
263
256
  })
264
- DomUtil.element({
265
- tagName: 'option',
266
- value: '',
267
- textContent: translate('Import in a new layer'),
268
- parent: layerSelect,
269
- selected: true,
270
- })
257
+ layerSelect.appendChild(
258
+ DOMUtils.loadTemplate(
259
+ `<option value="" selected>${translate('Import in a new layer')}</option>`
260
+ )
261
+ )
271
262
  }
272
263
 
273
264
  open() {
@@ -1,4 +1,3 @@
1
- import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
1
  import { uMapAlert as Alert } from '../../components/alerts/alert.js'
3
2
  import { BaseAjax, SingleMixin } from '../autocomplete.js'
4
3
  import { translate } from '../i18n.js'