umap-project 2.7.0__py3-none-any.whl → 2.7.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 (72) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  3. umap/locale/es/LC_MESSAGES/django.po +128 -134
  4. umap/settings/base.py +1 -1
  5. umap/static/umap/css/contextmenu.css +1 -1
  6. umap/static/umap/css/importers.css +0 -4
  7. umap/static/umap/img/16.svg +184 -1
  8. umap/static/umap/img/24-white.svg +0 -1
  9. umap/static/umap/img/24.svg +0 -1
  10. umap/static/umap/img/source/16.svg +200 -753
  11. umap/static/umap/img/source/24-white.svg +2 -3
  12. umap/static/umap/img/source/24.svg +2 -3
  13. umap/static/umap/js/modules/browser.js +0 -47
  14. umap/static/umap/js/modules/caption.js +4 -10
  15. umap/static/umap/js/modules/data/layer.js +14 -26
  16. umap/static/umap/js/modules/importer.js +0 -3
  17. umap/static/umap/js/modules/importers/communesfr.js +2 -2
  18. umap/static/umap/js/modules/rendering/layers/classified.js +0 -2
  19. umap/static/umap/js/modules/rendering/ui.js +6 -28
  20. umap/static/umap/js/modules/share.js +3 -1
  21. umap/static/umap/js/modules/slideshow.js +1 -1
  22. umap/static/umap/js/modules/sync/engine.js +8 -14
  23. umap/static/umap/js/modules/sync/hlc.js +3 -3
  24. umap/static/umap/js/modules/sync/updaters.js +2 -14
  25. umap/static/umap/js/modules/tableeditor.js +1 -1
  26. umap/static/umap/js/modules/ui/contextmenu.js +2 -18
  27. umap/static/umap/js/modules/utils.js +4 -24
  28. umap/static/umap/js/umap.controls.js +10 -31
  29. umap/static/umap/js/umap.core.js +1 -1
  30. umap/static/umap/js/umap.js +23 -31
  31. umap/static/umap/locale/ca.js +4 -8
  32. umap/static/umap/locale/ca.json +4 -8
  33. umap/static/umap/locale/en.js +1 -5
  34. umap/static/umap/locale/en.json +1 -5
  35. umap/static/umap/locale/es.js +319 -330
  36. umap/static/umap/locale/es.json +319 -330
  37. umap/static/umap/locale/fr.js +1 -5
  38. umap/static/umap/locale/fr.json +1 -5
  39. umap/static/umap/map.css +7 -37
  40. umap/static/umap/unittests/hlc.js +3 -10
  41. umap/static/umap/unittests/utils.js +0 -24
  42. umap/static/umap/vars.css +1 -2
  43. umap/static/umap/vendors/colorbrewer/colorbrewer.js +317 -309
  44. umap/static/umap/vendors/dompurify/purify.es.js +16 -15
  45. umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
  46. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js +2 -2
  47. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js.map +1 -1
  48. umap/static/umap/vendors/simple-statistics/simple-statistics.min.js +1 -1
  49. umap/static/umap/vendors/simple-statistics/simple-statistics.min.js.map +1 -1
  50. umap/templates/umap/css.html +2 -0
  51. umap/templates/umap/js.html +1 -0
  52. umap/templates/umap/map_detail.html +2 -2
  53. umap/tests/fixtures/test_upload_data.csv +2 -2
  54. umap/tests/integration/test_browser.py +7 -69
  55. umap/tests/integration/test_caption.py +3 -3
  56. umap/tests/integration/test_datalayer.py +5 -1
  57. umap/tests/integration/test_edit_datalayer.py +2 -1
  58. umap/tests/integration/test_edit_map.py +1 -1
  59. umap/tests/integration/test_edit_marker.py +1 -1
  60. umap/tests/integration/test_facets_browser.py +3 -3
  61. umap/tests/integration/test_import.py +4 -0
  62. umap/tests/integration/test_map.py +4 -0
  63. umap/tests/integration/test_view_marker.py +0 -63
  64. umap/tests/test_map_views.py +0 -19
  65. {umap_project-2.7.0.dist-info → umap_project-2.7.0b0.dist-info}/METADATA +10 -14
  66. {umap_project-2.7.0.dist-info → umap_project-2.7.0b0.dist-info}/RECORD +69 -72
  67. umap/asgi.py +0 -15
  68. umap/static/umap/img/importers/cadastrefr.svg +0 -23
  69. umap/static/umap/js/modules/importers/cadastrefr.js +0 -62
  70. {umap_project-2.7.0.dist-info → umap_project-2.7.0b0.dist-info}/WHEEL +0 -0
  71. {umap_project-2.7.0.dist-info → umap_project-2.7.0b0.dist-info}/entry_points.txt +0 -0
  72. {umap_project-2.7.0.dist-info → umap_project-2.7.0b0.dist-info}/licenses/LICENSE +0 -0
