umap-project 2.4.0b2__py3-none-any.whl → 2.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.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/locale/el/LC_MESSAGES/django.po +145 -90
- umap/locale/en/LC_MESSAGES/django.po +3 -3
- umap/locale/eu/LC_MESSAGES/django.po +145 -89
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +87 -37
- umap/static/umap/base.css +20 -6
- umap/static/umap/content.css +2 -2
- umap/static/umap/css/dialog.css +1 -1
- umap/static/umap/css/importers.css +2 -0
- umap/static/umap/css/panel.css +2 -2
- umap/static/umap/css/tooltip.css +1 -1
- umap/static/umap/img/16-white.svg +1 -3
- umap/static/umap/img/source/16-white.svg +2 -4
- umap/static/umap/js/components/alerts/alert.css +1 -1
- umap/static/umap/js/components/alerts/alert.js +1 -1
- umap/static/umap/js/modules/autocomplete.js +4 -4
- umap/static/umap/js/modules/browser.js +11 -11
- umap/static/umap/js/modules/caption.js +5 -5
- umap/static/umap/js/modules/dompurify.js +2 -3
- umap/static/umap/js/modules/facets.js +16 -10
- umap/static/umap/js/modules/global.js +16 -16
- umap/static/umap/js/modules/help.js +2 -2
- umap/static/umap/js/modules/importer.js +6 -6
- umap/static/umap/js/modules/importers/geodatamine.js +4 -4
- umap/static/umap/js/modules/importers/overpass.js +2 -2
- umap/static/umap/js/modules/orderable.js +2 -2
- umap/static/umap/js/modules/request.js +1 -1
- umap/static/umap/js/modules/rules.js +13 -10
- umap/static/umap/js/modules/sync/engine.js +3 -3
- umap/static/umap/js/modules/sync/updaters.js +10 -11
- umap/static/umap/js/modules/sync/websocket.js +1 -1
- umap/static/umap/js/modules/ui/dialog.js +1 -1
- umap/static/umap/js/modules/ui/panel.js +1 -1
- umap/static/umap/js/modules/ui/tooltip.js +6 -6
- umap/static/umap/js/modules/urls.js +1 -2
- umap/static/umap/js/modules/utils.js +19 -19
- umap/static/umap/js/umap.controls.js +26 -28
- umap/static/umap/js/umap.core.js +19 -15
- umap/static/umap/js/umap.datalayer.permissions.js +15 -18
- umap/static/umap/js/umap.features.js +102 -120
- umap/static/umap/js/umap.forms.js +46 -74
- umap/static/umap/js/umap.icon.js +17 -22
- umap/static/umap/js/umap.js +126 -131
- umap/static/umap/js/umap.layer.js +159 -167
- umap/static/umap/js/umap.permissions.js +6 -9
- umap/static/umap/js/umap.popup.js +20 -20
- umap/static/umap/js/umap.share.js +9 -15
- umap/static/umap/js/umap.slideshow.js +12 -14
- umap/static/umap/js/umap.tableeditor.js +5 -5
- umap/static/umap/locale/am_ET.json +5 -2
- umap/static/umap/locale/ar.json +5 -2
- umap/static/umap/locale/ast.json +5 -2
- umap/static/umap/locale/bg.json +5 -2
- umap/static/umap/locale/br.json +5 -2
- umap/static/umap/locale/ca.json +5 -2
- umap/static/umap/locale/cs_CZ.json +5 -2
- umap/static/umap/locale/da.json +5 -2
- umap/static/umap/locale/de.json +5 -2
- umap/static/umap/locale/el.json +10 -7
- umap/static/umap/locale/en.js +2 -1
- umap/static/umap/locale/en.json +5 -2
- umap/static/umap/locale/en_US.json +5 -2
- umap/static/umap/locale/es.js +9 -8
- umap/static/umap/locale/es.json +12 -9
- umap/static/umap/locale/et.json +5 -2
- umap/static/umap/locale/fa_IR.json +5 -2
- umap/static/umap/locale/fi.json +5 -2
- umap/static/umap/locale/fr.js +2 -1
- umap/static/umap/locale/fr.json +5 -2
- umap/static/umap/locale/gl.json +5 -2
- umap/static/umap/locale/he.json +5 -2
- umap/static/umap/locale/hr.json +5 -2
- umap/static/umap/locale/hu.json +5 -2
- umap/static/umap/locale/id.json +5 -2
- umap/static/umap/locale/is.json +5 -2
- umap/static/umap/locale/it.json +5 -2
- umap/static/umap/locale/ja.json +5 -2
- umap/static/umap/locale/ko.json +5 -2
- umap/static/umap/locale/lt.json +5 -2
- umap/static/umap/locale/ms.json +5 -2
- umap/static/umap/locale/nl.json +5 -2
- umap/static/umap/locale/no.json +5 -2
- umap/static/umap/locale/pl.json +5 -2
- umap/static/umap/locale/pl_PL.json +5 -2
- umap/static/umap/locale/pt.js +61 -60
- umap/static/umap/locale/pt.json +64 -61
- umap/static/umap/locale/pt_BR.json +5 -2
- umap/static/umap/locale/pt_PT.json +5 -2
- umap/static/umap/locale/ro.json +5 -2
- umap/static/umap/locale/ru.json +5 -2
- umap/static/umap/locale/sk_SK.json +5 -2
- umap/static/umap/locale/sl.json +5 -2
- umap/static/umap/locale/sr.json +5 -2
- umap/static/umap/locale/sv.json +5 -2
- umap/static/umap/locale/th_TH.json +5 -2
- umap/static/umap/locale/tr.json +5 -2
- umap/static/umap/locale/uk_UA.json +5 -2
- umap/static/umap/locale/vi.json +5 -2
- umap/static/umap/locale/vi_VN.json +5 -2
- umap/static/umap/locale/zh.json +5 -2
- umap/static/umap/locale/zh_CN.json +5 -2
- umap/static/umap/locale/zh_TW.Big5.json +5 -2
- umap/static/umap/locale/zh_TW.json +5 -2
- umap/static/umap/map.css +22 -22
- umap/static/umap/unittests/utils.js +5 -5
- umap/static/umap/vars.css +12 -1
- umap/storage.py +1 -1
- umap/tests/integration/test_browser.py +76 -3
- umap/tests/integration/test_edit_polygon.py +11 -0
- umap/tests/integration/test_map.py +29 -0
- umap/tests/integration/test_map_preview.py +36 -2
- umap/tests/integration/test_view_marker.py +2 -2
- umap/tests/test_views.py +2 -2
- umap/views.py +3 -2
- {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/METADATA +3 -3
- {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/RECORD +120 -129
- {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/WHEEL +1 -1
- umap/.DS_Store +0 -0
- umap/static/.DS_Store +0 -0
- umap/static/umap/.DS_Store +0 -0
- umap/static/umap/favicons/.DS_Store +0 -0
- umap/static/umap/fonts/.DS_Store +0 -0
- umap/static/umap/img/.DS_Store +0 -0
- umap/static/umap/img/source/.DS_Store +0 -0
- umap/tests/.DS_Store +0 -0
- umap/tests/integration/.DS_Store +0 -0
- {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/entry_points.txt +0 -0
- {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -15,11 +15,9 @@ U.Layer = {
|
|
|
15
15
|
return this._layers
|
|
16
16
|
},
|
|
17
17
|
|
|
18
|
-
getEditableOptions:
|
|
19
|
-
return []
|
|
20
|
-
},
|
|
18
|
+
getEditableOptions: () => [],
|
|
21
19
|
|
|
22
|
-
onEdit:
|
|
20
|
+
onEdit: () => {},
|
|
23
21
|
|
|
24
22
|
hasDataVisible: function () {
|
|
25
23
|
return !!Object.keys(this._layers).length
|
|
@@ -67,11 +65,9 @@ U.Layer.Cluster = L.MarkerClusterGroup.extend({
|
|
|
67
65
|
polygonOptions: {
|
|
68
66
|
color: this.datalayer.getColor(),
|
|
69
67
|
},
|
|
70
|
-
iconCreateFunction:
|
|
71
|
-
return new U.Icon.Cluster(datalayer, cluster)
|
|
72
|
-
},
|
|
68
|
+
iconCreateFunction: (cluster) => new U.Icon.Cluster(datalayer, cluster),
|
|
73
69
|
}
|
|
74
|
-
if (this.datalayer.options.cluster
|
|
70
|
+
if (this.datalayer.options.cluster?.radius) {
|
|
75
71
|
options.maxClusterRadius = this.datalayer.options.cluster.radius
|
|
76
72
|
}
|
|
77
73
|
L.MarkerClusterGroup.prototype.initialize.call(this, options)
|
|
@@ -99,26 +95,24 @@ U.Layer.Cluster = L.MarkerClusterGroup.extend({
|
|
|
99
95
|
return L.MarkerClusterGroup.prototype.removeLayer.call(this, layer)
|
|
100
96
|
},
|
|
101
97
|
|
|
102
|
-
getEditableOptions:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
]
|
|
121
|
-
},
|
|
98
|
+
getEditableOptions: () => [
|
|
99
|
+
[
|
|
100
|
+
'options.cluster.radius',
|
|
101
|
+
{
|
|
102
|
+
handler: 'BlurIntInput',
|
|
103
|
+
placeholder: L._('Clustering radius'),
|
|
104
|
+
helpText: L._('Override clustering radius (default 80)'),
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
[
|
|
108
|
+
'options.cluster.textColor',
|
|
109
|
+
{
|
|
110
|
+
handler: 'TextColorPicker',
|
|
111
|
+
placeholder: L._('Auto'),
|
|
112
|
+
helpText: L._('Text color for the cluster label'),
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
],
|
|
122
116
|
|
|
123
117
|
onEdit: function (field, builder) {
|
|
124
118
|
if (field === 'options.cluster.radius') {
|
|
@@ -182,8 +176,8 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
|
|
|
182
176
|
getValues: function () {
|
|
183
177
|
const values = []
|
|
184
178
|
this.datalayer.eachLayer((layer) => {
|
|
185
|
-
|
|
186
|
-
if (!isNaN(value)) values.push(value)
|
|
179
|
+
const value = this._getValue(layer)
|
|
180
|
+
if (!Number.isNaN(value)) values.push(value)
|
|
187
181
|
})
|
|
188
182
|
return values
|
|
189
183
|
},
|
|
@@ -196,9 +190,9 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
|
|
|
196
190
|
this.options.colors = []
|
|
197
191
|
return
|
|
198
192
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
193
|
+
const mode = this.datalayer.options.choropleth.mode
|
|
194
|
+
let classes = +this.datalayer.options.choropleth.classes || 5
|
|
195
|
+
let breaks
|
|
202
196
|
classes = Math.min(classes, values.length)
|
|
203
197
|
if (mode === 'manual') {
|
|
204
198
|
const manualBreaks = this.datalayer.options.choropleth.breaks
|
|
@@ -206,7 +200,7 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
|
|
|
206
200
|
breaks = manualBreaks
|
|
207
201
|
.split(',')
|
|
208
202
|
.map((b) => +b)
|
|
209
|
-
.filter((b) => !isNaN(b))
|
|
203
|
+
.filter((b) => !Number.isNaN(b))
|
|
210
204
|
}
|
|
211
205
|
} else if (mode === 'equidistant') {
|
|
212
206
|
breaks = ss.equalIntervalBreaks(values, classes)
|
|
@@ -249,7 +243,7 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
|
|
|
249
243
|
addLayer: function (layer) {
|
|
250
244
|
// Do not add yet the layer to the map
|
|
251
245
|
// wait for datachanged event, so we want compute breaks once
|
|
252
|
-
|
|
246
|
+
const id = this.getLayerId(layer)
|
|
253
247
|
this._layers[id] = layer
|
|
254
248
|
return this
|
|
255
249
|
},
|
|
@@ -332,7 +326,9 @@ U.Layer.Choropleth = L.FeatureGroup.extend({
|
|
|
332
326
|
|
|
333
327
|
renderLegend: function (container) {
|
|
334
328
|
const parent = L.DomUtil.create('ul', '', container)
|
|
335
|
-
let li
|
|
329
|
+
let li
|
|
330
|
+
let color
|
|
331
|
+
let label
|
|
336
332
|
|
|
337
333
|
this.options.breaks.slice(0, -1).forEach((limit, index) => {
|
|
338
334
|
li = L.DomUtil.create('li', '', parent)
|
|
@@ -364,13 +360,10 @@ U.Layer.Heat = L.HeatLayer.extend({
|
|
|
364
360
|
|
|
365
361
|
addLayer: function (layer) {
|
|
366
362
|
if (layer instanceof L.Marker) {
|
|
367
|
-
let latlng = layer.getLatLng()
|
|
368
|
-
|
|
369
|
-
if (
|
|
370
|
-
|
|
371
|
-
this.datalayer.options.heat.intensityProperty
|
|
372
|
-
) {
|
|
373
|
-
alt = parseFloat(
|
|
363
|
+
let latlng = layer.getLatLng()
|
|
364
|
+
let alt
|
|
365
|
+
if (this.datalayer.options.heat?.intensityProperty) {
|
|
366
|
+
alt = Number.parseFloat(
|
|
374
367
|
layer.properties[this.datalayer.options.heat.intensityProperty || 0]
|
|
375
368
|
)
|
|
376
369
|
latlng = new L.LatLng(latlng.lat, latlng.lng, alt)
|
|
@@ -383,37 +376,33 @@ U.Layer.Heat = L.HeatLayer.extend({
|
|
|
383
376
|
this.setLatLngs([])
|
|
384
377
|
},
|
|
385
378
|
|
|
386
|
-
getFeatures:
|
|
387
|
-
return {}
|
|
388
|
-
},
|
|
379
|
+
getFeatures: () => ({}),
|
|
389
380
|
|
|
390
381
|
getBounds: function () {
|
|
391
382
|
return L.latLngBounds(this._latlngs)
|
|
392
383
|
},
|
|
393
384
|
|
|
394
|
-
getEditableOptions:
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
]
|
|
416
|
-
},
|
|
385
|
+
getEditableOptions: () => [
|
|
386
|
+
[
|
|
387
|
+
'options.heat.radius',
|
|
388
|
+
{
|
|
389
|
+
handler: 'Range',
|
|
390
|
+
min: 10,
|
|
391
|
+
max: 100,
|
|
392
|
+
step: 5,
|
|
393
|
+
label: L._('Heatmap radius'),
|
|
394
|
+
helpText: L._('Override heatmap radius (default 25)'),
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
[
|
|
398
|
+
'options.heat.intensityProperty',
|
|
399
|
+
{
|
|
400
|
+
handler: 'BlurInput',
|
|
401
|
+
placeholder: L._('Heatmap intensity property'),
|
|
402
|
+
helpText: L._('Optional intensity property for heatmap'),
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
],
|
|
417
406
|
|
|
418
407
|
onEdit: function (field, builder) {
|
|
419
408
|
if (field === 'options.heat.intensityProperty') {
|
|
@@ -440,23 +429,23 @@ U.Layer.Heat = L.HeatLayer.extend({
|
|
|
440
429
|
if (!this._map) {
|
|
441
430
|
return
|
|
442
431
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
432
|
+
const data = []
|
|
433
|
+
const r = this._heat._r
|
|
434
|
+
const size = this._map.getSize()
|
|
435
|
+
const bounds = new L.Bounds(L.point([-r, -r]), size.add([r, r]))
|
|
436
|
+
const cellSize = r / 2
|
|
437
|
+
const grid = []
|
|
438
|
+
const panePos = this._map._getMapPanePos()
|
|
439
|
+
const offsetX = panePos.x % cellSize
|
|
440
|
+
const offsetY = panePos.y % cellSize
|
|
441
|
+
let i
|
|
442
|
+
let len
|
|
443
|
+
let p
|
|
444
|
+
let cell
|
|
445
|
+
let x
|
|
446
|
+
let y
|
|
447
|
+
let j
|
|
448
|
+
let len2
|
|
460
449
|
|
|
461
450
|
this._max = 1
|
|
462
451
|
|
|
@@ -465,7 +454,7 @@ U.Layer.Heat = L.HeatLayer.extend({
|
|
|
465
454
|
x = Math.floor((p.x - offsetX) / cellSize) + 2
|
|
466
455
|
y = Math.floor((p.y - offsetY) / cellSize) + 2
|
|
467
456
|
|
|
468
|
-
|
|
457
|
+
const alt =
|
|
469
458
|
this._latlngs[i].alt !== undefined
|
|
470
459
|
? this._latlngs[i].alt
|
|
471
460
|
: this._latlngs[i][2] !== undefined
|
|
@@ -538,23 +527,20 @@ U.DataLayer = L.Evented.extend({
|
|
|
538
527
|
|
|
539
528
|
let isDirty = false
|
|
540
529
|
let isDeleted = false
|
|
541
|
-
const self = this
|
|
542
530
|
try {
|
|
543
531
|
Object.defineProperty(this, 'isDirty', {
|
|
544
|
-
get:
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
set: function (status) {
|
|
548
|
-
if (!isDirty && status) self.fire('dirty')
|
|
532
|
+
get: () => isDirty,
|
|
533
|
+
set: (status) => {
|
|
534
|
+
if (!isDirty && status) this.fire('dirty')
|
|
549
535
|
isDirty = status
|
|
550
536
|
if (status) {
|
|
551
|
-
|
|
537
|
+
this.map.addDirtyDatalayer(this)
|
|
552
538
|
// A layer can be made dirty by indirect action (like dragging layers)
|
|
553
539
|
// we need to have it loaded before saving it.
|
|
554
|
-
if (!
|
|
540
|
+
if (!this.isLoaded()) this.fetchData()
|
|
555
541
|
} else {
|
|
556
|
-
|
|
557
|
-
|
|
542
|
+
this.map.removeDirtyDatalayer(this)
|
|
543
|
+
this.isDeleted = false
|
|
558
544
|
}
|
|
559
545
|
},
|
|
560
546
|
})
|
|
@@ -563,13 +549,11 @@ U.DataLayer = L.Evented.extend({
|
|
|
563
549
|
}
|
|
564
550
|
try {
|
|
565
551
|
Object.defineProperty(this, 'isDeleted', {
|
|
566
|
-
get:
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
set: function (status) {
|
|
570
|
-
if (!isDeleted && status) self.fire('deleted')
|
|
552
|
+
get: () => isDeleted,
|
|
553
|
+
set: (status) => {
|
|
554
|
+
if (!isDeleted && status) this.fire('deleted')
|
|
571
555
|
isDeleted = status
|
|
572
|
-
if (status)
|
|
556
|
+
if (status) this.isDirty = status
|
|
573
557
|
},
|
|
574
558
|
})
|
|
575
559
|
} catch (e) {
|
|
@@ -582,11 +566,11 @@ U.DataLayer = L.Evented.extend({
|
|
|
582
566
|
this.options.remoteData = {}
|
|
583
567
|
}
|
|
584
568
|
// Retrocompat
|
|
585
|
-
if (this.options.remoteData
|
|
569
|
+
if (this.options.remoteData?.from) {
|
|
586
570
|
this.options.fromZoom = this.options.remoteData.from
|
|
587
571
|
delete this.options.remoteData.from
|
|
588
572
|
}
|
|
589
|
-
if (this.options.remoteData
|
|
573
|
+
if (this.options.remoteData?.to) {
|
|
590
574
|
this.options.toZoom = this.options.remoteData.to
|
|
591
575
|
delete this.options.remoteData.to
|
|
592
576
|
}
|
|
@@ -618,9 +602,9 @@ U.DataLayer = L.Evented.extend({
|
|
|
618
602
|
},
|
|
619
603
|
|
|
620
604
|
render: function (fields, builder) {
|
|
621
|
-
|
|
605
|
+
const impacts = U.Utils.getImpactsFromSchema(fields)
|
|
622
606
|
|
|
623
|
-
for (
|
|
607
|
+
for (const impact of impacts) {
|
|
624
608
|
switch (impact) {
|
|
625
609
|
case 'ui':
|
|
626
610
|
this.map.onDataLayersChanged()
|
|
@@ -745,8 +729,8 @@ U.DataLayer = L.Evented.extend({
|
|
|
745
729
|
}
|
|
746
730
|
},
|
|
747
731
|
|
|
748
|
-
fromGeoJSON: function (geojson) {
|
|
749
|
-
this.addData(geojson)
|
|
732
|
+
fromGeoJSON: function (geojson, sync = true) {
|
|
733
|
+
this.addData(geojson, sync)
|
|
750
734
|
this._geojson = geojson
|
|
751
735
|
this._dataloaded = true
|
|
752
736
|
this.fire('dataloaded')
|
|
@@ -757,7 +741,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
757
741
|
if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat
|
|
758
742
|
if (geojson._umap_options) this.setOptions(geojson._umap_options)
|
|
759
743
|
if (this.isRemoteLayer()) await this.fetchRemoteData()
|
|
760
|
-
else this.fromGeoJSON(geojson)
|
|
744
|
+
else this.fromGeoJSON(geojson, false)
|
|
761
745
|
this._loaded = true
|
|
762
746
|
},
|
|
763
747
|
|
|
@@ -787,14 +771,14 @@ U.DataLayer = L.Evented.extend({
|
|
|
787
771
|
},
|
|
788
772
|
|
|
789
773
|
showAtZoom: function () {
|
|
790
|
-
const from = parseInt(this.options.fromZoom, 10)
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
return !((!isNaN(from) && zoom < from) || (!isNaN(to) && zoom > to))
|
|
774
|
+
const from = Number.parseInt(this.options.fromZoom, 10)
|
|
775
|
+
const to = Number.parseInt(this.options.toZoom, 10)
|
|
776
|
+
const zoom = this.map.getZoom()
|
|
777
|
+
return !((!Number.isNaN(from) && zoom < from) || (!Number.isNaN(to) && zoom > to))
|
|
794
778
|
},
|
|
795
779
|
|
|
796
780
|
hasDynamicData: function () {
|
|
797
|
-
return !!
|
|
781
|
+
return !!this.options.remoteData?.dynamic
|
|
798
782
|
},
|
|
799
783
|
|
|
800
784
|
fetchRemoteData: async function (force) {
|
|
@@ -806,7 +790,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
806
790
|
url = this.map.proxyUrl(url, this.options.remoteData.ttl)
|
|
807
791
|
}
|
|
808
792
|
const response = await this.map.request.get(url)
|
|
809
|
-
if (response
|
|
793
|
+
if (response?.ok) {
|
|
810
794
|
this.clear()
|
|
811
795
|
this.rawToGeoJSON(
|
|
812
796
|
await response.text(),
|
|
@@ -884,11 +868,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
884
868
|
},
|
|
885
869
|
|
|
886
870
|
isRemoteLayer: function () {
|
|
887
|
-
return Boolean(
|
|
888
|
-
this.options.remoteData &&
|
|
889
|
-
this.options.remoteData.url &&
|
|
890
|
-
this.options.remoteData.format
|
|
891
|
-
)
|
|
871
|
+
return Boolean(this.options.remoteData?.url && this.options.remoteData.format)
|
|
892
872
|
},
|
|
893
873
|
|
|
894
874
|
isClustered: function () {
|
|
@@ -911,12 +891,13 @@ U.DataLayer = L.Evented.extend({
|
|
|
911
891
|
if (this.hasDataLoaded()) this.fire('datachanged')
|
|
912
892
|
},
|
|
913
893
|
|
|
914
|
-
removeLayer: function (feature) {
|
|
894
|
+
removeLayer: function (feature, sync) {
|
|
915
895
|
const id = L.stamp(feature)
|
|
896
|
+
if (sync !== false) feature.sync.delete()
|
|
897
|
+
this.layer.removeLayer(feature)
|
|
916
898
|
feature.disconnectFromDataLayer(this)
|
|
917
899
|
this._index.splice(this._index.indexOf(id), 1)
|
|
918
900
|
delete this._layers[id]
|
|
919
|
-
this.layer.removeLayer(feature)
|
|
920
901
|
delete this.map.features_index[feature.getSlug()]
|
|
921
902
|
if (this.hasDataLoaded()) this.fire('datachanged')
|
|
922
903
|
},
|
|
@@ -938,11 +919,11 @@ U.DataLayer = L.Evented.extend({
|
|
|
938
919
|
if (idx !== -1) this._propertiesIndex.splice(idx, 1)
|
|
939
920
|
},
|
|
940
921
|
|
|
941
|
-
addData: function (geojson) {
|
|
922
|
+
addData: function (geojson, sync) {
|
|
942
923
|
try {
|
|
943
924
|
// Do not fail if remote data is somehow invalid,
|
|
944
925
|
// otherwise the layer becomes uneditable.
|
|
945
|
-
this.geojsonToFeatures(geojson)
|
|
926
|
+
this.geojsonToFeatures(geojson, sync)
|
|
946
927
|
} catch (err) {
|
|
947
928
|
console.log('Error with DataLayer', this.umap_id)
|
|
948
929
|
console.error(err)
|
|
@@ -953,7 +934,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
953
934
|
this.rawToGeoJSON(c, type, (geojson) => this.addData(geojson))
|
|
954
935
|
},
|
|
955
936
|
|
|
956
|
-
rawToGeoJSON:
|
|
937
|
+
rawToGeoJSON: (c, type, callback) => {
|
|
957
938
|
const toDom = (x) => {
|
|
958
939
|
const doc = new DOMParser().parseFromString(x, 'text/xml')
|
|
959
940
|
const errorNode = doc.querySelector('parsererror')
|
|
@@ -975,7 +956,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
975
956
|
// csv2geojson fallback to null geometries when it cannot determine
|
|
976
957
|
// lat or lon columns. This is valid geojson, but unwanted from a user
|
|
977
958
|
// point of view.
|
|
978
|
-
if (result
|
|
959
|
+
if (result?.features.length) {
|
|
979
960
|
if (result.features[0].geometry === null) {
|
|
980
961
|
err = {
|
|
981
962
|
type: 'Error',
|
|
@@ -996,7 +977,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
996
977
|
U.Alert.error(message, 10000)
|
|
997
978
|
console.error(err)
|
|
998
979
|
}
|
|
999
|
-
if (result
|
|
980
|
+
if (result?.features.length) {
|
|
1000
981
|
callback(result)
|
|
1001
982
|
}
|
|
1002
983
|
}
|
|
@@ -1029,9 +1010,9 @@ U.DataLayer = L.Evented.extend({
|
|
|
1029
1010
|
// The choice of the name is not ours, because it is required by Leaflet.
|
|
1030
1011
|
// It is misleading, as the returned objects are uMap objects, and not
|
|
1031
1012
|
// GeoJSON features.
|
|
1032
|
-
geojsonToFeatures: function (geojson) {
|
|
1013
|
+
geojsonToFeatures: function (geojson, sync) {
|
|
1033
1014
|
if (!geojson) return
|
|
1034
|
-
const features = geojson
|
|
1015
|
+
const features = Array.isArray(geojson) ? geojson : geojson.features
|
|
1035
1016
|
let i
|
|
1036
1017
|
let len
|
|
1037
1018
|
|
|
@@ -1045,10 +1026,10 @@ U.DataLayer = L.Evented.extend({
|
|
|
1045
1026
|
|
|
1046
1027
|
const geometry = geojson.type === 'Feature' ? geojson.geometry : geojson
|
|
1047
1028
|
|
|
1048
|
-
|
|
1029
|
+
const feature = this.geoJSONToLeaflet({ geometry, geojson })
|
|
1049
1030
|
if (feature) {
|
|
1050
1031
|
this.addLayer(feature)
|
|
1051
|
-
feature.onCommit()
|
|
1032
|
+
if (sync) feature.onCommit()
|
|
1052
1033
|
return feature
|
|
1053
1034
|
}
|
|
1054
1035
|
},
|
|
@@ -1077,7 +1058,8 @@ U.DataLayer = L.Evented.extend({
|
|
|
1077
1058
|
} = {}) {
|
|
1078
1059
|
if (!geometry) return // null geometry is valid geojson.
|
|
1079
1060
|
const coords = geometry.coordinates
|
|
1080
|
-
let latlng
|
|
1061
|
+
let latlng
|
|
1062
|
+
let latlngs
|
|
1081
1063
|
|
|
1082
1064
|
// Create a default geojson if none is provided
|
|
1083
1065
|
if (geojson === undefined) geojson = { type: 'Feature', geometry: geometry }
|
|
@@ -1176,7 +1158,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
1176
1158
|
importFromUrl: async function (uri, type) {
|
|
1177
1159
|
uri = this.map.localizeUrl(uri)
|
|
1178
1160
|
const response = await this.map.request.get(uri)
|
|
1179
|
-
if (response
|
|
1161
|
+
if (response?.ok) {
|
|
1180
1162
|
this.importRaw(await response.text(), type)
|
|
1181
1163
|
}
|
|
1182
1164
|
},
|
|
@@ -1222,8 +1204,8 @@ U.DataLayer = L.Evented.extend({
|
|
|
1222
1204
|
const options = U.Utils.CopyJSON(this.options)
|
|
1223
1205
|
options.name = L._('Clone of {name}', { name: this.options.name })
|
|
1224
1206
|
delete options.id
|
|
1225
|
-
const geojson = U.Utils.CopyJSON(this._geojson)
|
|
1226
|
-
|
|
1207
|
+
const geojson = U.Utils.CopyJSON(this._geojson)
|
|
1208
|
+
const datalayer = this.map.createDataLayer(options)
|
|
1227
1209
|
datalayer.fromGeoJSON(geojson)
|
|
1228
1210
|
return datalayer
|
|
1229
1211
|
},
|
|
@@ -1272,28 +1254,28 @@ U.DataLayer = L.Evented.extend({
|
|
|
1272
1254
|
if (!this.map.editEnabled || !this.isLoaded()) {
|
|
1273
1255
|
return
|
|
1274
1256
|
}
|
|
1275
|
-
const container = L.DomUtil.create('div', 'umap-layer-properties-container')
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1257
|
+
const container = L.DomUtil.create('div', 'umap-layer-properties-container')
|
|
1258
|
+
const metadataFields = [
|
|
1259
|
+
'options.name',
|
|
1260
|
+
'options.description',
|
|
1261
|
+
['options.type', { handler: 'LayerTypeChooser', label: L._('Type of layer') }],
|
|
1262
|
+
['options.displayOnLoad', { label: L._('Display on load'), handler: 'Switch' }],
|
|
1263
|
+
[
|
|
1264
|
+
'options.browsable',
|
|
1265
|
+
{
|
|
1266
|
+
label: L._('Data is browsable'),
|
|
1267
|
+
handler: 'Switch',
|
|
1268
|
+
helpEntries: 'browsable',
|
|
1269
|
+
},
|
|
1270
|
+
],
|
|
1271
|
+
[
|
|
1272
|
+
'options.inCaption',
|
|
1273
|
+
{
|
|
1274
|
+
label: L._('Show this layer in the caption'),
|
|
1275
|
+
handler: 'Switch',
|
|
1276
|
+
},
|
|
1277
|
+
],
|
|
1278
|
+
]
|
|
1297
1279
|
L.DomUtil.createTitle(container, L._('Layer properties'), 'icon-layers')
|
|
1298
1280
|
let builder = new U.FormBuilder(this, metadataFields, {
|
|
1299
1281
|
callback: function (e) {
|
|
@@ -1318,7 +1300,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
1318
1300
|
layerProperties.appendChild(builder.build())
|
|
1319
1301
|
}
|
|
1320
1302
|
|
|
1321
|
-
|
|
1303
|
+
const shapeOptions = [
|
|
1322
1304
|
'options.color',
|
|
1323
1305
|
'options.iconClass',
|
|
1324
1306
|
'options.iconUrl',
|
|
@@ -1337,7 +1319,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
1337
1319
|
const shapeProperties = L.DomUtil.createFieldset(container, L._('Shape properties'))
|
|
1338
1320
|
shapeProperties.appendChild(builder.build())
|
|
1339
1321
|
|
|
1340
|
-
|
|
1322
|
+
const optionsFields = [
|
|
1341
1323
|
'options.smoothFactor',
|
|
1342
1324
|
'options.dashArray',
|
|
1343
1325
|
'options.zoomTo',
|
|
@@ -1484,23 +1466,23 @@ U.DataLayer = L.Evented.extend({
|
|
|
1484
1466
|
},
|
|
1485
1467
|
|
|
1486
1468
|
getOption: function (option, feature) {
|
|
1487
|
-
if (this.layer
|
|
1469
|
+
if (this.layer?.getOption) {
|
|
1488
1470
|
const value = this.layer.getOption(option, feature)
|
|
1489
1471
|
if (typeof value !== 'undefined') return value
|
|
1490
1472
|
}
|
|
1491
1473
|
if (typeof this.getOwnOption(option) !== 'undefined') {
|
|
1492
1474
|
return this.getOwnOption(option)
|
|
1493
|
-
}
|
|
1475
|
+
}
|
|
1476
|
+
if (this.layer?.defaults?.[option]) {
|
|
1494
1477
|
return this.layer.defaults[option]
|
|
1495
|
-
} else {
|
|
1496
|
-
return this.map.getOption(option, feature)
|
|
1497
1478
|
}
|
|
1479
|
+
return this.map.getOption(option, feature)
|
|
1498
1480
|
},
|
|
1499
1481
|
|
|
1500
1482
|
buildVersionsFieldset: async function (container) {
|
|
1501
1483
|
const appendVersion = (data) => {
|
|
1502
|
-
const date = new Date(parseInt(data.at, 10))
|
|
1503
|
-
const content = `${date.toLocaleString(L.lang)} (${parseInt(data.size) / 1000}Kb)`
|
|
1484
|
+
const date = new Date(Number.parseInt(data.at, 10))
|
|
1485
|
+
const content = `${date.toLocaleString(L.lang)} (${Number.parseInt(data.size) / 1000}Kb)`
|
|
1504
1486
|
const el = L.DomUtil.create('div', 'umap-datalayer-version', versionsContainer)
|
|
1505
1487
|
const button = L.DomUtil.createButton(
|
|
1506
1488
|
'',
|
|
@@ -1576,7 +1558,7 @@ U.DataLayer = L.Evented.extend({
|
|
|
1576
1558
|
|
|
1577
1559
|
// Is this layer type browsable in theorie
|
|
1578
1560
|
isBrowsable: function () {
|
|
1579
|
-
return this.layer
|
|
1561
|
+
return this.layer?.browsable
|
|
1580
1562
|
},
|
|
1581
1563
|
|
|
1582
1564
|
// Is this layer browsable in theorie
|
|
@@ -1757,6 +1739,16 @@ U.DataLayer = L.Evented.extend({
|
|
|
1757
1739
|
const editor = new U.TableEditor(this)
|
|
1758
1740
|
editor.edit()
|
|
1759
1741
|
},
|
|
1742
|
+
|
|
1743
|
+
getFilterKeys: function () {
|
|
1744
|
+
// This keys will be used to filter feature from the browser text input.
|
|
1745
|
+
// By default, it will we use the "name" property, which is also the one used as label in the features list.
|
|
1746
|
+
// When map owner has configured another label or sort key, we try to be smart and search in the same keys.
|
|
1747
|
+
if (this.map.options.filterKey) return this.map.options.filterKey
|
|
1748
|
+
if (this.options.labelKey) return this.options.labelKey
|
|
1749
|
+
if (this.map.options.sortKey) return this.map.options.sortKey
|
|
1750
|
+
return 'name'
|
|
1751
|
+
},
|
|
1760
1752
|
})
|
|
1761
1753
|
|
|
1762
1754
|
L.TileLayer.include({
|
|
@@ -12,16 +12,13 @@ U.MapPermissions = L.Class.extend({
|
|
|
12
12
|
this.setOptions(map.options.permissions)
|
|
13
13
|
this.map = map
|
|
14
14
|
let isDirty = false
|
|
15
|
-
const self = this
|
|
16
15
|
try {
|
|
17
16
|
Object.defineProperty(this, 'isDirty', {
|
|
18
|
-
get:
|
|
19
|
-
|
|
20
|
-
},
|
|
21
|
-
set: function (status) {
|
|
17
|
+
get: () => isDirty,
|
|
18
|
+
set: (status) => {
|
|
22
19
|
isDirty = status
|
|
23
20
|
if (status) {
|
|
24
|
-
|
|
21
|
+
this.map.isDirty = status
|
|
25
22
|
}
|
|
26
23
|
},
|
|
27
24
|
})
|
|
@@ -38,7 +35,7 @@ U.MapPermissions = L.Class.extend({
|
|
|
38
35
|
return (
|
|
39
36
|
this.map.options.user &&
|
|
40
37
|
this.map.options.permissions.owner &&
|
|
41
|
-
this.map.options.user.id
|
|
38
|
+
this.map.options.user.id === this.map.options.permissions.owner.id
|
|
42
39
|
)
|
|
43
40
|
},
|
|
44
41
|
|
|
@@ -154,7 +151,7 @@ U.MapPermissions = L.Class.extend({
|
|
|
154
151
|
if (this.isOwner() || this.isAnonymousMap())
|
|
155
152
|
formData.append('edit_status', this.options.edit_status)
|
|
156
153
|
if (this.isOwner()) {
|
|
157
|
-
formData.append('owner', this.options.owner
|
|
154
|
+
formData.append('owner', this.options.owner?.id)
|
|
158
155
|
formData.append('share_status', this.options.share_status)
|
|
159
156
|
}
|
|
160
157
|
const [data, response, error] = await this.map.server.post(
|
|
@@ -183,7 +180,7 @@ U.MapPermissions = L.Class.extend({
|
|
|
183
180
|
},
|
|
184
181
|
|
|
185
182
|
addOwnerLink: function (element, container) {
|
|
186
|
-
if (this.options.owner
|
|
183
|
+
if (this.options.owner?.name && this.options.owner.url) {
|
|
187
184
|
const ownerContainer = L.DomUtil.add(
|
|
188
185
|
element,
|
|
189
186
|
'umap-map-owner',
|