@@ -1,8 +1,8 @@
1
1
  <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
2
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
3
 
4
- <svg width="252" height="252" viewBox="0 0 66.674992 66.674992" version="1.1" id="svg2876" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" sodipodi:docname="24-white.svg" inkscape:export-filename="../24-white.svg" inkscape:export-xdpi="7.52" inkscape:export-ydpi="7.52" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
5
- <sodipodi:namedview id="namedview2878" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" showguides="true" inkscape:zoom="5.3566812" inkscape:cx="50.030978" inkscape:cy="170.06799" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="layer1">
4
+ <svg width="252" height="252" viewBox="0 0 66.674992 66.674992" version="1.1" id="svg2876" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" sodipodi:docname="24-white.svg" inkscape:export-filename="../24-white.svg" inkscape:export-xdpi="7.52" inkscape:export-ydpi="7.52" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
5
+ <sodipodi:namedview id="namedview2878" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" showguides="true" inkscape:zoom="2.6753614" inkscape:cx="107.64901" inkscape:cy="85.409023" inkscape:window-width="960" inkscape:window-height="1011" inkscape:window-x="20" inkscape:window-y="20" inkscape:window-maximized="0" inkscape:current-layer="layer1">
6
6
  <inkscape:grid type="xygrid" id="grid2997" empspacing="6" originx="0" originy="0" spacingy="0.2645833" spacingx="0.2645833" units="px" visible="true" />
7
7
  <inkscape:grid id="grid1" units="px" originx="0" originy="0" spacingx="9.5249989" spacingy="9.5249989" empcolor="#3f3fff" empopacity="0.25098039" color="#3f3fff" opacity="0.1254902" empspacing="1" dotted="false" gridanglex="30" gridanglez="30" visible="true" />
8
8
  </sodipodi:namedview>
@@ -74,6 +74,5 @@
74
74
  <g id="info" transform="matrix(0.33072916,0,0,0.33072916,-11.906249,-256.10415)" style="stroke-width:0.8">
75
75
  <path id="path3762" style="fill:#f2f2f2;fill-opacity:1;stroke:#999999;stroke-width:0.2;stroke-dasharray:none;stroke-opacity:1" d="m 107.99999,838.36217 a 8,8 0 0 0 -7.999998,8 8,8 0 0 0 7.999998,8 8,8 0 0 0 8,-8 8,8 0 0 0 -8,-8 z m 0,2.5 a 1.5,1.5 0 0 1 1.5,1.5 1.5,1.5 0 0 1 -1.5,1.5 1.5,1.5 0 0 1 -1.5,-1.5 1.5,1.5 0 0 1 1.5,-1.5 z m -1,4.5 h 2 v 6 h -2 z" />
76
76
  </g>
77
- <path d="m 5.6444435,59.43432 v 1.034991 h 1.0541546 z m 1.1759257,1.612262 h -1.1759257 c -0.3247228,0 -0.5879626,-0.258453 -0.5879626,-0.577271 v -1.154545 h -2.3518514 v 5.195451 h 4.1157397 z m -4.1157397,-2.309089 h 3.0615854 l 1.6421175,1.612259 v 4.160465 c 0,0.318822 -0.2632403,0.577275 -0.5879632,0.577275 h -4.1157397 c -0.3247231,0 -0.5879631,-0.258453 -0.5879631,-0.577275 v -5.195451 c 0,-0.31882 0.26324,-0.577273 0.5879631,-0.577273 z m 1.7638882,3.92135 v -1.323625 h 0.5879632 v 1.323625 l 0.3800861,-0.373177 0.415753,0.408196 -1.0898206,1.070004 -1.0898208,-1.070004 0.4157526,-0.408196 z" fill-rule="evenodd" id="downloadfile" style="fill:#f2f2f2;fill-opacity:1;stroke-width:0.06614583;stroke:#999999;stroke-opacity:0.50980395;stroke-dasharray:none" />
78
77
  </g>
79
78
  </svg>
@@ -1,8 +1,8 @@
1
1
  <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
2
  <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
3
 
4
- <svg width="252" height="252" viewBox="0 0 66.674999 66.674999" version="1.1" id="svg6237" inkscape:version="1.4 (e7c3feb100, 2024-10-09)" sodipodi:docname="24.svg" inkscape:export-filename="../24.svg" inkscape:export-xdpi="7.52" inkscape:export-ydpi="7.52" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
5
- <sodipodi:namedview id="namedview6239" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" showguides="true" inkscape:zoom="3.1596124" inkscape:cx="118.68544" inkscape:cy="166.47612" inkscape:window-width="1920" inkscape:window-height="1011" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="layer1">
4
+ <svg width="252" height="252" viewBox="0 0 66.674999 66.674999" version="1.1" id="svg6237" inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" sodipodi:docname="24.svg" inkscape:export-filename="../24.svg" inkscape:export-xdpi="7.52" inkscape:export-ydpi="7.52" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
5
+ <sodipodi:namedview id="namedview6239" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" showgrid="true" showguides="true" inkscape:zoom="3.1596124" inkscape:cx="117.10297" inkscape:cy="106.50041" inkscape:window-width="960" inkscape:window-height="1011" inkscape:window-x="20" inkscape:window-y="20" inkscape:window-maximized="0" inkscape:current-layer="layer1">
6
6
  <inkscape:grid type="xygrid" id="grid6358" empspacing="6" originx="0" originy="0" spacingy="0.26458333" spacingx="0.26458333" units="px" visible="true" />
7
7
  <inkscape:grid id="grid1" units="px" originx="0" originy="0" spacingx="9.5249999" spacingy="9.5249999" empcolor="#3f3fff" empopacity="0.25098039" color="#ff0000" opacity="0.83529412" empspacing="0" dotted="false" gridanglex="30" gridanglez="30" visible="true" />
8
8
  </sodipodi:namedview>
@@ -98,6 +98,5 @@
98
98
  <g id="info" transform="matrix(0.33072916,0,0,0.33072916,-11.90625,-256.10415)" style="fill:#4d4d4d;fill-opacity:1;stroke-width:0.8">
99
99
  <path id="path3762" style="fill:#4d4d4d;fill-opacity:1;stroke:none;stroke-width:0.8" d="m 108,838.36217 a 8,8 0 0 0 -8,8 8,8 0 0 0 8,8 8,8 0 0 0 8,-8 8,8 0 0 0 -8,-8 z m 0,2.5 a 1.5,1.5 0 0 1 1.5,1.5 1.5,1.5 0 0 1 -1.5,1.5 1.5,1.5 0 0 1 -1.5,-1.5 1.5,1.5 0 0 1 1.5,-1.5 z m -1,4.5 h 2 v 6 h -2 z" />
100
100
  </g>
101
- <path d="m 5.6444435,59.43432 v 1.034991 h 1.0541546 z m 1.1759257,1.612262 h -1.1759257 c -0.3247228,0 -0.5879626,-0.258453 -0.5879626,-0.577271 v -1.154545 h -2.3518514 v 5.195451 h 4.1157397 z m -4.1157397,-2.309089 h 3.0615854 l 1.6421175,1.612259 v 4.160465 c 0,0.318822 -0.2632403,0.577275 -0.5879632,0.577275 h -4.1157397 c -0.3247231,0 -0.5879631,-0.258453 -0.5879631,-0.577275 v -5.195451 c 0,-0.31882 0.26324,-0.577273 0.5879631,-0.577273 z m 1.7638882,3.92135 v -1.323625 h 0.5879632 v 1.323625 l 0.3800861,-0.373177 0.415753,0.408196 -1.0898206,1.070004 -1.0898208,-1.070004 0.4157526,-0.408196 z" fill-rule="evenodd" id="downloadfile" style="fill:#464646;fill-opacity:1;stroke-width:0.192424" />
102
101
  </g>
103
102
  </svg>
@@ -1,9 +1,6 @@
1
1
  import { DomEvent, DomUtil, stamp } from '../../vendors/leaflet/leaflet-src.esm.js'
2
2
  import { translate } from './i18n.js'
3
3
  import * as Icon from './rendering/icon.js'
4
- import * as Utils from './utils.js'
5
- import { EXPORT_FORMATS } from './formatter.js'
6
- import ContextMenu from './ui/contextmenu.js'
7
4
 
8
5
  export default class Browser {
9
6
  constructor(map) {
@@ -101,7 +98,6 @@ export default class Browser {
101
98
  datalayer.eachFeature((feature) => this.addFeature(feature, container))
102
99
 
103
100
  const total = datalayer.count()
104
- if (!total) return
105
101
  const current = container.querySelectorAll('li').length
106
102
  const count = total === current ? total : `${current}/${total}`
107
103
  const counter = DomUtil.create('span', 'datalayer-counter', headline)
@@ -168,7 +164,6 @@ export default class Browser {
168
164
  })
169
165
  this.filtersTitle = container.querySelector('summary')
170
166
  this.toggleBadge()
171
- this.addMainToolbox(container)
172
167
  this.dataContainer = DomUtil.create('div', '', container)
173
168
 
174
169
  let fields = [
@@ -220,48 +215,6 @@ export default class Browser {
220
215
  }
221
216
  }
222
217
 
223
- addMainToolbox(container) {
224
- const [toolbox, { toggle, fitBounds, download }] = Utils.loadTemplateWithRefs(`
225
- <div class="main-toolbox">
226
- <i class="icon icon-16 icon-eye" title="${translate('show/hide all layers')}" data-ref="toggle"></i>
227
- <i class="icon icon-16 icon-zoom" title="${translate('zoom to data extent')}" data-ref="fitBounds"></i>
228
- <i class="icon icon-16 icon-download" title="${translate('download visible data')}" data-ref="download"></i>
229
- </div>
230
- `)
231
- container.appendChild(toolbox)
232
- toggle.addEventListener('click', () => this.toggleLayers())
233
- fitBounds.addEventListener('click', () => this.map.fitDataBounds())
234
- download.addEventListener('click', () => this.downloadVisible(download))
235
- }
236
-
237
- downloadVisible(element) {
238
- const menu = new ContextMenu({ fixed: true })
239
- const items = []
240
- for (const format of Object.keys(EXPORT_FORMATS)) {
241
- items.push({
242
- label: format,
243
- action: () => this.map.share.download(format),
244
- })
245
- }
246
- menu.openBelow(element, items)
247
- }
248
-
249
- toggleLayers() {
250
- // If at least one layer is shown, hide it
251
- // otherwise show all
252
- let allHidden = true
253
- this.map.eachBrowsableDataLayer((datalayer) => {
254
- if (datalayer.isVisible()) allHidden = false
255
- })
256
- this.map.eachBrowsableDataLayer((datalayer) => {
257
- if (allHidden) {
258
- datalayer.show()
259
- } else {
260
- if (datalayer.isVisible()) datalayer.hide()
261
- }
262
- })
263
- }
264
-
265
218
  static backButton(map) {
266
219
  const button = DomUtil.createButtonIcon(
267
220
  DomUtil.create('li', '', undefined),
@@ -40,21 +40,15 @@ export default class Caption {
40
40
  )
41
41
  const creditsContainer = DomUtil.create('div', 'credits-container', container)
42
42
  this.addCredits(creditsContainer)
43
- this.map.panel.open({ content: container }).then(() => {
44
- // Create the legend when the panel is actually on the DOM
45
- this.map.eachDataLayerReverse((datalayer) => datalayer.renderLegend())
46
- })
43
+ this.map.panel.open({ content: container })
47
44
  }
48
45
 
49
46
  addDataLayer(datalayer, container) {
50
47
  if (!datalayer.options.inCaption) return
51
- const p = DomUtil.create(
52
- 'p',
53
- `caption-item ${datalayer.cssId}`,
54
- container
55
- )
56
- const legend = DomUtil.create('span', 'datalayer-legend', p)
48
+ const p = DomUtil.create('p', 'datalayer-legend', container)
49
+ const legend = DomUtil.create('span', '', p)
57
50
  const headline = DomUtil.create('strong', '', p)
51
+ datalayer.renderLegend(legend)
58
52
  if (datalayer.options.description) {
59
53
  DomUtil.element({
60
54
  tagName: 'span',
@@ -115,10 +115,6 @@ export class DataLayer {
115
115
  return this._isDeleted
116
116
  }
117
117
 
118
- get cssId() {
119
- return `datalayer-${stamp(this)}`
120
- }
121
-
122
118
  getSyncMetadata() {
123
119
  return {
124
120
  subject: 'datalayer',
@@ -239,7 +235,6 @@ export class DataLayer {
239
235
  }
240
236
 
241
237
  dataChanged() {
242
- if (!this.hasDataLoaded()) return
243
238
  this.map.onDataLayersChanged()
244
239
  this.layer.dataChanged()
245
240
  }
@@ -247,13 +242,8 @@ export class DataLayer {
247
242
  fromGeoJSON(geojson, sync = true) {
248
243
  this.addData(geojson, sync)
249
244
  this._geojson = geojson
250
- this.onDataLoaded()
251
- this.dataChanged()
252
- }
253
-
254
- onDataLoaded() {
255
245
  this._dataloaded = true
256
- this.renderLegend()
246
+ this.dataChanged()
257
247
  }
258
248
 
259
249
  async fromUmapGeoJSON(geojson) {
@@ -394,7 +384,7 @@ export class DataLayer {
394
384
  this.indexProperties(feature)
395
385
  this.map.features_index[feature.getSlug()] = feature
396
386
  this.showFeature(feature)
397
- this.dataChanged()
387
+ if (this.hasDataLoaded()) this.dataChanged()
398
388
  }
399
389
 
400
390
  removeFeature(feature, sync) {
@@ -405,7 +395,7 @@ export class DataLayer {
405
395
  feature.disconnectFromDataLayer(this)
406
396
  this._index.splice(this._index.indexOf(id), 1)
407
397
  delete this._features[id]
408
- if (this.isVisible()) this.dataChanged()
398
+ if (this.hasDataLoaded() && this.isVisible()) this.dataChanged()
409
399
  }
410
400
 
411
401
  indexProperties(feature) {
@@ -812,12 +802,13 @@ export class DataLayer {
812
802
  this
813
803
  )
814
804
  if (this.umap_id) {
815
- const filename = `${Utils.slugify(this.options.name)}.geojson`
816
- const download = Utils.loadTemplate(`
817
- <a class="button" href="${this._dataUrl()}" download="${filename}">
818
- <i class="icon icon-24 icon-download"></i>${translate('Download')}
819
- </a>`)
820
- advancedButtons.appendChild(download)
805
+ const download = DomUtil.createLink(
806
+ 'button umap-download',
807
+ advancedButtons,
808
+ translate('Download'),
809
+ this._dataUrl(),
810
+ '_blank'
811
+ )
821
812
  }
822
813
  const backButton = DomUtil.createButtonIcon(
823
814
  undefined,
@@ -1129,13 +1120,10 @@ export class DataLayer {
1129
1120
  return 'displayName'
1130
1121
  }
1131
1122
 
1132
- renderLegend() {
1133
- for (const container of document.querySelectorAll(`.${this.cssId} .datalayer-legend`)) {
1134
- container.innerHTML = ''
1135
- if (this.layer.renderLegend) return this.layer.renderLegend(container)
1136
- const color = DomUtil.create('span', 'datalayer-color', container)
1137
- color.style.backgroundColor = this.getColor()
1138
- }
1123
+ renderLegend(container) {
1124
+ if (this.layer.renderLegend) return this.layer.renderLegend(container)
1125
+ const color = DomUtil.create('span', 'datalayer-color', container)
1126
+ color.style.backgroundColor = this.getColor()
1139
1127
  }
1140
1128
 
1141
1129
  renderToolbox(container) {
@@ -69,9 +69,6 @@ export default class Importer {
69
69
  case 'communesfr':
70
70
  import('./importers/communesfr.js').then(register)
71
71
  break
72
- case 'cadastrefr':
73
- import('./importers/cadastrefr.js').then(register)
74
- break
75
72
  case 'overpass':
76
73
  import('./importers/overpass.js').then(register)
77
74
  break
@@ -2,7 +2,7 @@ import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
2
  import { BaseAjax, SingleMixin } from '../autocomplete.js'
3
3
  import * as Util from '../utils.js'
4
4
 
5
- export class AutocompleteCommunes extends SingleMixin(BaseAjax) {
5
+ class Autocomplete extends SingleMixin(BaseAjax) {
6
6
  createResult(item) {
7
7
  return super.createResult({
8
8
  value: item.code,
@@ -46,7 +46,7 @@ export class Importer {
46
46
  importer.dialog.close()
47
47
  },
48
48
  }
49
- this.autocomplete = new AutocompleteCommunes(container, options)
49
+ this.autocomplete = new Autocomplete(container, options)
50
50
 
51
51
  importer.dialog.open({
52
52
  template: container,
@@ -3,7 +3,6 @@ import { translate } from '../../i18n.js'
3
3
  import { LayerMixin } from './base.js'
4
4
  import * as Utils from '../../utils.js'
5
5
  import { CircleMarker } from '../ui.js'
6
- import colorbrewer from '../../../../vendors/colorbrewer/colorbrewer.js'
7
6
 
8
7
  // Layer where each feature color is relative to the others,
9
8
  // so we need all features before behing able to set one
@@ -75,7 +74,6 @@ const ClassifiedMixin = {
75
74
  },
76
75
 
77
76
  renderLegend: function (container) {
78
- if (!this.datalayer.hasDataLoaded()) return
79
77
  const parent = DomUtil.create('ul', '', container)
80
78
  const items = this.getLegendItems()
81
79
  for (const [color, label] of items) {
@@ -36,12 +36,6 @@ const FeatureMixin = {
36
36
  }
37
37
  },
38
38
 
39
- _removeIcon: function () {
40
- // It may not be in the DOM, and Leaflet does not deal with this
41
- // situation
42
- if (this._icon) Marker.prototype._removeIcon.call(this)
43
- },
44
-
45
39
  addInteractions: function () {
46
40
  this.on('contextmenu editable:vertex:contextmenu', this.onContextMenu)
47
41
  this.on('click', this.onClick)
@@ -92,10 +86,12 @@ const FeatureMixin = {
92
86
 
93
87
  onContextMenu: function (event) {
94
88
  DomEvent.stop(event)
95
- const items = this.feature
96
- .getContextMenuItems(event)
97
- .concat(this._map.getContextMenuItems(event))
98
- this._map.contextmenu.open(event.originalEvent, items)
89
+ const items = this._map.getContextMenuItems(event)
90
+ items.push('-', ...this.feature.getContextMenuItems(event))
91
+ this._map.contextmenu.open(
92
+ [event.originalEvent.clientX, event.originalEvent.clientY],
93
+ items
94
+ )
99
95
  },
100
96
 
101
97
  onCommit: function () {
@@ -167,12 +163,6 @@ export const LeafletMarker = Marker.extend({
167
163
  return this.setLatLng(latlng)
168
164
  },
169
165
 
170
- getEvents: function () {
171
- const events = Marker.prototype.getEvents.call(this)
172
- events.moveend = this.onMoveEnd
173
- return events
174
- },
175
-
176
166
  addInteractions() {
177
167
  PointMixin.addInteractions.call(this)
178
168
  this._popupHandlersAdded = true // prevent Leaflet from binding event on bindPopup
@@ -180,19 +170,7 @@ export const LeafletMarker = Marker.extend({
180
170
  this.on('popupclose', this.resetHighlight)
181
171
  },
182
172
 
183
- onMoveEnd: function () {
184
- this._initIcon()
185
- this.update()
186
- },
187
-
188
173
  _initIcon: function () {
189
- if (!this._map.getBounds().contains(this.getCenter())) {
190
- if (this._icon) this._removeIcon()
191
- if (this._tooltip && this.isTooltipOpen()) {
192
- this.unbindTooltip()
193
- }
194
- return
195
- }
196
174
  this.options.icon = this.getIcon()
197
175
  Marker.prototype._initIcon.call(this)
198
176
  // Allow to run code when icon is actually part of the DOM
@@ -142,7 +142,9 @@ export default class Share {
142
142
  async format(mode) {
143
143
  const type = EXPORT_FORMATS[mode]
144
144
  const content = await type.formatter(this.map)
145
- const filename = Utils.slugify(this.map.options.name) + type.ext
145
+ let name = this.map.options.name || 'data'
146
+ name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
147
+ const filename = name + type.ext
146
148
  return { content, filetype: type.filetype, filename }
147
149
  }
148
150
 
@@ -1,5 +1,5 @@
1
- import { translate } from './i18n.js'
2
1
  import { WithTemplate } from './utils.js'
2
+ import { translate } from './i18n.js'
3
3
 
4
4
  const TOOLBOX_TEMPLATE = `
5
5
  <ul class="umap-slideshow-toolbox dark">
@@ -1,7 +1,7 @@
1
- import * as Utils from '../utils.js'
2
- import { HybridLogicalClock } from './hlc.js'
3
1
  import { DataLayerUpdater, FeatureUpdater, MapUpdater } from './updaters.js'
4
2
  import { WebSocketTransport } from './websocket.js'
3
+ import { HybridLogicalClock } from './hlc.js'
4
+ import * as Utils from '../utils.js'
5
5
 
6
6
  /**
7
7
  * The syncEngine exposes an API to sync messages between peers over the network.
@@ -81,7 +81,7 @@ export class SyncEngine {
81
81
  }
82
82
 
83
83
  _send(inputMessage) {
84
- const message = this._operations.addLocal(inputMessage)
84
+ let message = this._operations.addLocal(inputMessage)
85
85
 
86
86
  if (this.offline) return
87
87
  if (this.transport) {
@@ -101,11 +101,6 @@ export class SyncEngine {
101
101
  updater.applyMessage(operation)
102
102
  }
103
103
 
104
- getNumberOfConnectedPeers() {
105
- if (this.peers) return this.peers.length
106
- return 0
107
- }
108
-
109
104
  /**
110
105
  * This is called by the transport layer on new messages,
111
106
  * and dispatches the different "on*" methods.
@@ -151,10 +146,10 @@ export class SyncEngine {
151
146
  onJoinResponse({ uuid, peers }) {
152
147
  debug('received join response', { uuid, peers })
153
148
  this.uuid = uuid
154
- this.onListPeersResponse({ peers })
149
+ this.peers = peers
155
150
 
156
151
  // Get one peer at random
157
- const randomPeer = this._getRandomPeer()
152
+ let randomPeer = this._getRandomPeer()
158
153
 
159
154
  if (randomPeer) {
160
155
  // Retrieve the operations which happened before join.
@@ -173,7 +168,6 @@ export class SyncEngine {
173
168
  onListPeersResponse({ peers }) {
174
169
  debug('received peerinfo', { peers })
175
170
  this.peers = peers
176
- this.updaters.map.update({ key: 'numberOfConnectedPeers' })
177
171
  }
178
172
 
179
173
  /**
@@ -254,7 +248,7 @@ export class SyncEngine {
254
248
  * @returns {string|bool} the selected peer uuid, or False if none was found.
255
249
  */
256
250
  _getRandomPeer() {
257
- const otherPeers = this.peers.filter((p) => p !== this.uuid)
251
+ let otherPeers = this.peers.filter((p) => p !== this.uuid)
258
252
  if (otherPeers.length > 0) {
259
253
  const random = Math.floor(Math.random() * otherPeers.length)
260
254
  return otherPeers[random]
@@ -308,7 +302,7 @@ export class Operations {
308
302
  * @returns {*} clock-aware message
309
303
  */
310
304
  addLocal(inputMessage) {
311
- const message = { ...inputMessage, hlc: this._hlc.tick() }
305
+ let message = { ...inputMessage, hlc: this._hlc.tick() }
312
306
  this._operations.push(message)
313
307
  return message
314
308
  }
@@ -348,7 +342,7 @@ export class Operations {
348
342
  */
349
343
  storeRemoteOperations(remoteOperations) {
350
344
  // get the highest date from the passed operations
351
- const greatestHLC = remoteOperations
345
+ let greatestHLC = remoteOperations
352
346
  .map((op) => op.hlc)
353
347
  .reduce((max, current) => (current > max ? current : max))
354
348
 
@@ -30,12 +30,12 @@ export class HybridLogicalClock {
30
30
  * @returns object
31
31
  */
32
32
  parse(raw) {
33
- const tokens = raw.split(':')
33
+ let tokens = raw.split(':')
34
34
 
35
35
  if (tokens.length !== 3) {
36
36
  throw new SyntaxError(`Unable to parse ${raw}`)
37
37
  }
38
- const [walltime, rawNN, id] = tokens
38
+ let [walltime, rawNN, id] = tokens
39
39
 
40
40
  let nn = Number.parseInt(rawNN)
41
41
  if (Number.isNaN(nn)) {
@@ -92,7 +92,7 @@ export class HybridLogicalClock {
92
92
  if (now > local.walltime && now > remote.walltime) {
93
93
  nextValue = { ...local, walltime: now }
94
94
  } else if (local.walltime == remote.walltime) {
95
- const nn = Math.max(local.nn, remote.nn) + 1
95
+ let nn = Math.max(local.nn, remote.nn) + 1
96
96
  nextValue = { ...local, nn: nn }
97
97
  } else if (remote.walltime > local.walltime) {
98
98
  nextValue = { ...remote, id: local.id, nn: remote.nn + 1 }
@@ -1,5 +1,3 @@
1
- import { fieldInSchema } from '../utils.js'
2
-
3
1
  /**
4
2
  * Updaters are classes able to convert messages
5
3
  * received from other peers (or from the server) to changes on the map.
@@ -44,10 +42,7 @@ class BaseUpdater {
44
42
 
45
43
  export class MapUpdater extends BaseUpdater {
46
44
  update({ key, value }) {
47
- if (fieldInSchema(key)) {
48
- this.updateObjectValue(this.map, key, value)
49
- }
50
-
45
+ this.updateObjectValue(this.map, key, value)
51
46
  this.map.render([key])
52
47
  }
53
48
  }
@@ -61,14 +56,7 @@ export class DataLayerUpdater extends BaseUpdater {
61
56
 
62
57
  update({ key, metadata, value }) {
63
58
  const datalayer = this.getDataLayerFromID(metadata.id)
64
- if (fieldInSchema(key)) {
65
- this.updateObjectValue(datalayer, key, value)
66
- } else {
67
- console.debug(
68
- 'Not applying update for datalayer because key is not in the schema',
69
- key
70
- )
71
- }
59
+ this.updateObjectValue(datalayer, key, value)
72
60
  datalayer.render([key])
73
61
  }
74
62
  }
@@ -64,7 +64,7 @@ export default class TableEditor extends WithTemplate {
64
64
  action: () => this.deleteProperty(property),
65
65
  })
66
66
  }
67
- this.contextmenu.open(event, actions)
67
+ this.contextmenu.open([event.clientX, event.clientY], actions)
68
68
  }
69
69
 
70
70
  renderHeaders() {
@@ -15,18 +15,7 @@ export default class ContextMenu extends Positioned {
15
15
  })
16
16
  }
17
17
 
18
- open(event, items) {
19
- const left = event.clientX
20
- const top = event.clientY
21
- this.openAt([left, top], items)
22
- }
23
-
24
- openBelow(element, items) {
25
- const coords = this.getPosition(element)
26
- this.openAt([coords.left, coords.bottom], items)
27
- }
28
-
29
- openAt([left, top], items) {
18
+ open([left, top], items) {
30
19
  this.container.innerHTML = ''
31
20
  for (const item of items) {
32
21
  if (item === '-') {
@@ -47,12 +36,7 @@ export default class ContextMenu extends Positioned {
47
36
  this.container.appendChild(li)
48
37
  }
49
38
  }
50
- // When adding contextmenu below the map container, clicking on any link will send the
51
- // "focusout" element on link click, preventing to trigger the click action
52
- const parent = document
53
- .elementFromPoint(left, top)
54
- .closest('.leaflet-container').parentNode
55
- parent.appendChild(this.container)
39
+ document.body.appendChild(this.container)
56
40
  if (this.options.fixed) {
57
41
  this.setPosition({ left, top })
58
42
  } else {
@@ -35,7 +35,7 @@ export function checkId(string) {
35
35
  * @returns Array[string]
36
36
  */
37
37
  export function getImpactsFromSchema(fields, schema) {
38
- const current_schema = schema || U.SCHEMA
38
+ schema = schema || U.SCHEMA
39
39
  const impacted = fields
40
40
  .map((field) => {
41
41
  // remove the option prefix for fields
@@ -46,30 +46,14 @@ export function getImpactsFromSchema(fields, schema) {
46
46
  .reduce((acc, field) => {
47
47
  // retrieve the "impacts" field from the schema
48
48
  // and merge them together using sets
49
- const impacts = current_schema[field]?.impacts || []
50
- for (const impact of impacts) {
51
- acc.add(impact)
52
- }
49
+ const impacts = schema[field]?.impacts || []
50
+ impacts.forEach((impact) => acc.add(impact))
53
51
  return acc
54
52
  }, new Set())
55
53
 
56
54
  return Array.from(impacted)
57
55
  }
58
56
 
59
- /**
60
- * Check if a field exists in the schema.
61
- *
62
- * @param {string} field
63
- * @param {object} schema
64
- * @returns {boolean}
65
- */
66
- export function fieldInSchema(field, schema) {
67
- const current_schema = schema || U.SCHEMA
68
- if (typeof field !== 'string') return false
69
- const field_name = field.replace('options.', '').split('.')[0]
70
- return current_schema[field_name] !== undefined
71
- }
72
-
73
57
  /**
74
58
  * Import DOM purify, and initialize it.
75
59
  *
@@ -423,10 +407,6 @@ export class WithTemplate {
423
407
  }
424
408
  }
425
409
 
426
- export function deepEqual(object1, object2) {
410
+ export function deepEqual(object1, object2){
427
411
  return JSON.stringify(object1) === JSON.stringify(object2)
428
412
  }
429
-
430
- export function slugify(str) {
431
- return (str || 'data').replace(/[^a-z0-9]/gi, '_').toLowerCase()
432
- }
@@ -453,13 +453,17 @@ U.PermanentCreditsControl = L.Control.extend({
453
453
  },
454
454
 
455
455
  onAdd: function () {
456
- this.paragraphContainer = L.DomUtil.create(
456
+ const paragraphContainer = L.DomUtil.create(
457
457
  'div',
458
- 'umap-permanent-credits-container text'
458
+ 'umap-permanent-credits-container'
459
459
  )
460
+ const creditsParagraph = L.DomUtil.create('p', '', paragraphContainer)
461
+
462
+ this.paragraphContainer = paragraphContainer
460
463
  this.setCredits()
461
464
  this.setBackground()
462
- return this.paragraphContainer
465
+
466
+ return paragraphContainer
463
467
  },
464
468
 
465
469
  setCredits: function () {
@@ -657,36 +661,11 @@ const ControlsMixin = {
657
661
  })
658
662
  }
659
663
  button.addEventListener('click', () => {
660
- menu.openBelow(button, actions)
664
+ const x = button.offsetLeft
665
+ const y = button.offsetTop + button.offsetHeight
666
+ menu.open([x, y], actions)
661
667
  })
662
668
  }
663
-
664
- const connectedPeers = this.sync.getNumberOfConnectedPeers()
665
- if (connectedPeers !== 0) {
666
- const connectedPeersCount = L.DomUtil.createButton(
667
- 'leaflet-control-connected-peers',
668
- rightContainer,
669
- '',
670
- )
671
- L.DomEvent.on(connectedPeersCount, 'mouseover', () => {
672
- this.tooltip.open({
673
- content: L._('{connectedPeers} peer(s) currently connected to this map', {
674
- connectedPeers: connectedPeers,
675
- }),
676
- anchor: connectedPeersCount,
677
- position: 'bottom',
678
- delay: 500,
679
- duration: 5000,
680
- })
681
- })
682
-
683
- const updateConnectedPeersCount = () => {
684
- connectedPeersCount.innerHTML =
685
- '<span>' + this.sync.getNumberOfConnectedPeers() + '</span>'
686
- }
687
- updateConnectedPeersCount()
688
- }
689
-
690
669
  this.help.getStartedLink(rightContainer)
691
670
  const controlEditCancel = L.DomUtil.createButton(
692
671
  'leaflet-control-edit-cancel',